/** @file DXE Chipset Services Library. This file contains only one function that is DxeCsSvcLegacyRegionAccessCtrl(). The function DxeCsSvcLegacyRegionAccessCtrl() use chipset services to control legacy region can be access or not. ;*************************************************************************** ;* Copyright (c) 2018, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include #include #include //#include //#define PCI_BASE_ADDRESS 0x80000000 //#define SYSTEM_DECODER_BASE (((UINTN)PCI_BASE_ADDRESS + (UINTN)(SA_MC_BUS << 16 ) + \ // (UINTN)(SA_MC_DEV << 11) + (UINTN)(SA_MC_FUN << 8) + (UINTN)R_SA_PAM0)); #define SYSTEM_DECODER_BASE (( (UINTN)(SA_MC_BUS << 16 ) + (UINTN)(SA_MC_DEV << 11) + \ (UINTN)(SA_MC_FUN << 8) + (UINTN)R_SA_PAM0)); typedef enum { LegacyRegionSegment_F = 0, LegacyRegionSegment_C = 1, LegacyRegionSegment_D = 3, LegacyRegionSegment_E = 5, LegacyRegionSegment_All = 7 } LEGACY_REGION_SEGMENT; LEGACY_REGION_SEGMENT mSegment[4] = { LegacyRegionSegment_C, LegacyRegionSegment_D, LegacyRegionSegment_E, LegacyRegionSegment_F }; UINT8 mLockData[7] = {0x10, 0x11, 0x11, 0x11, 0x11, 0x33, 0x33}; UINT8 mUnLockData[7] = {0x30, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33}; /** LegacyRegionManipulation is consumed by LegacyRegionAccessCtrl(). @param[in] Segment @param[in] IsWriteProtect @retval None */ STATIC VOID LegacyRegionManipulation ( IN LEGACY_REGION_SEGMENT Segment, IN BOOLEAN IsWriteProtect ) { UINT32 SystemDecoderBase; UINT8 *Data; UINTN Index; Index = 0; SystemDecoderBase = SYSTEM_DECODER_BASE; if (IsWriteProtect) { Data = mLockData; } else { Data = mUnLockData; } if (Segment == (UINTN)LegacyRegionSegment_F) { PciExpressWrite8 (SystemDecoderBase, Data[(UINTN)Segment]); } else if (Segment == (UINTN)LegacyRegionSegment_All) { for (Index = 0; Index < (UINTN)Segment; Index++) { PciExpressWrite8 ((SystemDecoderBase + (UINT32)Index), Data[Index]); } } else { PciExpressWrite8 ((SystemDecoderBase + (UINT32)Segment), Data[(UINTN)Segment]); PciExpressWrite8 ((SystemDecoderBase + (UINT32)Segment + 1), Data[(UINTN)(Segment + 1)]); } return; } /** Legacy Region Access Control. @param[in] Start Start of the region to lock or unlock. @param[in] Length Length of the region. @param[in] Mode LEGACY_REGION_ACCESS_LOCK or LEGACY_REGION_ACCESS_UNLOCK If LEGACY_REGION_ACCESS_LOCK, then LegacyRegionAccessCtrl() lock the specific legacy region. @retval EFI_SUCCESS Function returns successfully @retval EFI_INVALID_PARAMETER 1. The parameter Start is small then 0xC0000. 2. The parameter Length is to long. The Start + Length - 1 should small then 0xF0000. 3. The Mode parameter is neither LEGACY_REGION_ACCESS_LOCK nor LEGACY_REGION_ACCESS_UNLOCK */ EFI_STATUS LegacyRegionAccessCtrl ( IN UINT32 Start, IN UINT32 Length, IN UINT32 Mode ) { UINTN End; LEGACY_REGION_SEGMENT IndexStart; LEGACY_REGION_SEGMENT IndexEnd; UINTN Index; if (Mode != LEGACY_REGION_ACCESS_UNLOCK && Mode != LEGACY_REGION_ACCESS_LOCK) { return EFI_INVALID_PARAMETER; } if (Start < 0xC0000) { return EFI_INVALID_PARAMETER; } End = Start + Length - 1; Start = Start & 0xF0000; End = End & 0xF0000; Start = Start >> 16; End = End >> 16; Start = Start - 0x0C; if (Start >= 4) { return EFI_INVALID_PARAMETER; } IndexStart = mSegment[Start]; End = End - 0x0C; if (End >= 4) { return EFI_INVALID_PARAMETER; } IndexEnd = mSegment[End]; if (IndexStart == IndexEnd) { LegacyRegionManipulation (IndexStart, (BOOLEAN)Mode); } else if (IndexStart == LegacyRegionSegment_C && IndexEnd == LegacyRegionSegment_F) { LegacyRegionManipulation (LegacyRegionSegment_All, (BOOLEAN)Mode); } else { for (Index = Start; Index <= End; Index++ ) { LegacyRegionManipulation (mSegment[Index], (BOOLEAN)Mode); } } return EFI_SUCCESS; }