mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-30 12:43:41 +01:00
7c0aa811ec
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
856 lines
32 KiB
C
856 lines
32 KiB
C
/** @file
|
|
Legacy Region Support
|
|
|
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
|
|
|
This program and the accompanying materials are
|
|
licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
Modified by dmazar with support for different chipsets and added newer ones.
|
|
|
|
**/
|
|
/* Part of codes comes from
|
|
*
|
|
* memtest86
|
|
*
|
|
* Released under version 2 of the Gnu Public License.
|
|
* By Chris Brady, cbrady@sgi.com
|
|
* ----------------------------------------------------
|
|
* MemTest86+ V4.00 Specific code (GPL V2.0)
|
|
* By Samuel DEMEULEMEESTER, sdemeule@memtest.org
|
|
* http://www.canardpc.com - http://www.memtest.org
|
|
*/
|
|
|
|
|
|
#include "LegacyRegion2.h"
|
|
|
|
#define DEBUG_LR 1
|
|
|
|
#if DEBUG_LR == 1
|
|
#define DBG(...) MemLog(TRUE, 1, __VA_ARGS__)
|
|
#else
|
|
#define DBG(...)
|
|
#endif
|
|
|
|
//
|
|
// Current chipset's tables
|
|
//
|
|
UINT32 mVendorDeviceId = 0;
|
|
STATIC PAM_REGISTER_VALUE *mRegisterValues = NULL;
|
|
UINT8 mPamPciBus = 0;
|
|
UINT8 mPamPciDev = 0;
|
|
UINT8 mPamPciFunc = 0;
|
|
|
|
//
|
|
// Intel 830 Chipset and similar
|
|
//
|
|
|
|
//
|
|
// 440 PAM map.
|
|
//
|
|
// PAM Range Offset Bits Operation
|
|
// =============== ====== ==== ===============================================================
|
|
// 0xC0000-0xC3FFF 0x5a 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xC4000-0xC7FFF 0x5a 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xC8000-0xCBFFF 0x5b 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xCC000-0xCFFFF 0x5b 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD0000-0xD3FFF 0x5c 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD4000-0xD7FFF 0x5c 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD8000-0xDBFFF 0x5d 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xDC000-0xDFFFF 0x5d 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE0000-0xE3FFF 0x5e 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE4000-0xE7FFF 0x5e 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE8000-0xEBFFF 0x5f 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xEC000-0xEFFFF 0x5f 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xF0000-0xFFFFF 0x59 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
//
|
|
STATIC LEGACY_MEMORY_SECTION_INFO mSectionArray[] = {
|
|
{0xC0000, SIZE_16KB, FALSE, FALSE},
|
|
{0xC4000, SIZE_16KB, FALSE, FALSE},
|
|
{0xC8000, SIZE_16KB, FALSE, FALSE},
|
|
{0xCC000, SIZE_16KB, FALSE, FALSE},
|
|
{0xD0000, SIZE_16KB, FALSE, FALSE},
|
|
{0xD4000, SIZE_16KB, FALSE, FALSE},
|
|
{0xD8000, SIZE_16KB, FALSE, FALSE},
|
|
{0xDC000, SIZE_16KB, FALSE, FALSE},
|
|
{0xE0000, SIZE_16KB, FALSE, FALSE},
|
|
{0xE4000, SIZE_16KB, FALSE, FALSE},
|
|
{0xE8000, SIZE_16KB, FALSE, FALSE},
|
|
{0xEC000, SIZE_16KB, FALSE, FALSE},
|
|
{0xF0000, SIZE_64KB, FALSE, FALSE}
|
|
};
|
|
|
|
STATIC PAM_REGISTER_VALUE mRegisterValues830[] = {
|
|
{REG_PAM1_OFFSET_830, 0x01, 0x02},
|
|
{REG_PAM1_OFFSET_830, 0x10, 0x20},
|
|
{REG_PAM2_OFFSET_830, 0x01, 0x02},
|
|
{REG_PAM2_OFFSET_830, 0x10, 0x20},
|
|
{REG_PAM3_OFFSET_830, 0x01, 0x02},
|
|
{REG_PAM3_OFFSET_830, 0x10, 0x20},
|
|
{REG_PAM4_OFFSET_830, 0x01, 0x02},
|
|
{REG_PAM4_OFFSET_830, 0x10, 0x20},
|
|
{REG_PAM5_OFFSET_830, 0x01, 0x02},
|
|
{REG_PAM5_OFFSET_830, 0x10, 0x20},
|
|
{REG_PAM6_OFFSET_830, 0x01, 0x02},
|
|
{REG_PAM6_OFFSET_830, 0x10, 0x20},
|
|
{REG_PAM0_OFFSET_830, 0x10, 0x20}
|
|
};
|
|
|
|
|
|
//
|
|
// Intel 4 Series Chipset and similar
|
|
//
|
|
|
|
//
|
|
// PAM map.
|
|
//
|
|
// PAM Range Offset Bits Operation
|
|
// =============== ====== ==== ===============================================================
|
|
// 0xC0000-0xC3FFF 0x91 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xC4000-0xC7FFF 0x91 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xC8000-0xCBFFF 0x92 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xCC000-0xCFFFF 0x92 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD0000-0xD3FFF 0x93 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD4000-0xD7FFF 0x93 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD8000-0xDBFFF 0x94 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xDC000-0xDFFFF 0x94 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE0000-0xE3FFF 0x95 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE4000-0xE7FFF 0x95 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE8000-0xEBFFF 0x96 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xEC000-0xEFFFF 0x96 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xF0000-0xFFFFF 0x90 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
//
|
|
|
|
STATIC PAM_REGISTER_VALUE mRegisterValuesS4[] = {
|
|
{REG_PAM1_OFFSET_S4, 0x01, 0x02},
|
|
{REG_PAM1_OFFSET_S4, 0x10, 0x20},
|
|
{REG_PAM2_OFFSET_S4, 0x01, 0x02},
|
|
{REG_PAM2_OFFSET_S4, 0x10, 0x20},
|
|
{REG_PAM3_OFFSET_S4, 0x01, 0x02},
|
|
{REG_PAM3_OFFSET_S4, 0x10, 0x20},
|
|
{REG_PAM4_OFFSET_S4, 0x01, 0x02},
|
|
{REG_PAM4_OFFSET_S4, 0x10, 0x20},
|
|
{REG_PAM5_OFFSET_S4, 0x01, 0x02},
|
|
{REG_PAM5_OFFSET_S4, 0x10, 0x20},
|
|
{REG_PAM6_OFFSET_S4, 0x01, 0x02},
|
|
{REG_PAM6_OFFSET_S4, 0x10, 0x20},
|
|
{REG_PAM0_OFFSET_S4, 0x10, 0x20}
|
|
};
|
|
|
|
//
|
|
// Core processors
|
|
//
|
|
|
|
//
|
|
// PAM map.
|
|
//
|
|
// PAM Range Offset Bits Operation
|
|
// =============== ====== ==== ===============================================================
|
|
// 0xC0000-0xC3FFF 0x81 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xC4000-0xC7FFF 0x81 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xC8000-0xCBFFF 0x82 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xCC000-0xCFFFF 0x82 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD0000-0xD3FFF 0x83 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD4000-0xD7FFF 0x83 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xD8000-0xDBFFF 0x84 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xDC000-0xDFFFF 0x84 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE0000-0xE3FFF 0x85 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE4000-0xE7FFF 0x85 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xE8000-0xEBFFF 0x86 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xEC000-0xEFFFF 0x86 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
// 0xF0000-0xFFFFF 0x80 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
|
|
//
|
|
|
|
STATIC PAM_REGISTER_VALUE mRegisterValuesCP[] = {
|
|
{REG_PAM1_OFFSET_CP, 0x01, 0x02},
|
|
{REG_PAM1_OFFSET_CP, 0x10, 0x20},
|
|
{REG_PAM2_OFFSET_CP, 0x01, 0x02},
|
|
{REG_PAM2_OFFSET_CP, 0x10, 0x20},
|
|
{REG_PAM3_OFFSET_CP, 0x01, 0x02},
|
|
{REG_PAM3_OFFSET_CP, 0x10, 0x20},
|
|
{REG_PAM4_OFFSET_CP, 0x01, 0x02},
|
|
{REG_PAM4_OFFSET_CP, 0x10, 0x20},
|
|
{REG_PAM5_OFFSET_CP, 0x01, 0x02},
|
|
{REG_PAM5_OFFSET_CP, 0x10, 0x20},
|
|
{REG_PAM6_OFFSET_CP, 0x01, 0x02},
|
|
{REG_PAM6_OFFSET_CP, 0x10, 0x20},
|
|
{REG_PAM0_OFFSET_CP, 0x10, 0x20}
|
|
};
|
|
|
|
STATIC PAM_REGISTER_VALUE mRegisterValuesNH[] = {
|
|
{REG_PAM1_OFFSET_NH, 0x01, 0x02},
|
|
{REG_PAM1_OFFSET_NH, 0x10, 0x20},
|
|
{REG_PAM2_OFFSET_NH, 0x01, 0x02},
|
|
{REG_PAM2_OFFSET_NH, 0x10, 0x20},
|
|
{REG_PAM3_OFFSET_NH, 0x01, 0x02},
|
|
{REG_PAM3_OFFSET_NH, 0x10, 0x20},
|
|
{REG_PAM4_OFFSET_NH, 0x01, 0x02},
|
|
{REG_PAM4_OFFSET_NH, 0x10, 0x20},
|
|
{REG_PAM5_OFFSET_NH, 0x01, 0x02},
|
|
{REG_PAM5_OFFSET_NH, 0x10, 0x20},
|
|
{REG_PAM6_OFFSET_NH, 0x01, 0x02},
|
|
{REG_PAM6_OFFSET_NH, 0x10, 0x20},
|
|
{REG_PAM0_OFFSET_NH, 0x10, 0x20}
|
|
};
|
|
|
|
//NForce chipset
|
|
|
|
STATIC PAM_REGISTER_VALUE mRegisterValuesNV[] = {
|
|
{REG_PAM1_OFFSET_NV, 0x01, 0x02},
|
|
{REG_PAM1_OFFSET_NV, 0x10, 0x20},
|
|
{REG_PAM2_OFFSET_NV, 0x01, 0x02},
|
|
{REG_PAM2_OFFSET_NV, 0x10, 0x20},
|
|
{REG_PAM3_OFFSET_NV, 0x01, 0x02},
|
|
{REG_PAM3_OFFSET_NV, 0x10, 0x20},
|
|
{REG_PAM4_OFFSET_NV, 0x01, 0x02},
|
|
{REG_PAM4_OFFSET_NV, 0x10, 0x20},
|
|
{REG_PAM5_OFFSET_NV, 0x01, 0x02},
|
|
{REG_PAM5_OFFSET_NV, 0x10, 0x20},
|
|
{REG_PAM6_OFFSET_NV, 0x01, 0x02},
|
|
{REG_PAM6_OFFSET_NV, 0x10, 0x20},
|
|
{REG_PAM0_OFFSET_NV, 0x10, 0x20}
|
|
};
|
|
|
|
//
|
|
// Handle used to install the Legacy Region Protocol
|
|
//
|
|
STATIC EFI_HANDLE mHandle = NULL;
|
|
|
|
//
|
|
// Instance of the Legacy Region Protocol to install into the handle database
|
|
//
|
|
STATIC EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2 = {
|
|
LegacyRegion2Decode,
|
|
LegacyRegion2Lock,
|
|
LegacyRegion2BootLock,
|
|
LegacyRegion2Unlock,
|
|
LegacyRegionGetInfo
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
LegacyRegionManipulationInternal (
|
|
IN UINT32 Start,
|
|
IN UINT32 Length,
|
|
IN BOOLEAN *ReadEnable,
|
|
IN BOOLEAN *WriteEnable,
|
|
OUT UINT32 *Granularity
|
|
)
|
|
{
|
|
UINT32 EndAddress;
|
|
UINTN Index;
|
|
UINTN StartIndex;
|
|
|
|
//
|
|
// Validate input parameters.
|
|
//
|
|
if (Length == 0 || Granularity == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
EndAddress = Start + Length - 1;
|
|
if ((Start < PAM_BASE_ADDRESS) || EndAddress > PAM_LIMIT_ADDRESS) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Loop to find the start PAM.
|
|
//
|
|
StartIndex = 0;
|
|
for (Index = 0; Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0])); Index++) {
|
|
if ((Start >= mSectionArray[Index].Start) && (Start < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {
|
|
StartIndex = Index;
|
|
break;
|
|
}
|
|
}
|
|
ASSERT (Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0])));
|
|
|
|
//
|
|
// Program PAM until end PAM is encountered
|
|
//
|
|
for (Index = StartIndex; Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0])); Index++) {
|
|
//DBG(", Set %x = %x",
|
|
// mRegisterValues[Index].PAMRegOffset,
|
|
// PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset))
|
|
// );
|
|
if (ReadEnable != NULL) {
|
|
if (*ReadEnable) {
|
|
//DBG(" R-");
|
|
PciOr8 (
|
|
PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset),
|
|
mRegisterValues[Index].ReadEnableData
|
|
);
|
|
} else {
|
|
//DBG(" R+");
|
|
PciAnd8 (
|
|
PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset),
|
|
(UINT8) (~mRegisterValues[Index].ReadEnableData)
|
|
);
|
|
}
|
|
}
|
|
if (WriteEnable != NULL) {
|
|
if (*WriteEnable) {
|
|
//DBG(" W+");
|
|
PciOr8 (
|
|
PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset),
|
|
mRegisterValues[Index].WriteEnableData
|
|
);
|
|
} else {
|
|
//DBG(" W-");
|
|
PciAnd8 (
|
|
PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset),
|
|
(UINT8) (~mRegisterValues[Index].WriteEnableData)
|
|
);
|
|
}
|
|
}
|
|
//DBG(" => %x",
|
|
// PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset))
|
|
// );
|
|
|
|
//
|
|
// If the end PAM is encountered, record its length as granularity and jump out.
|
|
//
|
|
if ((EndAddress >= mSectionArray[Index].Start) && (EndAddress < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {
|
|
*Granularity = mSectionArray[Index].Length;
|
|
break;
|
|
}
|
|
}
|
|
ASSERT (Index < (sizeof(mSectionArray) / sizeof(mSectionArray[0])));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
LegacyRegionGetInfoInternal (
|
|
OUT UINT32 *DescriptorCount,
|
|
OUT LEGACY_MEMORY_SECTION_INFO **Descriptor
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT8 PamValue;
|
|
|
|
//
|
|
// Check input parameters
|
|
//
|
|
if (DescriptorCount == NULL || Descriptor == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Fill in current status of legacy region.
|
|
//
|
|
*DescriptorCount = (sizeof(mSectionArray) / sizeof(mSectionArray[0]));
|
|
for (Index = 0; Index < *DescriptorCount; Index++) {
|
|
PamValue = PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, mRegisterValues[Index].PAMRegOffset));
|
|
mSectionArray[Index].ReadEnabled = FALSE;
|
|
if ((PamValue & mRegisterValues[Index].ReadEnableData) != 0) {
|
|
mSectionArray[Index].ReadEnabled = TRUE;
|
|
}
|
|
mSectionArray[Index].WriteEnabled = FALSE;
|
|
if ((PamValue & mRegisterValues[Index].WriteEnableData) != 0) {
|
|
mSectionArray[Index].WriteEnabled = TRUE;
|
|
}
|
|
}
|
|
|
|
*Descriptor = mSectionArray;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
|
|
|
|
If the On parameter evaluates to TRUE, this function enables memory reads in the address range
|
|
Start to (Start + Length - 1).
|
|
If the On parameter evaluates to FALSE, this function disables memory reads in the address range
|
|
Start to (Start + Length - 1).
|
|
|
|
@param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
|
|
@param Start[in] The beginning of the physical address of the region whose attributes
|
|
should be modified.
|
|
@param Length[in] The number of bytes of memory whose attributes should be modified.
|
|
The actual number of bytes modified may be greater than the number
|
|
specified.
|
|
@param Granularity[out] The number of bytes in the last region affected. This may be less
|
|
than the total number of bytes affected if the starting address
|
|
was not aligned to a region's starting address or if the length
|
|
was greater than the number of bytes in the first region.
|
|
@param On[in] Decode / Non-Decode flag.
|
|
|
|
@retval EFI_SUCCESS The region's attributes were successfully modified.
|
|
@retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LegacyRegion2Decode (
|
|
IN EFI_LEGACY_REGION2_PROTOCOL *This,
|
|
IN UINT32 Start,
|
|
IN UINT32 Length,
|
|
OUT UINT32 *Granularity,
|
|
IN BOOLEAN *On
|
|
)
|
|
{
|
|
return LegacyRegionManipulationInternal (Start, Length, On, NULL, Granularity);
|
|
}
|
|
|
|
|
|
/**
|
|
Modify the hardware to disallow memory attribute changes in a region.
|
|
|
|
This function makes the attributes of a region read only. Once a region is boot-locked with this
|
|
function, the read and write attributes of that region cannot be changed until a power cycle has
|
|
reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
|
|
|
|
@param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
|
|
@param Start[in] The beginning of the physical address of the region whose
|
|
attributes should be modified.
|
|
@param Length[in] The number of bytes of memory whose attributes should be modified.
|
|
The actual number of bytes modified may be greater than the number
|
|
specified.
|
|
@param Granularity[out] The number of bytes in the last region affected. This may be less
|
|
than the total number of bytes affected if the starting address was
|
|
not aligned to a region's starting address or if the length was
|
|
greater than the number of bytes in the first region.
|
|
|
|
@retval EFI_SUCCESS The region's attributes were successfully modified.
|
|
@retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
|
|
@retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in
|
|
a way that will not affect memory regions outside the legacy memory
|
|
region.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LegacyRegion2BootLock (
|
|
IN EFI_LEGACY_REGION2_PROTOCOL *This,
|
|
IN UINT32 Start,
|
|
IN UINT32 Length,
|
|
OUT UINT32 *Granularity
|
|
)
|
|
{
|
|
if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
|
|
/**
|
|
Modify the hardware to disallow memory writes in a region.
|
|
|
|
This function changes the attributes of a memory range to not allow writes.
|
|
|
|
@param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
|
|
@param Start[in] The beginning of the physical address of the region whose
|
|
attributes should be modified.
|
|
@param Length[in] The number of bytes of memory whose attributes should be modified.
|
|
The actual number of bytes modified may be greater than the number
|
|
specified.
|
|
@param Granularity[out] The number of bytes in the last region affected. This may be less
|
|
than the total number of bytes affected if the starting address was
|
|
not aligned to a region's starting address or if the length was
|
|
greater than the number of bytes in the first region.
|
|
|
|
@retval EFI_SUCCESS The region's attributes were successfully modified.
|
|
@retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LegacyRegion2Lock (
|
|
IN EFI_LEGACY_REGION2_PROTOCOL *This,
|
|
IN UINT32 Start,
|
|
IN UINT32 Length,
|
|
OUT UINT32 *Granularity
|
|
)
|
|
{
|
|
BOOLEAN WriteEnable;
|
|
|
|
WriteEnable = FALSE;
|
|
return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);
|
|
}
|
|
|
|
|
|
/**
|
|
Modify the hardware to allow memory writes in a region.
|
|
|
|
This function changes the attributes of a memory range to allow writes.
|
|
|
|
@param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
|
|
@param Start[in] The beginning of the physical address of the region whose
|
|
attributes should be modified.
|
|
@param Length[in] The number of bytes of memory whose attributes should be modified.
|
|
The actual number of bytes modified may be greater than the number
|
|
specified.
|
|
@param Granularity[out] The number of bytes in the last region affected. This may be less
|
|
than the total number of bytes affected if the starting address was
|
|
not aligned to a region's starting address or if the length was
|
|
greater than the number of bytes in the first region.
|
|
|
|
@retval EFI_SUCCESS The region's attributes were successfully modified.
|
|
@retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LegacyRegion2Unlock (
|
|
IN EFI_LEGACY_REGION2_PROTOCOL *This,
|
|
IN UINT32 Start,
|
|
IN UINT32 Length,
|
|
OUT UINT32 *Granularity
|
|
)
|
|
{
|
|
BOOLEAN WriteEnable;
|
|
|
|
WriteEnable = TRUE;
|
|
return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);
|
|
}
|
|
|
|
/**
|
|
Get region information for the attributes of the Legacy Region.
|
|
|
|
This function is used to discover the granularity of the attributes for the memory in the legacy
|
|
region. Each attribute may have a different granularity and the granularity may not be the same
|
|
for all memory ranges in the legacy region.
|
|
|
|
@param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
|
|
@param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor
|
|
buffer.
|
|
@param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy
|
|
region information is deposited. This buffer will contain a list of
|
|
DescriptorCount number of region descriptors. This function will
|
|
provide the memory for the buffer.
|
|
|
|
@retval EFI_SUCCESS The region's attributes were successfully modified.
|
|
@retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LegacyRegionGetInfo (
|
|
IN EFI_LEGACY_REGION2_PROTOCOL *This,
|
|
OUT UINT32 *DescriptorCount,
|
|
OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor
|
|
)
|
|
{
|
|
LEGACY_MEMORY_SECTION_INFO *SectionInfo;
|
|
UINT32 SectionCount;
|
|
EFI_LEGACY_REGION_DESCRIPTOR *DescriptorArray;
|
|
UINTN Index;
|
|
UINTN DescriptorIndex;
|
|
|
|
//
|
|
// Get section numbers and information
|
|
//
|
|
LegacyRegionGetInfoInternal (&SectionCount, &SectionInfo);
|
|
|
|
//
|
|
// Each section has 3 descriptors, corresponding to readability, writeability, and lock status.
|
|
//
|
|
DescriptorArray = AllocatePool (sizeof (EFI_LEGACY_REGION_DESCRIPTOR) * SectionCount * 3);
|
|
if (DescriptorArray == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
DescriptorIndex = 0;
|
|
for (Index = 0; Index < SectionCount; Index++) {
|
|
DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
|
|
DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
|
|
DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
|
|
if (SectionInfo[Index].ReadEnabled) {
|
|
DescriptorArray[DescriptorIndex].Attribute = LegacyRegionDecoded;
|
|
} else {
|
|
DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotDecoded;
|
|
}
|
|
DescriptorIndex++;
|
|
|
|
//
|
|
// Create descriptor for writeability, according to lock status
|
|
//
|
|
DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
|
|
DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
|
|
DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
|
|
if (SectionInfo[Index].WriteEnabled) {
|
|
DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteEnabled;
|
|
} else {
|
|
DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteDisabled;
|
|
}
|
|
DescriptorIndex++;
|
|
|
|
//
|
|
// Chipset does not support bootlock.
|
|
//
|
|
DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
|
|
DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
|
|
DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
|
|
DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotLocked;
|
|
DescriptorIndex++;
|
|
}
|
|
|
|
*DescriptorCount = (UINT32) DescriptorIndex;
|
|
*Descriptor = DescriptorArray;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Detects chipset and initialize PAM support tables
|
|
|
|
@retval EFI_SUCCESS Successfully initialized
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DetectChipset (
|
|
VOID
|
|
)
|
|
{
|
|
UINT16 VID = 0;
|
|
UINT16 DID = 0;
|
|
|
|
mRegisterValues = NULL;
|
|
|
|
mVendorDeviceId = PciRead32 (PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, 0));
|
|
DBG(" Chipset/proc: 0x%08X\n", mVendorDeviceId);
|
|
|
|
switch (mVendorDeviceId) {
|
|
|
|
//
|
|
// Intel 830 and similar
|
|
// Copied from 915 resolution created by steve tomljenovic,
|
|
// Resolution module by Evan Lojewski
|
|
//
|
|
case 0x35758086: // 830
|
|
case 0x35808086: // 855GM
|
|
DBG(" Intel 830 and similar (PAM 0x59-0x5f)\n");
|
|
mRegisterValues = mRegisterValues830;
|
|
break;
|
|
|
|
case 0x25C08086: // 5000
|
|
case 0x25D48086: // 5000V
|
|
case 0x65C08086: // 5100
|
|
DBG(" Intel 5000 and similar (PAM 0x59-0x5f)\n");
|
|
mRegisterValues = mRegisterValues830;
|
|
mPamPciDev = 16;
|
|
break;
|
|
|
|
//
|
|
// Intel Series 4 and similar
|
|
// Copied from 915 resolution created by steve tomljenovic,
|
|
// Resolution module by Evan Lojewski
|
|
//
|
|
case 0x25608086: // 845G
|
|
case 0x25708086: // 865G
|
|
case 0x25808086: // 915G
|
|
case 0x25908086: // 915GM
|
|
|
|
case 0x27708086: // 945G
|
|
case 0x27748086: // 955X
|
|
case 0x277c8086: // 975X
|
|
case 0x27a08086: // 945GM - Dell D430 Offset 090: 10 11 11 00 00
|
|
case 0x27ac8086: // 945GME
|
|
case 0x29208086: // G45
|
|
case 0x29708086: // 946GZ
|
|
case 0x29808086: // G965
|
|
case 0x29908086: // Q965
|
|
case 0x29a08086: // P965
|
|
case 0x29b08086: // R845
|
|
case 0x29c08086: // G31/P35
|
|
case 0x29d08086: // Q33
|
|
case 0x29e08086: // X38/X48
|
|
case 0x2a008086: // 965GM
|
|
case 0x2a108086: // GME965/GLE960
|
|
case 0x2a408086: // PM/GM45/47
|
|
case 0x2e008086: // Eaglelake
|
|
case 0x2e108086: // B43
|
|
case 0x2e208086: // P45
|
|
case 0x2e308086: // G41
|
|
case 0x2e408086: // B43 Base
|
|
case 0x2e908086: // B43 Soft Sku
|
|
case 0x81008086: // 500
|
|
case 0xA0008086: // 3150
|
|
DBG(" Intel Series 4 and similar (PAM 0x90-0x96)\n");
|
|
mRegisterValues = mRegisterValuesS4;
|
|
break;
|
|
|
|
//
|
|
// Core processors
|
|
// http://pci-ids.ucw.cz/read/PC/8086
|
|
//
|
|
case 0x01008086: // 2nd Generation Core Processor Family DRAM Controller
|
|
case 0x01048086: // 2nd Generation Core Processor Family DRAM Controller
|
|
case 0x01088086: // Xeon E3-1200 2nd Generation Core Processor Family DRAM Controller
|
|
case 0x010c8086: // Xeon E3-1200 2nd Generation Core Processor Family DRAM Controller
|
|
|
|
case 0x01508086: // 3rd Generation Core Processor Family DRAM Controller
|
|
case 0x01548086: // 3rd Generation Core Processor Family DRAM Controller
|
|
case 0x01588086: // 3rd Generation Core Processor Family DRAM Controller
|
|
case 0x015c8086: // 3rd Generation Core Processor Family DRAM Controller
|
|
|
|
case 0x01608086: // 3rd Generation Core Processor Family DRAM Controller
|
|
case 0x01648086: // 3rd Generation Core Processor Family DRAM Controller
|
|
|
|
case 0x0C008086: // 4rd Generation Core Processor Family DRAM Controller
|
|
case 0x0C048086: // 4rd Generation M-Processor Series
|
|
case 0x0C088086: // 4rd Generation Haswell Xeon
|
|
case 0x0A048086: // 4rd Generation U-Processor Series
|
|
case 0x0D048086: // 4rd Generation H-Processor Series (BGA) with GT3 Graphics
|
|
case 0x16048086: // 5th Generation Core Processor Family DRAM Controller
|
|
|
|
case 0x191f8086: // 6th Generation (Skylake) DRAM Controller (Z170X)
|
|
|
|
case 0x0F008086: // Bay Trail Family DRAM Controller
|
|
DBG(" Next Generation Core processors (PAM 0x80-0x86)\n");
|
|
mRegisterValues = mRegisterValuesCP;
|
|
break;
|
|
|
|
//1st gen i7 - Nehalem
|
|
case 0x00408086: // Core Processor DRAM Controller
|
|
case 0x00448086: // Core Processor DRAM Controller - Arrandale
|
|
case 0x00488086: // Core Processor DRAM Controller
|
|
case 0x00698086: // Core Processor DRAM Controller
|
|
|
|
case 0xD1308086: // Xeon(R) CPU L3426 Processor DRAM Controller
|
|
case 0xD1318086: // Core-i Processor DRAM Controller
|
|
case 0xD1328086: //PM55 i7-720QM DRAM Controller
|
|
case 0x34008086: // Core-i Processor DRAM Controller
|
|
case 0x34018086: // Core-i Processor DRAM Controller
|
|
case 0x34028086: // Core-i Processor DRAM Controller
|
|
case 0x34038086: // Core-i Processor DRAM Controller
|
|
case 0x34048086: // Core-i Processor DRAM Controller
|
|
case 0x34058086: //X58 Core-i Processor DRAM Controller
|
|
case 0x34068086: // Core-i Processor DRAM Controller
|
|
case 0x34078086: // Core-i Processor DRAM Controller
|
|
DBG(" Core i7 processors (PAM 0x40-0x47)\n");
|
|
mRegisterValues = mRegisterValuesNH;
|
|
mPamPciBus = 0xFF;
|
|
for (mPamPciBus = 0xFF; mPamPciBus > 0x1F; mPamPciBus >>= 1) {
|
|
VID = PciRead16 (PCI_LIB_ADDRESS(mPamPciBus, 0, 1, 0x00));
|
|
if (VID != 0x8086) {
|
|
continue;
|
|
}
|
|
DID = PciRead16 (PCI_LIB_ADDRESS(mPamPciBus, 0, 1, 0x02));
|
|
if (DID > 0x2c00) {
|
|
break;
|
|
}
|
|
}
|
|
if ((VID != 0x8086) || (DID < 0x2c00)) {
|
|
DBG("Nehalem bus is not found, assume 0\n");
|
|
mPamPciBus = 0;
|
|
} else {
|
|
mPamPciFunc = 1;
|
|
}
|
|
break;
|
|
//case 0x2F008086: //Haswell-E information needed
|
|
case 0x3C008086: // Xeon E5 Processor
|
|
//DID = 3CF4 Check?
|
|
DBG(" Xeon E5 processors (PAM 0x40-0x47)\n");
|
|
mRegisterValues = mRegisterValuesNH;
|
|
mPamPciBus = PciRead8 (PCI_LIB_ADDRESS(0, 5, 0, 0x109));
|
|
mPamPciDev = 12;
|
|
mPamPciFunc = 6;
|
|
break;
|
|
|
|
case 0x0a8210de:
|
|
case 0x0a8610de:
|
|
DBG(" NForce MCP79 and similar (PAM 0xC0-0xC7)\n");
|
|
mRegisterValues = mRegisterValuesNV;
|
|
break;
|
|
|
|
default:
|
|
DBG(" Unknown chipset\n");
|
|
break;
|
|
}
|
|
|
|
/*
|
|
// Linux codes have this procedure. We need not it?
|
|
// Setup P35 Memory Controller
|
|
static void setup_p35(pci_dt_t *dram_dev)
|
|
{
|
|
uint32_t dev0;
|
|
|
|
// Activate MMR I/O
|
|
dev0 = pci_config_read32(dram_dev->dev.addr, 0x48);
|
|
if (!(dev0 & 0x1))
|
|
pci_config_write8(dram_dev->dev.addr, 0x48, (dev0 | 1));
|
|
}
|
|
*/
|
|
|
|
{
|
|
//
|
|
// Test known PAM addresses.
|
|
// Correct PAM1 value should be 0x11 for locked 0xC0000-0xC7FFF
|
|
//
|
|
UINT8 Pam40 = PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, 0x41));
|
|
UINT8 Pam59 = PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, 0x5a));
|
|
UINT8 Pam80 = PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, 0x81));
|
|
UINT8 Pam90 = PciRead8 (PCI_LIB_ADDRESS(mPamPciBus, mPamPciDev, mPamPciFunc, 0x91));
|
|
|
|
DBG(" Test PAM1=(0x41=%02x, 0x5a=%02x, 0x81=%02x, 0x91=%02x)", Pam40, Pam59, Pam80, Pam90);
|
|
DBG(" at chipset %08x\n", mVendorDeviceId);
|
|
|
|
}
|
|
|
|
return mRegisterValues != NULL ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Initialize Legacy Region support
|
|
|
|
@retval EFI_SUCCESS Successfully initialized
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LegacyRegion2Install (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *Protocol;
|
|
|
|
DBG("LegacyRegion2:");
|
|
|
|
//
|
|
// Check for presence of gEfiLegacyRegionProtocolGuid
|
|
// and gEfiLegacyRegion2ProtocolGuid
|
|
//
|
|
Status = gBS->LocateProtocol (&gEfiLegacyRegionProtocolGuid, NULL, (VOID **) &Protocol);
|
|
if (Status == EFI_SUCCESS) {
|
|
DBG(" EfiLegacyRegion exists - exiting\n");
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
Status = gBS->LocateProtocol (&gEfiLegacyRegion2ProtocolGuid, NULL, (VOID **) &Protocol);
|
|
if (Status == EFI_SUCCESS) {
|
|
DBG(" EfiLegacyRegion2 exists - exiting\n");
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = DetectChipset ();
|
|
if (EFI_ERROR (Status)) {
|
|
DBG(", Chipset not detected - exiting\n");
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Install the Legacy Region Protocol on a new handle
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&mHandle,
|
|
&gEfiLegacyRegion2ProtocolGuid,
|
|
&mLegacyRegion2,
|
|
NULL
|
|
);
|
|
|
|
DBG(", Install = %r\n", Status);
|
|
return Status;
|
|
}
|
|
|