From b47932475500fc4b72ceab745aefd590ad1d1e6a Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 22 Dec 2016 16:14:50 +0800 Subject: IntelFsp2Pkg: Move to new location Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- Core/IntelFsp2Pkg/Contributions.txt | 218 +++ .../FspNotifyPhase/FspNotifyPhasePeim.c | 142 ++ .../FspNotifyPhase/FspNotifyPhasePeim.h | 23 + .../FspNotifyPhase/FspNotifyPhasePeim.inf | 49 + Core/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf | 74 + Core/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf | 68 + Core/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf | 66 + .../FspSecCore/Ia32/FspApiEntryCommon.nasm | 76 + .../IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm | 202 +++ .../IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm | 62 + .../IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm | 477 +++++++ Core/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm | 35 + .../FspSecCore/Ia32/InitializeFpu.nasm | 78 ++ .../FspSecCore/Ia32/MicrocodeLoadNasm.inc | 16 + .../FspSecCore/Ia32/SaveRestoreSseNasm.inc | 187 +++ Core/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm | 78 ++ Core/IntelFsp2Pkg/FspSecCore/SecFsp.c | 214 +++ Core/IntelFsp2Pkg/FspSecCore/SecFsp.h | 99 ++ Core/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c | 97 ++ Core/IntelFsp2Pkg/FspSecCore/SecMain.c | 227 +++ Core/IntelFsp2Pkg/FspSecCore/SecMain.h | 140 ++ .../FspSecCore/Vtf0/Bin/ResetVec.ia32.raw | Bin 0 -> 68 bytes Core/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py | 53 + .../FspSecCore/Vtf0/Ia16/ResetVec.asm16 | 103 ++ .../FspSecCore/Vtf0/ResetVectorCode.asm | 17 + .../FspSecCore/Vtf0/Tools/FixupForRawSection.py | 110 ++ Core/IntelFsp2Pkg/Include/FspDataTable.h | 32 + Core/IntelFsp2Pkg/Include/FspEas.h | 24 + Core/IntelFsp2Pkg/Include/FspEas/FspApi.h | 288 ++++ Core/IntelFsp2Pkg/Include/FspGlobalData.h | 66 + Core/IntelFsp2Pkg/Include/FspMeasurePointId.h | 62 + Core/IntelFsp2Pkg/Include/FspStatusCode.h | 46 + Core/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h | 204 +++ Core/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h | 23 + Core/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h | 30 + Core/IntelFsp2Pkg/Include/Library/CacheLib.h | 62 + Core/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h | 29 + Core/IntelFsp2Pkg/Include/Library/FspCommonLib.h | 303 ++++ Core/IntelFsp2Pkg/Include/Library/FspPlatformLib.h | 96 ++ .../Include/Library/FspSecPlatformLib.h | 88 ++ .../Include/Library/FspSwitchStackLib.h | 45 + Core/IntelFsp2Pkg/IntelFsp2Pkg.dec | 80 ++ Core/IntelFsp2Pkg/IntelFsp2Pkg.dsc | 79 ++ .../BaseCacheAsRamLibNull.inf | 31 + .../BaseCacheAsRamLibNull/DisableCacheAsRamNull.c | 41 + .../Library/BaseCacheLib/BaseCacheLib.inf | 34 + Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c | 703 ++++++++++ .../Library/BaseCacheLib/CacheLibInternal.h | 59 + .../BaseDebugDeviceLibNull.inf | 34 + .../BaseDebugDeviceLibNull/DebugDeviceLibNull.c | 31 + .../Library/BaseFspCommonLib/BaseFspCommonLib.inf | 40 + .../Library/BaseFspCommonLib/FspCommonLib.c | 533 +++++++ .../BaseFspDebugLibSerialPort.inf | 50 + .../Library/BaseFspDebugLibSerialPort/DebugLib.c | 328 +++++ .../BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm | 31 + .../BaseFspPlatformLib/BaseFspPlatformLib.inf | 50 + .../Library/BaseFspPlatformLib/FspPlatformMemory.c | 122 ++ .../Library/BaseFspPlatformLib/FspPlatformNotify.c | 279 ++++ .../BaseFspSwitchStackLib.inf | 42 + .../BaseFspSwitchStackLib/FspSwitchStackLib.c | 42 + .../Library/BaseFspSwitchStackLib/Ia32/Stack.nasm | 74 + .../SecFspSecPlatformLibNull/Ia32/Flat32.nasm | 127 ++ .../SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm | 46 + .../SecFspSecPlatformLibNull/PlatformSecLibNull.c | 33 + .../SecFspSecPlatformLibNull.inf | 56 + Core/IntelFsp2Pkg/License.txt | 25 + Core/IntelFsp2Pkg/Tools/GenCfgOpt.py | 1467 ++++++++++++++++++++ Core/IntelFsp2Pkg/Tools/PatchFv.py | 947 +++++++++++++ Core/IntelFsp2Pkg/Tools/SplitFspBin.py | 679 +++++++++ .../Tools/UserManuals/GenCfgOptUserManual.docx | Bin 0 -> 28336 bytes .../Tools/UserManuals/PatchFvUserManual.docx | Bin 0 -> 21481 bytes .../Tools/UserManuals/SplitFspBinUserManual.md | 69 + 72 files changed, 10441 insertions(+) create mode 100644 Core/IntelFsp2Pkg/Contributions.txt create mode 100644 Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c create mode 100644 Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h create mode 100644 Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf create mode 100644 Core/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf create mode 100644 Core/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf create mode 100644 Core/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/SecFsp.c create mode 100644 Core/IntelFsp2Pkg/FspSecCore/SecFsp.h create mode 100644 Core/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c create mode 100644 Core/IntelFsp2Pkg/FspSecCore/SecMain.c create mode 100644 Core/IntelFsp2Pkg/FspSecCore/SecMain.h create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm create mode 100644 Core/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py create mode 100644 Core/IntelFsp2Pkg/Include/FspDataTable.h create mode 100644 Core/IntelFsp2Pkg/Include/FspEas.h create mode 100644 Core/IntelFsp2Pkg/Include/FspEas/FspApi.h create mode 100644 Core/IntelFsp2Pkg/Include/FspGlobalData.h create mode 100644 Core/IntelFsp2Pkg/Include/FspMeasurePointId.h create mode 100644 Core/IntelFsp2Pkg/Include/FspStatusCode.h create mode 100644 Core/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h create mode 100644 Core/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h create mode 100644 Core/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h create mode 100644 Core/IntelFsp2Pkg/Include/Library/CacheLib.h create mode 100644 Core/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h create mode 100644 Core/IntelFsp2Pkg/Include/Library/FspCommonLib.h create mode 100644 Core/IntelFsp2Pkg/Include/Library/FspPlatformLib.h create mode 100644 Core/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h create mode 100644 Core/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h create mode 100644 Core/IntelFsp2Pkg/IntelFsp2Pkg.dec create mode 100644 Core/IntelFsp2Pkg/IntelFsp2Pkg.dsc create mode 100644 Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf create mode 100644 Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf create mode 100644 Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h create mode 100644 Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf create mode 100644 Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c create mode 100644 Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm create mode 100644 Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm create mode 100644 Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm create mode 100644 Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c create mode 100644 Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf create mode 100644 Core/IntelFsp2Pkg/License.txt create mode 100644 Core/IntelFsp2Pkg/Tools/GenCfgOpt.py create mode 100644 Core/IntelFsp2Pkg/Tools/PatchFv.py create mode 100644 Core/IntelFsp2Pkg/Tools/SplitFspBin.py create mode 100644 Core/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.docx create mode 100644 Core/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.docx create mode 100644 Core/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md (limited to 'Core') diff --git a/Core/IntelFsp2Pkg/Contributions.txt b/Core/IntelFsp2Pkg/Contributions.txt new file mode 100644 index 0000000000..f87cbd73c6 --- /dev/null +++ b/Core/IntelFsp2Pkg/Contributions.txt @@ -0,0 +1,218 @@ + +====================== += Code Contributions = +====================== + +To make a contribution to a TianoCore project, follow these steps. +1. Create a change description in the format specified below to + use in the source control commit log. +2. Your commit message must include your "Signed-off-by" signature, + and "Contributed-under" message. +3. Your "Contributed-under" message explicitly states that the + contribution is made under the terms of the specified + contribution agreement. Your "Contributed-under" message + must include the name of contribution agreement and version. + For example: Contributed-under: TianoCore Contribution Agreement 1.0 + The "TianoCore Contribution Agreement" is included below in + this document. +4. Submit your code to the TianoCore project using the process + that the project documents on its web page. If the process is + not documented, then submit the code on development email list + for the project. +5. It is preferred that contributions are submitted using the same + copyright license as the base project. When that is not possible, + then contributions using the following licenses can be accepted: + * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause + * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause + * MIT: http://opensource.org/licenses/MIT + * Python-2.0: http://opensource.org/licenses/Python-2.0 + * Zlib: http://opensource.org/licenses/Zlib + + Contributions of code put into the public domain can also be + accepted. + + Contributions using other licenses might be accepted, but further + review will be required. + +===================================================== += Change Description / Commit Message / Patch Email = +===================================================== + +Your change description should use the standard format for a +commit message, and must include your "Signed-off-by" signature +and the "Contributed-under" message. + +== Sample Change Description / Commit Message = + +=== Start of sample patch email message === + +From: Contributor Name +Subject: [PATCH] CodeModule: Brief-single-line-summary + +Full-commit-message + +Contributed-under: TianoCore Contribution Agreement 1.0 +Signed-off-by: Contributor Name +--- + +An extra message for the patch email which will not be considered part +of the commit message can be added here. + +Patch content inline or attached + +=== End of sample patch email message === + +=== Notes for sample patch email === + +* The first line of commit message is taken from the email's subject + line following [PATCH]. The remaining portion of the commit message + is the email's content until the '---' line. +* git format-patch is one way to create this format + +=== Definitions for sample patch email === + +* "CodeModule" is a short idenfier for the affected code. For + example MdePkg, or MdeModulePkg UsbBusDxe. +* "Brief-single-line-summary" is a short summary of the change. +* The entire first line should be less than ~70 characters. +* "Full-commit-message" a verbose multiple line comment describing + the change. Each line should be less than ~70 characters. +* "Contributed-under" explicitely states that the contribution is + made under the terms of the contribtion agreement. This + agreement is included below in this document. +* "Signed-off-by" is the contributor's signature identifying them + by their real/legal name and their email address. + +======================================== += TianoCore Contribution Agreement 1.0 = +======================================== + +INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION, +INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE +PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE +TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE +TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR +REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE +CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS +OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED +BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS +AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE +AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT +USE THE CONTENT. + +Unless otherwise indicated, all Content made available on the TianoCore +site is provided to you under the terms and conditions of the BSD +License ("BSD"). A copy of the BSD License is available at +http://opensource.org/licenses/bsd-license.php +or when applicable, in the associated License.txt file. + +Certain other content may be made available under other licenses as +indicated in or with such Content. (For example, in a License.txt file.) + +You accept and agree to the following terms and conditions for Your +present and future Contributions submitted to TianoCore site. Except +for the license granted to Intel hereunder, You reserve all right, +title, and interest in and to Your Contributions. + +== SECTION 1: Definitions == +* "You" or "Contributor" shall mean the copyright owner or legal + entity authorized by the copyright owner that is making a + Contribution hereunder. All other entities that control, are + controlled by, or are under common control with that entity are + considered to be a single Contributor. For the purposes of this + definition, "control" means (i) the power, direct or indirect, to + cause the direction or management of such entity, whether by + contract or otherwise, or (ii) ownership of fifty percent (50%) + or more of the outstanding shares, or (iii) beneficial ownership + of such entity. +* "Contribution" shall mean any original work of authorship, + including any modifications or additions to an existing work, + that is intentionally submitted by You to the TinaoCore site for + inclusion in, or documentation of, any of the Content. For the + purposes of this definition, "submitted" means any form of + electronic, verbal, or written communication sent to the + TianoCore site or its representatives, including but not limited + to communication on electronic mailing lists, source code + control systems, and issue tracking systems that are managed by, + or on behalf of, the TianoCore site for the purpose of + discussing and improving the Content, but excluding + communication that is conspicuously marked or otherwise + designated in writing by You as "Not a Contribution." + +== SECTION 2: License for Contributions == +* Contributor hereby agrees that redistribution and use of the + Contribution in source and binary forms, with or without + modification, are permitted provided that the following + conditions are met: +** Redistributions of source code must retain the Contributor's + copyright notice, this list of conditions and the following + disclaimer. +** Redistributions in binary form must reproduce the Contributor's + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. +* Disclaimer. None of the names of Contributor, Intel, or the names + of their respective contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. +* Contributor grants a license (with the right to sublicense) under + claims of Contributor's patents that Contributor can license that + are infringed by the Contribution (as delivered by Contributor) to + make, use, distribute, sell, offer for sale, and import the + Contribution and derivative works thereof solely to the minimum + extent necessary for licensee to exercise the granted copyright + license; this patent license applies solely to those portions of + the Contribution that are unmodified. No hardware per se is + licensed. +* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE + CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE + CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +== SECTION 3: Representations == +* You represent that You are legally entitled to grant the above + license. If your employer(s) has rights to intellectual property + that You create that includes Your Contributions, You represent + that You have received permission to make Contributions on behalf + of that employer, that Your employer has waived such rights for + Your Contributions. +* You represent that each of Your Contributions is Your original + creation (see Section 4 for submissions on behalf of others). + You represent that Your Contribution submissions include complete + details of any third-party license or other restriction + (including, but not limited to, related patents and trademarks) + of which You are personally aware and which are associated with + any part of Your Contributions. + +== SECTION 4: Third Party Contributions == +* Should You wish to submit work that is not Your original creation, + You may submit it to TianoCore site separately from any + Contribution, identifying the complete details of its source + and of any license or other restriction (including, but not + limited to, related patents, trademarks, and license agreements) + of which You are personally aware, and conspicuously marking the + work as "Submitted on behalf of a third-party: [named here]". + +== SECTION 5: Miscellaneous == +* Applicable Laws. Any claims arising under or relating to this + Agreement shall be governed by the internal substantive laws of + the State of Delaware or federal courts located in Delaware, + without regard to principles of conflict of laws. +* Language. This Agreement is in the English language only, which + language shall be controlling in all respects, and all versions + of this Agreement in any other language shall be for accommodation + only and shall not be binding. All communications and notices made + or given pursuant to this Agreement, and all documentation and + support to be provided, unless otherwise noted, shall be in the + English language. + diff --git a/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c b/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c new file mode 100644 index 0000000000..6acdeb3b60 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.c @@ -0,0 +1,142 @@ +/** @file + Source file for FSP notify phase PEI module + + Copyright (c) 2016, Intel Corporation. All rights reserved. + 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. +**/ + +#include "FspNotifyPhasePeim.h" + +/** + + This function waits for FSP notify. + + @param This Entry point for DXE IPL PPI. + @param PeiServices General purpose services available to every PEIM. + @param HobList Address to the Pei HOB list. + + @return EFI_SUCCESS This function never returns. + +**/ +EFI_STATUS +EFIAPI +WaitForNotify ( + IN CONST EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ); + +CONST EFI_DXE_IPL_PPI mDxeIplPpi = { + WaitForNotify +}; + +CONST EFI_PEI_PPI_DESCRIPTOR mInstallDxeIplPpi = { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiDxeIplPpiGuid, + (VOID *) &mDxeIplPpi +}; + +CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + NULL +}; + +/** + + This function waits for FSP notify. + + @param This Entry point for DXE IPL PPI. + @param PeiServices General purpose services available to every PEIM. + @param HobList Address to the Pei HOB list. + + @return EFI_SUCCESS This function never returns. + +**/ +EFI_STATUS +EFIAPI +WaitForNotify ( + IN CONST EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ) +{ + EFI_STATUS Status; + + DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP HOB is located at 0x%08X\n", HobList)); + + // + // End of PEI phase signal + // + Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi); + ASSERT_EFI_ERROR (Status); + + // + // Give control back to BootLoader after FspSiliconInit + // + DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP is waiting for NOTIFY\n")); + FspSiliconInitDone (); + + // + // BootLoader called FSP again through NotifyPhase + // + FspWaitForNotify (); + + // + // Should not come here + // + while (TRUE) { + DEBUG ((DEBUG_ERROR, "No FSP API should be called after FSP is DONE!\n")); + SetFspApiReturnStatus (EFI_UNSUPPORTED); + Pei2LoaderSwitchStack (); + } + + return EFI_SUCCESS; +} + +/** + FSP notify phase PEI module entry point + + @param[in] FileHandle Not used. + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The function completes successfully + @retval EFI_OUT_OF_RESOURCES Insufficient resources to create database +**/ +EFI_STATUS +FspNotifyPhasePeimEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + VOID *OldDxeIplPpi; + EFI_PEI_PPI_DESCRIPTOR *OldDescriptor; + + DEBUG ((DEBUG_INFO | DEBUG_INIT, "The entry of FspNotificationPeim\n")); + + // + // Locate old DXE IPL PPI + // + Status = PeiServicesLocatePpi ( + &gEfiDxeIplPpiGuid, + 0, + &OldDescriptor, + &OldDxeIplPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Re-install the DXE IPL PPI to wait for notify + // + Status = PeiServicesReInstallPpi (OldDescriptor, &mInstallDxeIplPpi); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h b/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h new file mode 100644 index 0000000000..6e2ae591ec --- /dev/null +++ b/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.h @@ -0,0 +1,23 @@ +/** @file + Header file for FSP notify phase PEI module + + Copyright (c) 2016 Intel Corporation. All rights reserved. + 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. +**/ + +#ifndef _FSP_NOTIFY_PHASE_PEIM_H_ +#define _FSP_NOTIFY_PHASE_PEIM_H_ + +#include +#include +#include +#include +#include +#include +#endif diff --git a/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf b/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf new file mode 100644 index 0000000000..75f7ae5fb7 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf @@ -0,0 +1,49 @@ +## @file +# Component information file for the FSP notify phase PEI module. +# +#@copyright +# Copyright (c) 2016 Intel Corporation. All rights reserved. +# 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. +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FspNotifyPhasePeim + FILE_GUID = 29CBB005-C972-49F3-960F-292E2202CECD + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = FspNotifyPhasePeimEntryPoint + +[Sources] + FspNotifyPhasePeim.h + FspNotifyPhasePeim.c + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + PeimEntryPoint + DebugLib + FspPlatformLib + FspCommonLib + FspSwitchStackLib + +[Ppis] + gEfiDxeIplPpiGuid ## PRODUCES + gEfiEndOfPeiSignalPpiGuid ## PRODUCES + +[Protocols] + gEfiPciEnumerationCompleteProtocolGuid ## PRODUCES + +[Guids] + gEfiEventReadyToBootGuid ## PRODUCES ## Event + +[Depex] + gEfiDxeIplPpiGuid diff --git a/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf b/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf new file mode 100644 index 0000000000..611fab215a --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf @@ -0,0 +1,74 @@ +## @file +# Sec Core for FSP +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FspSecCoreM + FILE_GUID = C2F9AE46-3437-4FEF-9CB1-9A568B282FEE + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources] + SecMain.c + SecMain.h + SecFsp.c + SecFsp.h + SecFspApiChk.c + +[Sources.IA32] + Ia32/Stack.nasm + Ia32/InitializeFpu.nasm + Ia32/FspApiEntryM.nasm + Ia32/FspApiEntryCommon.nasm + Ia32/FspHelper.nasm + +[Binaries.Ia32] + RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + PciCf8Lib + SerialPortLib + FspSwitchStackLib + FspCommonLib + FspSecPlatformLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## UNDEFINED + gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage ## CONSUMES + +[FixedPcd] + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry ## CONSUMES + +[Ppis] + gEfiTemporaryRamSupportPpiGuid ## PRODUCES + diff --git a/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf b/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf new file mode 100644 index 0000000000..8e1bb4a592 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf @@ -0,0 +1,68 @@ +## @file +# Sec Core for FSP +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FspSecCoreS + FILE_GUID = 53AB1ACD-EDB1-4E3A-A2C7-978D721D179D + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources] + SecFspApiChk.c + +[Sources.IA32] + Ia32/Stack.nasm + Ia32/FspApiEntryS.nasm + Ia32/FspApiEntryCommon.nasm + Ia32/FspHelper.nasm + +[Binaries.Ia32] + RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + PciCf8Lib + SerialPortLib + FspSwitchStackLib + FspCommonLib + FspSecPlatformLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## UNDEFINED + gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES + +[FixedPcd] + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry ## CONSUMES + +[Ppis] + gEfiTemporaryRamSupportPpiGuid ## PRODUCES + diff --git a/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf b/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf new file mode 100644 index 0000000000..cf6a1918a3 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf @@ -0,0 +1,66 @@ +## @file +# Sec Core for FSP +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FspSecCoreT + FILE_GUID = 5B94E419-C795-414D-A0D4-B80A877BE5FE + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources] + + +[Sources.IA32] + Ia32/Stack.nasm + Ia32/InitializeFpu.nasm + Ia32/FspApiEntryT.nasm + Ia32/FspHelper.nasm + +[Binaries.Ia32] + RAW|Vtf0/Bin/ResetVec.ia32.raw |GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + BaseLib + PciCf8Lib + SerialPortLib + FspSwitchStackLib + FspCommonLib + FspSecPlatformLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## UNDEFINED + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize ## CONSUMES + +[FixedPcd] + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry ## CONSUMES + +[Ppis] + gEfiTemporaryRamSupportPpiGuid ## PRODUCES diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm new file mode 100644 index 0000000000..c48a95694c --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryCommon.nasm @@ -0,0 +1,76 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; 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. +;; + + SECTION .text + +; +; Following functions will be provided in C +; +extern ASM_PFX(Loader2PeiSwitchStack) +extern ASM_PFX(FspApiCallingCheck) + +; +; Following functions will be provided in ASM +; +extern ASM_PFX(FspApiCommonContinue) +extern ASM_PFX(AsmGetFspInfoHeader) + +;---------------------------------------------------------------------------- +; FspApiCommon API +; +; This is the FSP API common entry point to resume the FSP execution +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspApiCommon) +ASM_PFX(FspApiCommon): + ; + ; EAX holds the API index + ; + + ; + ; Stack must be ready + ; + push eax + add esp, 4 + cmp eax, dword [esp - 4] + jz FspApiCommon1 + mov eax, 080000003h + jmp exit + +FspApiCommon1: + ; + ; Verify the calling condition + ; + pushad + push DWORD [esp + (4 * 8 + 4)] ; push ApiParam + push eax ; push ApiIdx + call ASM_PFX(FspApiCallingCheck) + add esp, 8 + cmp eax, 0 + jz FspApiCommon2 + mov dword [esp + (4 * 7)], eax + popad +exit: + ret + +FspApiCommon2: + popad + cmp eax, 3 ; FspMemoryInit API + jz FspApiCommon3 + + call ASM_PFX(AsmGetFspInfoHeader) + jmp ASM_PFX(Loader2PeiSwitchStack) + +FspApiCommon3: + jmp ASM_PFX(FspApiCommonContinue) + diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm new file mode 100644 index 0000000000..9744e1682d --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryM.nasm @@ -0,0 +1,202 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; 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. +;; + + SECTION .text + +; +; Following are fixed PCDs +; +extern ASM_PFX(PcdGet32(PcdTemporaryRamBase)) +extern ASM_PFX(PcdGet32(PcdTemporaryRamSize)) +extern ASM_PFX(PcdGet32(PcdFspTemporaryRamSize)) + +struc FSPM_UPD_COMMON + ; FSP_UPD_HEADER { + .FspUpdHeader: resd 8 + ; } + ; FSPM_ARCH_UPD { + .Revision: resb 1 + .Reserved: resb 3 + .NvsBufferPtr: resd 1 + .StackBase: resd 1 + .StackSize: resd 1 + .BootLoaderTolumSize: resd 1 + .BootMode: resd 1 + .Reserved1: resb 8 + ; } + .size: +endstruc + +; +; Following functions will be provided in C +; +extern ASM_PFX(SecStartup) +extern ASM_PFX(FspApiCommon) + +; +; Following functions will be provided in PlatformSecLib +; +extern ASM_PFX(AsmGetFspBaseAddress) +extern ASM_PFX(AsmGetFspInfoHeader) + +API_PARAM1_OFFSET EQU 34h ; ApiParam1 [ sub esp,8 + pushad + pushfd + push eax + call] +FSP_HEADER_IMGBASE_OFFSET EQU 1Ch +FSP_HEADER_CFGREG_OFFSET EQU 24h + +;---------------------------------------------------------------------------- +; FspMemoryInit API +; +; This FSP API is called after TempRamInit and initializes the memory. +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspMemoryInitApi) +ASM_PFX(FspMemoryInitApi): + mov eax, 3 ; FSP_API_INDEX.FspMemoryInitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; TempRamExitApi API +; +; This API tears down temporary RAM +; +;---------------------------------------------------------------------------- +global ASM_PFX(TempRamExitApi) +ASM_PFX(TempRamExitApi): + mov eax, 4 ; FSP_API_INDEX.TempRamExitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspApiCommonContinue API +; +; This is the FSP API common entry point to resume the FSP execution +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspApiCommonContinue) +ASM_PFX(FspApiCommonContinue): + ; + ; EAX holds the API index + ; + + ; + ; FspMemoryInit API setup the initial stack frame + ; + + ; + ; Place holder to store the FspInfoHeader pointer + ; + push eax + + ; + ; Update the FspInfoHeader pointer + ; + push eax + call ASM_PFX(AsmGetFspInfoHeader) + mov [esp + 4], eax + pop eax + + ; + ; Create a Task Frame in the stack for the Boot Loader + ; + pushfd ; 2 pushf for 4 byte alignment + cli + pushad + + ; Reserve 8 bytes for IDT save/restore + sub esp, 8 + sidt [esp] + + + ; Get Stackbase and StackSize from FSPM_UPD Param + mov edx, [esp + API_PARAM1_OFFSET] + cmp edx, 0 + jnz FspStackSetup + + ; Get UPD default values if FspmUpdDataPtr (ApiParam1) is null + push eax + call ASM_PFX(AsmGetFspInfoHeader) + mov edx, [eax + FSP_HEADER_IMGBASE_OFFSET] + add edx, [eax + FSP_HEADER_CFGREG_OFFSET] + pop eax + + FspStackSetup: + mov edi, [edx + FSPM_UPD_COMMON.StackBase] + mov ecx, [edx + FSPM_UPD_COMMON.StackSize] + add edi, ecx + ; + ; Setup new FSP stack + ; + xchg edi, esp ; Exchange edi and esp, edi will be assigned to the current esp pointer and esp will be Stack base + Stack size + mov ebx, esp ; Put Stack base + Stack size in ebx + + ; + ; Pass the API Idx to SecStartup + ; + push eax + + ; + ; Pass the BootLoader stack to SecStartup + ; + push edi + + ; + ; Pass entry point of the PEI core + ; + call ASM_PFX(AsmGetFspBaseAddress) + mov edi, eax + call ASM_PFX(AsmGetPeiCoreOffset) + add edi, eax + push edi + + ; + ; Pass BFV into the PEI Core + ; It uses relative address to calucate the actual boot FV base + ; For FSP implementation with single FV, PcdFspBootFirmwareVolumeBase and + ; PcdFspAreaBaseAddress are the same. For FSP with mulitple FVs, + ; they are different. The code below can handle both cases. + ; + call ASM_PFX(AsmGetFspBaseAddress) + push eax + + ; + ; Pass stack base and size into the PEI Core + ; + sub ebx, ecx ; Stack base + Stack size - Stack size + push ebx + push ecx + + ; + ; Pass Control into the PEI Core + ; + call ASM_PFX(SecStartup) + add esp, 4 +exit: + ret + +global ASM_PFX(FspPeiCoreEntryOff) +ASM_PFX(FspPeiCoreEntryOff): + ; + ; This value will be pached by the build script + ; + DD 0x12345678 + +global ASM_PFX(AsmGetPeiCoreOffset) +ASM_PFX(AsmGetPeiCoreOffset): + mov eax, dword [ASM_PFX(FspPeiCoreEntryOff)] + ret + +;---------------------------------------------------------------------------- +; Module Entrypoint API +;---------------------------------------------------------------------------- +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + jmp $ diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm new file mode 100644 index 0000000000..cdc1149d6c --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryS.nasm @@ -0,0 +1,62 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; 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. +;; + + SECTION .text + +; +; Following functions will be provided in C +; +extern ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; NotifyPhase API +; +; This FSP API will notify the FSP about the different phases in the boot +; process +; +;---------------------------------------------------------------------------- +global ASM_PFX(NotifyPhaseApi) +ASM_PFX(NotifyPhaseApi): + mov eax, 2 ; FSP_API_INDEX.NotifyPhaseApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspSiliconInit API +; +; This FSP API initializes the CPU and the chipset including the IO +; controllers in the chipset to enable normal operation of these devices. +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspSiliconInitApi) +ASM_PFX(FspSiliconInitApi): + mov eax, 5 ; FSP_API_INDEX.FspSiliconInitApiIndex + jmp ASM_PFX(FspApiCommon) + +;---------------------------------------------------------------------------- +; FspApiCommonContinue API +; +; This is the FSP API common entry point to resume the FSP execution +; +;---------------------------------------------------------------------------- +global ASM_PFX(FspApiCommonContinue) +ASM_PFX(FspApiCommonContinue): + jmp $ + ret + +;---------------------------------------------------------------------------- +; Module Entrypoint API +;---------------------------------------------------------------------------- +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + jmp $ + diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm new file mode 100644 index 0000000000..6e860238fd --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm @@ -0,0 +1,477 @@ +;; @file +; Provide FSP API entry points. +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; 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. +;; + + SECTION .text + +%include "SaveRestoreSseNasm.inc" +%include "MicrocodeLoadNasm.inc" + +; +; Following are fixed PCDs +; +extern ASM_PFX(PcdGet32 (PcdTemporaryRamBase)) +extern ASM_PFX(PcdGet32 (PcdTemporaryRamSize)) +extern ASM_PFX(PcdGet32 (PcdFspReservedBufferSize)) + +; +; Following functions will be provided in PlatformSecLib +; +extern ASM_PFX(AsmGetFspBaseAddress) +extern ASM_PFX(AsmGetFspInfoHeader) +;extern ASM_PFX(LoadMicrocode) ; @todo: needs a weak implementation +extern ASM_PFX(SecPlatformInit) ; @todo: needs a weak implementation +extern ASM_PFX(SecCarInit) + +; +; Define the data length that we saved on the stack top +; +DATA_LEN_OF_PER0 EQU 18h +DATA_LEN_OF_MCUD EQU 18h +DATA_LEN_AT_STACK_TOP EQU (DATA_LEN_OF_PER0 + DATA_LEN_OF_MCUD + 4) + +; +; @todo: These structures are moved from MicrocodeLoadNasm.inc to avoid +; build error. This needs to be fixed later on. +; +struc MicrocodeHdr + .MicrocodeHdrVersion: resd 1 + .MicrocodeHdrRevision: resd 1 + .MicrocodeHdrDate: resd 1 + .MicrocodeHdrProcessor: resd 1 + .MicrocodeHdrChecksum: resd 1 + .MicrocodeHdrLoader: resd 1 + .MicrocodeHdrFlags: resd 1 + .MicrocodeHdrDataSize: resd 1 + .MicrocodeHdrTotalSize: resd 1 + .MicrocodeHdrRsvd: resd 3 + .size: +endstruc + +struc ExtSigHdr + .ExtSigHdrCount: resd 1 + .ExtSigHdrChecksum: resd 1 + .ExtSigHdrRsvd: resd 3 + .size: +endstruc + +struc ExtSig + .ExtSigProcessor: resd 1 + .ExtSigFlags: resd 1 + .ExtSigChecksum: resd 1 + .size: +endstruc + +struc LoadMicrocodeParams + ; FSP_UPD_HEADER { + .FspUpdHeader: resd 8 + ; } + ; FSPT_CORE_UPD { + .MicrocodeCodeAddr: resd 1 + .MicrocodeCodeSize: resd 1 + .CodeRegionBase: resd 1 + .CodeRegionSize: resd 1 + ; } + .size: +endstruc + + +; +; Define SSE macros +; +; +;args 1: ReturnAddress 2:MmxRegister +; +%macro LOAD_MMX_EXT 2 + mov esi, %1 + movd %2, esi ; save ReturnAddress into MMX +%endmacro + +; +;args 1: RoutineLabel 2:MmxRegister +; +%macro CALL_MMX_EXT 2 + mov esi, %%ReturnAddress + movd %2, esi ; save ReturnAddress into MMX + jmp %1 +%%ReturnAddress: +%endmacro + +; +;arg 1:MmxRegister +; +%macro RET_ESI_EXT 1 + movd esi, %1 ; move ReturnAddress from MMX to ESI + jmp esi +%endmacro + +; +;arg 1:RoutineLabel +; +%macro CALL_MMX 1 + CALL_MMX_EXT %1, mm7 +%endmacro + +%macro RET_ESI 0 + RET_ESI_EXT mm7 +%endmacro + +; +; @todo: The strong/weak implementation does not work. +; This needs to be reviewed later. +; +;------------------------------------------------------------------------------ +; +;;global ASM_PFX(SecPlatformInitDefault) +;ASM_PFX(SecPlatformInitDefault): +; ; Inputs: +; ; mm7 -> Return address +; ; Outputs: +; ; eax -> 0 - Successful, Non-zero - Failed. +; ; Register Usage: +; ; eax is cleared and ebp is used for return address. +; ; All others reserved. +; +; ; Save return address to EBP +; movd ebp, mm7 +; +; xor eax, eax +;Exit1: +; jmp ebp + +;------------------------------------------------------------------------------ +global ASM_PFX(LoadMicrocodeDefault) +ASM_PFX(LoadMicrocodeDefault): + ; Inputs: + ; esp -> LoadMicrocodeParams pointer + ; Register Usage: + ; esp Preserved + ; All others destroyed + ; Assumptions: + ; No memory available, stack is hard-coded and used for return address + ; Executed by SBSP and NBSP + ; Beginning of microcode update region starts on paragraph boundary + + ; + ; + ; Save return address to EBP + movd ebp, mm7 + + cmp esp, 0 + jz ParamError + mov eax, dword [esp + 4] ; Parameter pointer + cmp eax, 0 + jz ParamError + mov esp, eax + + ; skip loading Microcode if the MicrocodeCodeSize is zero + ; and report error if size is less than 2k + mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize] + cmp eax, 0 + jz Exit2 + cmp eax, 0800h + jl ParamError + + mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr] + cmp esi, 0 + jnz CheckMainHeader + +ParamError: + mov eax, 080000002h + jmp Exit2 + +CheckMainHeader: + ; Get processor signature and platform ID from the installed processor + ; and save into registers for later use + ; ebx = processor signature + ; edx = platform ID + mov eax, 1 + cpuid + mov ebx, eax + mov ecx, MSR_IA32_PLATFORM_ID + rdmsr + mov ecx, edx + shr ecx, 50-32 ; shift (50d-32d=18d=0x12) bits + and ecx, 7h ; platform id at bit[52..50] + mov edx, 1 + shl edx, cl + + ; Current register usage + ; esp -> stack with parameters + ; esi -> microcode update to check + ; ebx = processor signature + ; edx = platform ID + + ; Check for valid microcode header + ; Minimal test checking for header version and loader version as 1 + mov eax, dword 1 + cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], eax + jne AdvanceFixedSize + cmp dword [esi + MicrocodeHdr.MicrocodeHdrLoader], eax + jne AdvanceFixedSize + + ; Check if signature and plaform ID match + cmp ebx, dword [esi + MicrocodeHdr.MicrocodeHdrProcessor] + jne LoadMicrocodeDefault1 + test edx, dword [esi + MicrocodeHdr.MicrocodeHdrFlags ] + jnz LoadCheck ; Jif signature and platform ID match + +LoadMicrocodeDefault1: + ; Check if extended header exists + ; First check if MicrocodeHdrTotalSize and MicrocodeHdrDataSize are valid + xor eax, eax + cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax + je NextMicrocode + cmp dword [esi + MicrocodeHdr.MicrocodeHdrDataSize], eax + je NextMicrocode + + ; Then verify total size - sizeof header > data size + mov ecx, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize] + sub ecx, MicrocodeHdr.size + cmp ecx, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize] + jng NextMicrocode ; Jif extended header does not exist + + ; Set edi -> extended header + mov edi, esi + add edi, MicrocodeHdr.size + add edi, dword [esi + MicrocodeHdr.MicrocodeHdrDataSize] + + ; Get count of extended structures + mov ecx, dword [edi + ExtSigHdr.ExtSigHdrCount] + + ; Move pointer to first signature structure + add edi, ExtSigHdr.size + +CheckExtSig: + ; Check if extended signature and platform ID match + cmp dword [edi + ExtSig.ExtSigProcessor], ebx + jne LoadMicrocodeDefault2 + test dword [edi + ExtSig.ExtSigFlags], edx + jnz LoadCheck ; Jif signature and platform ID match +LoadMicrocodeDefault2: + ; Check if any more extended signatures exist + add edi, ExtSig.size + loop CheckExtSig + +NextMicrocode: + ; Advance just after end of this microcode + xor eax, eax + cmp dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize], eax + je LoadMicrocodeDefault3 + add esi, dword [esi + MicrocodeHdr.MicrocodeHdrTotalSize] + jmp CheckAddress +LoadMicrocodeDefault3: + add esi, dword 2048 + jmp CheckAddress + +AdvanceFixedSize: + ; Advance by 4X dwords + add esi, dword 1024 + +CheckAddress: + ; Is valid Microcode start point ? + cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh + jz Done + + ; Is automatic size detection ? + mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize] + cmp eax, 0ffffffffh + jz LoadMicrocodeDefault4 + + ; Address >= microcode region address + microcode region size? + add eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr] + cmp esi, eax + jae Done ;Jif address is outside of microcode region + jmp CheckMainHeader + +LoadMicrocodeDefault4: +LoadCheck: + ; Get the revision of the current microcode update loaded + mov ecx, MSR_IA32_BIOS_SIGN_ID + xor eax, eax ; Clear EAX + xor edx, edx ; Clear EDX + wrmsr ; Load 0 to MSR at 8Bh + + mov eax, 1 + cpuid + mov ecx, MSR_IA32_BIOS_SIGN_ID + rdmsr ; Get current microcode signature + + ; Verify this microcode update is not already loaded + cmp dword [esi + MicrocodeHdr.MicrocodeHdrRevision], edx + je Continue + +LoadMicrocode: + ; EAX contains the linear address of the start of the Update Data + ; EDX contains zero + ; ECX contains 79h (IA32_BIOS_UPDT_TRIG) + ; Start microcode load with wrmsr + mov eax, esi + add eax, MicrocodeHdr.size + xor edx, edx + mov ecx, MSR_IA32_BIOS_UPDT_TRIG + wrmsr + mov eax, 1 + cpuid + +Continue: + jmp NextMicrocode + +Done: + mov eax, 1 + cpuid + mov ecx, MSR_IA32_BIOS_SIGN_ID + rdmsr ; Get current microcode signature + xor eax, eax + cmp edx, 0 + jnz Exit2 + mov eax, 08000000Eh + +Exit2: + jmp ebp + + +global ASM_PFX(EstablishStackFsp) +ASM_PFX(EstablishStackFsp): + ; + ; Save parameter pointer in edx + ; + mov edx, dword [esp + 4] + + ; + ; Enable FSP STACK + ; + mov esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))] + add esp, DWORD [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))] + + push DATA_LEN_OF_MCUD ; Size of the data region + push 4455434Dh ; Signature of the data region 'MCUD' + push dword [edx + 2Ch] ; Code size sizeof(FSPT_UPD_COMMON) + 12 + push dword [edx + 28h] ; Code base sizeof(FSPT_UPD_COMMON) + 8 + push dword [edx + 24h] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4 + push dword [edx + 20h] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0 + + ; + ; Save API entry/exit timestamp into stack + ; + push DATA_LEN_OF_PER0 ; Size of the data region + push 30524550h ; Signature of the data region 'PER0' + rdtsc + push edx + push eax + LOAD_EDX + push edx + LOAD_EAX + push eax + + ; + ; Terminator for the data on stack + ; + push 0 + + ; + ; Set ECX/EDX to the BootLoader temporary memory range + ; + mov ecx, [ASM_PFX(PcdGet32 (PcdTemporaryRamBase))] + mov edx, ecx + add edx, [ASM_PFX(PcdGet32 (PcdTemporaryRamSize))] + sub edx, [ASM_PFX(PcdGet32 (PcdFspReservedBufferSize))] + + cmp ecx, edx ;If PcdFspReservedBufferSize >= PcdTemporaryRamSize, then error. + jb EstablishStackFspSuccess + mov eax, 80000003h ;EFI_UNSUPPORTED + jmp EstablishStackFspExit +EstablishStackFspSuccess: + xor eax, eax + +EstablishStackFspExit: + RET_ESI + +;---------------------------------------------------------------------------- +; TempRamInit API +; +; This FSP API will load the microcode update, enable code caching for the +; region specified by the boot loader and also setup a temporary stack to be +; used till main memory is initialized. +; +;---------------------------------------------------------------------------- +global ASM_PFX(TempRamInitApi) +ASM_PFX(TempRamInitApi): + ; + ; Ensure SSE is enabled + ; + ENABLE_SSE + + ; + ; Save EBP, EBX, ESI, EDI & ESP in XMM7 & XMM6 + ; + SAVE_REGS + + ; + ; Save timestamp into XMM6 + ; + rdtsc + SAVE_EAX + SAVE_EDX + + ; + ; Check Parameter + ; + mov eax, dword [esp + 4] + cmp eax, 0 + mov eax, 80000002h + jz TempRamInitExit + + ; + ; Sec Platform Init + ; + CALL_MMX ASM_PFX(SecPlatformInit) + cmp eax, 0 + jnz TempRamInitExit + + ; Load microcode + LOAD_ESP + CALL_MMX ASM_PFX(LoadMicrocodeDefault) + SXMMN xmm6, 3, eax ;Save microcode return status in ECX-SLOT 3 in xmm6. + ;@note If return value eax is not 0, microcode did not load, but continue and attempt to boot. + + ; Call Sec CAR Init + LOAD_ESP + CALL_MMX ASM_PFX(SecCarInit) + cmp eax, 0 + jnz TempRamInitExit + + LOAD_ESP + CALL_MMX ASM_PFX(EstablishStackFsp) + cmp eax, 0 + jnz TempRamInitExit + + LXMMN xmm6, eax, 3 ;Restore microcode status if no CAR init error from ECX-SLOT 3 in xmm6. + +TempRamInitExit: + mov bl, al ; save al data in bl + mov al, 07Fh ; API exit postcode 7f + out 080h, al + mov al, bl ; restore al data from bl + + ; + ; Load EBP, EBX, ESI, EDI & ESP from XMM7 & XMM6 + ; + LOAD_REGS + ret + +;---------------------------------------------------------------------------- +; Module Entrypoint API +;---------------------------------------------------------------------------- +global ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + jmp $ diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm new file mode 100644 index 0000000000..00e953b4f1 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/FspHelper.nasm @@ -0,0 +1,35 @@ +;; @file +; Provide FSP helper function. +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; 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. +;; + + SECTION .text + +global ASM_PFX(FspInfoHeaderRelativeOff) +ASM_PFX(FspInfoHeaderRelativeOff): + ; + ; This value will be pached by the build script + ; + DD 0x12345678 + +global ASM_PFX(AsmGetFspBaseAddress) +ASM_PFX(AsmGetFspBaseAddress): + mov eax, ASM_PFX(AsmGetFspInfoHeader) + sub eax, dword [ASM_PFX(FspInfoHeaderRelativeOff)] + add eax, 0x1C + mov eax, dword [eax] + ret + +global ASM_PFX(AsmGetFspInfoHeader) +ASM_PFX(AsmGetFspInfoHeader): + mov eax, ASM_PFX(AsmGetFspInfoHeader) + sub eax, dword [ASM_PFX(FspInfoHeaderRelativeOff)] + ret diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm b/Core/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm new file mode 100644 index 0000000000..cc87e893d5 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; 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. +; +; Abstract: +; +;------------------------------------------------------------------------------ + + +SECTION .data +; +; Float control word initial value: +; all exceptions masked, double-precision, round-to-nearest +; +ASM_PFX(mFpuControlWord): + dw 0x027F +; +; Multimedia-extensions control word: +; all exceptions masked, round-to-nearest, flush to zero for masked underflow +; +ASM_PFX(mMmxControlWord): + dd 0x01F80 + +SECTION .text + +; +; Initializes floating point units for requirement of UEFI specification. +; +; This function initializes floating-point control word to 0x027F (all exceptions +; masked,double-precision, round-to-nearest) and multimedia-extensions control word +; (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero +; for masked underflow). +; + +global ASM_PFX(InitializeFloatingPointUnits) +ASM_PFX(InitializeFloatingPointUnits): + + + push ebx + + ; + ; Initialize floating point units + ; + finit + fldcw [ASM_PFX(mFpuControlWord)] + + ; + ; Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test + ; whether the processor supports SSE instruction. + ; + mov eax, 1 + cpuid + bt edx, 25 + jnc Done + + ; + ; Set OSFXSR bit 9 in CR4 + ; + mov eax, cr4 + or eax, BIT9 + mov cr4, eax + + ; + ; The processor should support SSE instruction and we can use + ; ldmxcsr instruction + ; + ldmxcsr [ASM_PFX(mMmxControlWord)] +Done: + pop ebx + + ret diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc b/Core/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc new file mode 100644 index 0000000000..1663a85d11 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/MicrocodeLoadNasm.inc @@ -0,0 +1,16 @@ +;; @file +; +;@copyright +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; 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. +;; + +MSR_IA32_PLATFORM_ID equ 000000017h +MSR_IA32_BIOS_UPDT_TRIG equ 000000079h +MSR_IA32_BIOS_SIGN_ID equ 00000008bh \ No newline at end of file diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc b/Core/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc new file mode 100644 index 0000000000..ae0a93dc94 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/SaveRestoreSseNasm.inc @@ -0,0 +1,187 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; 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. +; +; Abstract: +; +; Provide macro for register save/restore using SSE registers +; +;------------------------------------------------------------------------------ + +; +; Define SSE instruction set +; +%ifdef USE_SSE41_FLAG +; +; Define SSE macros using SSE 4.1 instructions +; args 1:XMM, 2:IDX, 3:REG +%macro SXMMN 3 + pinsrd %1, %3, (%2 & 3) + %endmacro + +; +;args 1:XMM, 2:REG, 3:IDX +; +%macro LXMMN 3 + pextrd %2, %1, (%3 & 3) + %endmacro +%else +; +; Define SSE macros using SSE 2 instructions +; args 1:XMM, 2:IDX, 3:REG +%macro SXMMN 3 + pinsrw %1, %3, (%2 & 3) * 2 + ror %3, 16 + pinsrw %1, %3, (%2 & 3) * 2 + 1 + rol %3, 16 + %endmacro + +; +;args 1:XMM, 2:REG, 3:IDX +; +%macro LXMMN 3 + pshufd %1, %1, ((0E4E4E4h >> (%3 * 2)) & 0FFh) + movd %2, %1 + pshufd %1, %1, ((0E4E4E4h >> (%3 * 2 + (%3 & 1) * 4)) & 0FFh) + %endmacro +%endif + +; +; XMM7 to save/restore EBP, EBX, ESI, EDI +; +%macro SAVE_REGS 0 + SXMMN xmm7, 0, ebp + SXMMN xmm7, 1, ebx + SXMMN xmm7, 2, esi + SXMMN xmm7, 3, edi + SAVE_ESP + %endmacro + +%macro LOAD_REGS 0 + LXMMN xmm7, ebp, 0 + LXMMN xmm7, ebx, 1 + LXMMN xmm7, esi, 2 + LXMMN xmm7, edi, 3 + LOAD_ESP + %endmacro + +; +; XMM6 to save/restore EAX, EDX, ECX, ESP +; +%macro LOAD_EAX 0 + LXMMN xmm6, eax, 1 + %endmacro + +%macro SAVE_EAX 0 + SXMMN xmm6, 1, eax + %endmacro + +%macro LOAD_EDX 0 + LXMMN xmm6, edx, 2 + %endmacro + +%macro SAVE_EDX 0 + SXMMN xmm6, 2, edx + %endmacro + +%macro SAVE_ECX 0 + SXMMN xmm6, 3, ecx + %endmacro + +%macro LOAD_ECX 0 + LXMMN xmm6, ecx, 3 + %endmacro + +%macro SAVE_ESP 0 + SXMMN xmm6, 0, esp + %endmacro + +%macro LOAD_ESP 0 + movd esp, xmm6 + %endmacro +; +; XMM5 for calling stack +; arg 1:Entry +%macro CALL_XMM 1 + mov esi, %%ReturnAddress + pslldq xmm5, 4 +%ifdef USE_SSE41_FLAG + pinsrd xmm5, esi, 0 +%else + pinsrw xmm5, esi, 0 + ror esi, 16 + pinsrw xmm5, esi, 1 +%endif + mov esi, %1 + jmp esi +%%ReturnAddress: + %endmacro + +%macro RET_XMM 0 + movd esi, xmm5 + psrldq xmm5, 4 + jmp esi + %endmacro + +%macro ENABLE_SSE 0 + ; + ; Initialize floating point units + ; + jmp NextAddress +align 4 + ; + ; Float control word initial value: + ; all exceptions masked, double-precision, round-to-nearest + ; +FpuControlWord DW 027Fh + ; + ; Multimedia-extensions control word: + ; all exceptions masked, round-to-nearest, flush to zero for masked underflow + ; +MmxControlWord DD 01F80h +SseError: + ; + ; Processor has to support SSE + ; + jmp SseError +NextAddress: + finit + fldcw [FpuControlWord] + + ; + ; Use CpuId instructuion (CPUID.01H:EDX.SSE[bit 25] = 1) to test + ; whether the processor supports SSE instruction. + ; + mov eax, 1 + cpuid + bt edx, 25 + jnc SseError + +%ifdef USE_SSE41_FLAG + ; + ; SSE 4.1 support + ; + bt ecx, 19 + jnc SseError +%endif + + ; + ; Set OSFXSR bit (bit #9) & OSXMMEXCPT bit (bit #10) + ; + mov eax, cr4 + or eax, 00000600h + mov cr4, eax + + ; + ; The processor should support SSE instruction and we can use + ; ldmxcsr instruction + ; + ldmxcsr [MmxControlWord] + %endmacro diff --git a/Core/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm b/Core/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm new file mode 100644 index 0000000000..338e700751 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Ia32/Stack.nasm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; 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. +; +; Abstract: +; +; Switch the stack from temporary memory to permanent memory. +; +;------------------------------------------------------------------------------ + +SECTION .text + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; SecSwitchStack ( +; UINT32 TemporaryMemoryBase, +; UINT32 PermenentMemoryBase +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(SecSwitchStack) +ASM_PFX(SecSwitchStack): + ; + ; Save three register: eax, ebx, ecx + ; + push eax + push ebx + push ecx + push edx + + ; + ; !!CAUTION!! this function address's is pushed into stack after + ; migration of whole temporary memory, so need save it to permanent + ; memory at first! + ; + + mov ebx, [esp + 20] ; Save the first parameter + mov ecx, [esp + 24] ; Save the second parameter + + ; + ; Save this function's return address into permanent memory at first. + ; Then, Fixup the esp point to permanent memory + ; + mov eax, esp + sub eax, ebx + add eax, ecx + mov edx, dword [esp] ; copy pushed register's value to permanent memory + mov dword [eax], edx + mov edx, dword [esp + 4] + mov dword [eax + 4], edx + mov edx, dword [esp + 8] + mov dword [eax + 8], edx + mov edx, dword [esp + 12] + mov dword [eax + 12], edx + mov edx, dword [esp + 16] ; Update this function's return address into permanent memory + mov dword [eax + 16], edx + mov esp, eax ; From now, esp is pointed to permanent memory + + ; + ; Fixup the ebp point to permenent memory + ; + mov eax, ebp + sub eax, ebx + add eax, ecx + mov ebp, eax ; From now, ebp is pointed to permanent memory + + pop edx + pop ecx + pop ebx + pop eax + ret diff --git a/Core/IntelFsp2Pkg/FspSecCore/SecFsp.c b/Core/IntelFsp2Pkg/FspSecCore/SecFsp.c new file mode 100644 index 0000000000..96f8fb7554 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/SecFsp.c @@ -0,0 +1,214 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include "SecFsp.h" + +/** + + Calculate the FSP IDT gate descriptor. + + @param[in] IdtEntryTemplate IDT gate descriptor template. + + @return FSP specific IDT gate descriptor. + +**/ +UINT64 +FspGetExceptionHandler( + IN UINT64 IdtEntryTemplate + ) +{ + UINT32 Entry; + UINT64 ExceptionHandler; + IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor; + FSP_INFO_HEADER *FspInfoHeader; + + FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader(); + ExceptionHandler = IdtEntryTemplate; + IdtGateDescriptor = (IA32_IDT_GATE_DESCRIPTOR *)&ExceptionHandler; + Entry = (IdtGateDescriptor->Bits.OffsetHigh << 16) | IdtGateDescriptor->Bits.OffsetLow; + Entry = FspInfoHeader->ImageBase + FspInfoHeader->ImageSize - (~Entry + 1); + IdtGateDescriptor->Bits.OffsetHigh = (UINT16)(Entry >> 16); + IdtGateDescriptor->Bits.OffsetLow = (UINT16)Entry; + + return ExceptionHandler; +} + +/** + This interface fills platform specific data. + + @param[in,out] FspData Pointer to the FSP global data. + +**/ +VOID +EFIAPI +SecGetPlatformData ( + IN OUT FSP_GLOBAL_DATA *FspData + ) +{ + FSP_PLAT_DATA *FspPlatformData; + UINT32 TopOfCar; + UINT32 *StackPtr; + UINT32 DwordSize; + + FspPlatformData = &FspData->PlatformData; + + // + // The entries of platform information, together with the number of them, + // reside in the bottom of stack, left untouched by normal stack operation. + // + + FspPlatformData->DataPtr = NULL; + FspPlatformData->MicrocodeRegionBase = 0; + FspPlatformData->MicrocodeRegionSize = 0; + FspPlatformData->CodeRegionBase = 0; + FspPlatformData->CodeRegionSize = 0; + + // + // Pointer to the size field + // + TopOfCar = PcdGet32(PcdTemporaryRamBase) + PcdGet32(PcdTemporaryRamSize); + StackPtr = (UINT32 *)(TopOfCar - sizeof (UINT32)); + + if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) { + while (*StackPtr != 0) { + if (*(StackPtr - 1) == FSP_MCUD_SIGNATURE) { + // + // This following data was pushed onto stack after TempRamInit API + // + DwordSize = 4; + StackPtr = StackPtr - 1 - DwordSize; + CopyMem (&(FspPlatformData->MicrocodeRegionBase), StackPtr, (DwordSize << 2)); + StackPtr--; + } else if (*(StackPtr - 1) == FSP_PER0_SIGNATURE) { + // + // This is the performance data for InitTempMemory API entry/exit + // + DwordSize = 4; + StackPtr = StackPtr - 1 - DwordSize; + CopyMem (FspData->PerfData, StackPtr, (DwordSize << 2)); + + ((UINT8 *)(&FspData->PerfData[0]))[7] = FSP_PERF_ID_API_TEMP_RAM_INIT_ENTRY; + ((UINT8 *)(&FspData->PerfData[1]))[7] = FSP_PERF_ID_API_TEMP_RAM_INIT_EXIT; + + StackPtr--; + } else { + StackPtr -= (*StackPtr); + } + } + } +} + +/** + + Initialize the FSP global data region. + It needs to be done as soon as possible after the stack is setup. + + @param[in,out] PeiFspData Pointer of the FSP global data. + @param[in] BootLoaderStack BootLoader stack. + @param[in] ApiIdx The index of the FSP API. + +**/ +VOID +FspGlobalDataInit ( + IN OUT FSP_GLOBAL_DATA *PeiFspData, + IN UINT32 BootLoaderStack, + IN UINT8 ApiIdx + ) +{ + VOID *FspmUpdDataPtr; + CHAR8 ImageId[9]; + UINTN Idx; + + // + // Set FSP Global Data pointer + // + SetFspGlobalDataPointer (PeiFspData); + ZeroMem ((VOID *)PeiFspData, sizeof(FSP_GLOBAL_DATA)); + + PeiFspData->Signature = FSP_GLOBAL_DATA_SIGNATURE; + PeiFspData->Version = 0; + PeiFspData->CoreStack = BootLoaderStack; + PeiFspData->PerfIdx = 2; + PeiFspData->PerfSig = FSP_PERFORMANCE_DATA_SIGNATURE; + + SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY); + + // + // Get FSP Header offset + // It may have multiple FVs, so look into the last one for FSP header + // + PeiFspData->FspInfoHeader = (FSP_INFO_HEADER *)AsmGetFspInfoHeader(); + SecGetPlatformData (PeiFspData); + + // + // Set API calling mode + // + SetFspApiCallingIndex (ApiIdx); + + // + // Set UPD pointer + // + FspmUpdDataPtr = (VOID *) GetFspApiParameter (); + if (FspmUpdDataPtr == NULL) { + FspmUpdDataPtr = (VOID *)(PeiFspData->FspInfoHeader->ImageBase + PeiFspData->FspInfoHeader->CfgRegionOffset); + } + SetFspUpdDataPointer (FspmUpdDataPtr); + SetFspMemoryInitUpdDataPointer (FspmUpdDataPtr); + SetFspSiliconInitUpdDataPointer (NULL); + + // + // Initialize serial port + // It might have been done in ProcessLibraryConstructorList(), however, + // the FSP global data is not initialized at that time. So do it again + // for safe. + // + SerialPortInitialize (); + + // + // Ensure the golbal data pointer is valid + // + ASSERT (GetFspGlobalDataPointer () == PeiFspData); + + for (Idx = 0; Idx < 8; Idx++) { + ImageId[Idx] = PeiFspData->FspInfoHeader->ImageId[Idx]; + } + ImageId[Idx] = 0; + + DEBUG ((DEBUG_INFO | DEBUG_INIT, "\n============= FSP Spec v%d.%d Header Revision v%x (%a v%x.%x.%x.%x) =============\n", \ + (PeiFspData->FspInfoHeader->SpecVersion >> 4) & 0xF, \ + PeiFspData->FspInfoHeader->SpecVersion & 0xF, \ + PeiFspData->FspInfoHeader->HeaderRevision, \ + ImageId, \ + (PeiFspData->FspInfoHeader->ImageRevision >> 24) & 0xFF, \ + (PeiFspData->FspInfoHeader->ImageRevision >> 16) & 0xFF, \ + (PeiFspData->FspInfoHeader->ImageRevision >> 8) & 0xFF, \ + PeiFspData->FspInfoHeader->ImageRevision & 0xFF)); +} + +/** + + Adjust the FSP data pointers after the stack is migrated to memory. + + @param[in] OffsetGap The offset gap between the old stack and the new stack. + +**/ +VOID +FspDataPointerFixUp ( + IN UINT32 OffsetGap + ) +{ + FSP_GLOBAL_DATA *NewFspData; + + NewFspData = (FSP_GLOBAL_DATA *)((UINTN)GetFspGlobalDataPointer() + (UINTN)OffsetGap); + SetFspGlobalDataPointer (NewFspData); +} diff --git a/Core/IntelFsp2Pkg/FspSecCore/SecFsp.h b/Core/IntelFsp2Pkg/FspSecCore/SecFsp.h new file mode 100644 index 0000000000..f199b12e4d --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/SecFsp.h @@ -0,0 +1,99 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _SEC_FSP_H_ +#define _SEC_FSP_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FSP_MCUD_SIGNATURE SIGNATURE_32 ('M', 'C', 'U', 'D') +#define FSP_PER0_SIGNATURE SIGNATURE_32 ('P', 'E', 'R', '0') + +/** + + Calculate the FSP IDT gate descriptor. + + @param[in] IdtEntryTemplate IDT gate descriptor template. + + @return FSP specific IDT gate descriptor. + +**/ +UINT64 +FspGetExceptionHandler( + IN UINT64 IdtEntryTemplate + ); + +/** + + Initialize the FSP global data region. + It needs to be done as soon as possible after the stack is setup. + + @param[in,out] PeiFspData Pointer of the FSP global data. + @param[in] BootLoaderStack BootLoader stack. + @param[in] ApiIdx The index of the FSP API. + +**/ +VOID +FspGlobalDataInit ( + IN OUT FSP_GLOBAL_DATA *PeiFspData, + IN UINT32 BootLoaderStack, + IN UINT8 ApiIdx + ); + + +/** + + Adjust the FSP data pointers after the stack is migrated to memory. + + @param[in] OffsetGap The offset gap between the old stack and the new stack. + +**/ +VOID +FspDataPointerFixUp ( + IN UINT32 OffsetGap + ); + + +/** + This interface returns the base address of FSP binary. + + @return FSP binary base address. + +**/ +UINT32 +EFIAPI +AsmGetFspBaseAddress ( + VOID + ); + +/** + This interface gets FspInfoHeader pointer + + @return FSP binary base address. + +**/ +UINT32 +EFIAPI +AsmGetFspInfoHeader ( + VOID + ); + +#endif diff --git a/Core/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c b/Core/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c new file mode 100644 index 0000000000..bace5eca43 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/SecFspApiChk.c @@ -0,0 +1,97 @@ +/** @file + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include "SecFsp.h" + + +/** + This function check the FSP API calling condition. + + @param[in] ApiIdx Internal index of the FSP API. + @param[in] ApiParam Parameter of the FSP API. + +**/ +EFI_STATUS +EFIAPI +FspApiCallingCheck ( + IN UINT8 ApiIdx, + IN VOID *ApiParam + ) +{ + EFI_STATUS Status; + FSP_GLOBAL_DATA *FspData; + + Status = EFI_SUCCESS; + FspData = GetFspGlobalDataPointer (); + + if (ApiIdx == NotifyPhaseApiIndex) { + // + // NotifyPhase check + // + if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) { + Status = EFI_UNSUPPORTED; + } else { + if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) { + Status = EFI_UNSUPPORTED; + } + } + } else if (ApiIdx == FspMemoryInitApiIndex) { + // + // FspMemoryInit check + // + if ((UINT32)FspData != 0xFFFFFFFF) { + Status = EFI_UNSUPPORTED; + } else if (EFI_ERROR (FspUpdSignatureCheck (ApiIdx, ApiParam))) { + Status = EFI_INVALID_PARAMETER; + } + } else if (ApiIdx == TempRamExitApiIndex) { + // + // TempRamExit check + // + if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) { + Status = EFI_UNSUPPORTED; + } else { + if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) { + Status = EFI_UNSUPPORTED; + } + } + } else if (ApiIdx == FspSiliconInitApiIndex) { + // + // FspSiliconInit check + // + if ((FspData == NULL) || ((UINT32)FspData == 0xFFFFFFFF)) { + Status = EFI_UNSUPPORTED; + } else { + if (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE) { + Status = EFI_UNSUPPORTED; + } else if (EFI_ERROR (FspUpdSignatureCheck (ApiIdx, ApiParam))) { + Status = EFI_INVALID_PARAMETER; + } + } + } else { + Status = EFI_UNSUPPORTED; + } + + if (!EFI_ERROR (Status)) { + if ((ApiIdx != FspMemoryInitApiIndex)) { + // + // For FspMemoryInit, the global data is not valid yet + // The API index will be updated by SecCore after the global data + // is initialized + // + SetFspApiCallingIndex (ApiIdx); + } + } + + return Status; +} diff --git a/Core/IntelFsp2Pkg/FspSecCore/SecMain.c b/Core/IntelFsp2Pkg/FspSecCore/SecMain.c new file mode 100644 index 0000000000..fa556bf058 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/SecMain.c @@ -0,0 +1,227 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include "SecMain.h" +#include "SecFsp.h" + +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = { + SecTemporaryRamSupport +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTemporaryRamSupportPpiGuid, + &gSecTemporaryRamSupportPpi + } +}; + +// +// These are IDT entries pointing to 08:FFFFFFE4h. +// +UINT64 mIdtEntryTemplate = 0xffff8e000008ffe4ULL; + +/** + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + + @param[in] SizeOfRam Size of the temporary memory available for use. + @param[in] TempRamBase Base address of tempory ram + @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume. + @param[in] PeiCore PeiCore entry point. + @param[in] BootLoaderStack BootLoader stack. + @param[in] ApiIdx the index of API. + + @return This function never returns. + +**/ +VOID +EFIAPI +SecStartup ( + IN UINT32 SizeOfRam, + IN UINT32 TempRamBase, + IN VOID *BootFirmwareVolume, + IN PEI_CORE_ENTRY PeiCore, + IN UINT32 BootLoaderStack, + IN UINT32 ApiIdx + ) +{ + EFI_SEC_PEI_HAND_OFF SecCoreData; + IA32_DESCRIPTOR IdtDescriptor; + SEC_IDT_TABLE IdtTableInStack; + UINT32 Index; + FSP_GLOBAL_DATA PeiFspData; + UINT64 ExceptionHandler; + + // + // Process all libraries constructor function linked to SecCore. + // + ProcessLibraryConstructorList (); + + // + // Initialize floating point operating environment + // to be compliant with UEFI spec. + // + InitializeFloatingPointUnits (); + + + // |-------------------|----> + // |Idt Table | + // |-------------------| + // |PeiService Pointer | PeiStackSize + // |-------------------| + // | | + // | Stack | + // |-------------------|----> + // | | + // | | + // | Heap | PeiTemporayRamSize + // | | + // | | + // |-------------------|----> TempRamBase + IdtTableInStack.PeiService = NULL; + ExceptionHandler = FspGetExceptionHandler(mIdtEntryTemplate); + for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { + CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&ExceptionHandler, sizeof (UINT64)); + } + + IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable; + IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); + + AsmWriteIdtr (&IdtDescriptor); + + // + // Initialize the global FSP data region + // + FspGlobalDataInit (&PeiFspData, BootLoaderStack, (UINT8)ApiIdx); + + // + // Update the base address and length of Pei temporary memory + // + SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF); + SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume; + SecCoreData.BootFirmwareVolumeSize = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength; + + SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase; + SecCoreData.TemporaryRamSize = SizeOfRam; + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize * PcdGet8 (PcdFspHeapSizePercentage) / 100; + SecCoreData.StackBase = (VOID*)(UINTN)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize); + SecCoreData.StackSize = SecCoreData.TemporaryRamSize - SecCoreData.PeiTemporaryRamSize; + + DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase)); + DEBUG ((DEBUG_INFO, "Fsp BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize)); + DEBUG ((DEBUG_INFO, "Fsp TemporaryRamBase - 0x%x\n", SecCoreData.TemporaryRamBase)); + DEBUG ((DEBUG_INFO, "Fsp TemporaryRamSize - 0x%x\n", SecCoreData.TemporaryRamSize)); + DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamBase - 0x%x\n", SecCoreData.PeiTemporaryRamBase)); + DEBUG ((DEBUG_INFO, "Fsp PeiTemporaryRamSize - 0x%x\n", SecCoreData.PeiTemporaryRamSize)); + DEBUG ((DEBUG_INFO, "Fsp StackBase - 0x%x\n", SecCoreData.StackBase)); + DEBUG ((DEBUG_INFO, "Fsp StackSize - 0x%x\n", SecCoreData.StackSize)); + + // + // Call PeiCore Entry + // + PeiCore (&SecCoreData, mPeiSecPlatformInformationPpi); + + // + // Should never be here + // + CpuDeadLoop (); +} + +/** + This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into + permanent memory. + + @param[in] PeiServices Pointer to the PEI Services Table. + @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the + Temporary RAM contents. + @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the + Temporary RAM contents. + @param[in] CopySize Amount of memory to migrate from temporary to permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when + TemporaryMemoryBase > PermanentMemoryBase. + +**/ +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + IA32_DESCRIPTOR IdtDescriptor; + VOID* OldHeap; + VOID* NewHeap; + VOID* OldStack; + VOID* NewStack; + UINTN HeapSize; + UINTN StackSize; + + HeapSize = CopySize * PcdGet8 (PcdFspHeapSizePercentage) / 100 ; + StackSize = CopySize - HeapSize; + + OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; + NewHeap = (VOID*)((UINTN)PermanentMemoryBase + StackSize); + + OldStack = (VOID*)((UINTN)TemporaryMemoryBase + HeapSize); + NewStack = (VOID*)(UINTN)PermanentMemoryBase; + + // + // Migrate Heap + // + CopyMem (NewHeap, OldHeap, HeapSize); + + // + // Migrate Stack + // + CopyMem (NewStack, OldStack, StackSize); + + + // + // We need *not* fix the return address because currently, + // The PeiCore is executed in flash. + // + + // + // Rebase IDT table in permanent memory + // + AsmReadIdtr (&IdtDescriptor); + IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack; + + AsmWriteIdtr (&IdtDescriptor); + + // + // Fixed the FSP data pointer + // + FspDataPointerFixUp ((UINTN)NewStack - (UINTN)OldStack); + + // + // SecSwitchStack function must be invoked after the memory migration + // immediatly, also we need fixup the stack change caused by new call into + // permenent memory. + // + SecSwitchStack ( + (UINT32) (UINTN) OldStack, + (UINT32) (UINTN) NewStack + ); + + return EFI_SUCCESS; +} diff --git a/Core/IntelFsp2Pkg/FspSecCore/SecMain.h b/Core/IntelFsp2Pkg/FspSecCore/SecMain.h new file mode 100644 index 0000000000..33f73625ca --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/SecMain.h @@ -0,0 +1,140 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _SEC_CORE_H_ +#define _SEC_CORE_H_ + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SEC_IDT_ENTRY_COUNT 34 + +typedef VOID (*PEI_CORE_ENTRY) ( \ + IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData, \ + IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList \ +); + +typedef struct _SEC_IDT_TABLE { + EFI_PEI_SERVICES *PeiService; + UINT64 IdtTable[SEC_IDT_ENTRY_COUNT]; +} SEC_IDT_TABLE; + +/** + Switch the stack in the temporary memory to the one in the permanent memory. + + This function must be invoked after the memory migration immediately. The relative + position of the stack in the temporary and permanent memory is same. + + @param[in] TemporaryMemoryBase Base address of the temporary memory. + @param[in] PermenentMemoryBase Base address of the permanent memory. +**/ +VOID +EFIAPI +SecSwitchStack ( + IN UINT32 TemporaryMemoryBase, + IN UINT32 PermenentMemoryBase + ); + +/** + This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into + permanent memory. + + @param[in] PeiServices Pointer to the PEI Services Table. + @param[in] TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the + Temporary RAM contents. + @param[in] PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the + Temporary RAM contents. + @param[in] CopySize Amount of memory to migrate from temporary to permanent memory. + + @retval EFI_SUCCESS The data was successfully returned. + @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when + TemporaryMemoryBase > PermanentMemoryBase. + +**/ +EFI_STATUS +EFIAPI +SecTemporaryRamSupport ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ); + +/** + Initializes floating point units for requirement of UEFI specification. + + This function initializes floating-point control word to 0x027F (all exceptions + masked,double-precision, round-to-nearest) and multimedia-extensions control word + (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero + for masked underflow). + +**/ +VOID +EFIAPI +InitializeFloatingPointUnits ( + VOID + ); + +/** + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + + @param[in] SizeOfRam Size of the temporary memory available for use. + @param[in] TempRamBase Base address of tempory ram + @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume. + @param[in] PeiCore PeiCore entry point. + @param[in] BootLoaderStack BootLoader stack. + @param[in] ApiIdx the index of API. + + @return This function never returns. + +**/ +VOID +EFIAPI +SecStartup ( + IN UINT32 SizeOfRam, + IN UINT32 TempRamBase, + IN VOID *BootFirmwareVolume, + IN PEI_CORE_ENTRY PeiCore, + IN UINT32 BootLoaderStack, + IN UINT32 ApiIdx + ); + +/** + Autogenerated function that calls the library constructors for all of the module's + dependent libraries. This function must be called by the SEC Core once a stack has + been established. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + VOID + ); + +#endif diff --git a/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw new file mode 100644 index 0000000000..2dc9f178d3 Binary files /dev/null and b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw differ diff --git a/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py new file mode 100644 index 0000000000..3018391445 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Build.py @@ -0,0 +1,53 @@ +## @file +# Automate the process of building the various reset vector types +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# +# 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. +# + +import glob +import os +import subprocess +import sys + +def RunCommand(commandLine): + #print ' '.join(commandLine) + return subprocess.call(commandLine) + +for filename in glob.glob(os.path.join('Bin', '*.raw')): + os.remove(filename) + +arch = 'ia32' +debugType = None +output = os.path.join('Bin', 'ResetVec') +output += '.' + arch +if debugType is not None: + output += '.' + debugType +output += '.raw' +commandLine = ( + 'nasm', + '-D', 'ARCH_%s' % arch.upper(), + '-D', 'DEBUG_%s' % str(debugType).upper(), + '-o', output, + 'ResetVectorCode.asm', + ) +ret = RunCommand(commandLine) +print '\tASM\t' + output +if ret != 0: sys.exit(ret) + +commandLine = ( + 'python', + 'Tools/FixupForRawSection.py', + output, + ) +print '\tFIXUP\t' + output +ret = RunCommand(commandLine) +if ret != 0: sys.exit(ret) + diff --git a/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 new file mode 100644 index 0000000000..585876fa86 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Ia16/ResetVec.asm16 @@ -0,0 +1,103 @@ +;; @file +; Reset Vector Data structure +; This structure is located at 0xFFFFFFC0 +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.
+; 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. +; +;; + +BITS 16 + + +; +; The layout of this file is fixed. The build tool makes assumption of the layout. +; + +ORG 0x0 +; +; Reserved +; +ReservedData: DD 0eeeeeeeeh, 0eeeeeeeeh + + ; ORG 0x10 + TIMES 0x10-($-$$) DB 0 +; +; This is located at 0xFFFFFFD0h +; + mov di, "AP" + jmp ApStartup + + ; ORG 0x20 + + TIMES 0x20-($-$$) DB 0 + +; Pointer to the entry point of the PEI core +; It is located at 0xFFFFFFE0, and is fixed up by some build tool +; So if the value 8..1 appears in the final FD image, tool failure occurs. +; +PeiCoreEntryPoint: DD 0x12345678 + +; +; This is the handler for all kinds of exceptions. Since it's for debugging +; purpose only, nothing except a deadloop would be done here. Developers could +; analyze the cause of the exception if a debugger had been attached. +; +InterruptHandler: + jmp $ + iret + + ; ORG 0x30 + TIMES 0x30-($-$$) DB 0 +; +; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte +; Execution starts here upon power-on/platform-reset. +; +ResetHandler: + nop + nop + +ApStartup: + ; + ; Jmp Rel16 instruction + ; Use machine code directly in case of the assembler optimization + ; SEC entry point relatvie address will be fixed up by some build tool. + ; + ; Typically, SEC entry point is the function _ModuleEntryPoint() defined in + ; SecEntry.asm + ; + DB 0x0e9 + DW -3 + + ; ORG 0x38 + + TIMES 0x38-($-$$) DB 0 +; +; Ap reset vector segment address is at 0xFFFFFFF8 +; This will be fixed up by some build tool, +; so if the value 1..8 appears in the final FD image, +; tool failure occurs +; +ApSegAddress: dd 0x12345678 + + ; ORG 0x3c + TIMES 0x3c-($-$$) DB 0 +; +; BFV Base is at 0xFFFFFFFC +; This will be fixed up by some build tool, +; so if the value 1..8 appears in the final FD image, +; tool failure occurs. +; +BfvBase: DD 0x12345678 + +; +; Nothing can go here, otherwise the layout of this file would change. +; + + ; END diff --git a/Core/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm new file mode 100644 index 0000000000..72b252491f --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/ResetVectorCode.asm @@ -0,0 +1,17 @@ +;------------------------------------------------------------------------------ +; @file +; This file includes all other code files to assemble the reset vector code +; +; Copyright (c) 2014, Intel Corporation. All rights reserved.
+; 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. +; +;------------------------------------------------------------------------------ + + +%include "Ia16/ResetVec.asm16" diff --git a/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py new file mode 100644 index 0000000000..8e7c20b401 --- /dev/null +++ b/Core/IntelFsp2Pkg/FspSecCore/Vtf0/Tools/FixupForRawSection.py @@ -0,0 +1,110 @@ +## @file +# Apply fixup to VTF binary image for FFS Raw section +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# +# 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. +# + +import sys + +filename = sys.argv[1] + +if filename.lower().find('ia32') >= 0: + d = open(sys.argv[1], 'rb').read() + c = ((len(d) + 4 + 7) & ~7) - 4 + if c > len(d): + c -= len(d) + f = open(sys.argv[1], 'wb') + f.write('\x90' * c) + f.write(d) + f.close() +else: + from struct import pack + + PAGE_PRESENT = 0x01 + PAGE_READ_WRITE = 0x02 + PAGE_USER_SUPERVISOR = 0x04 + PAGE_WRITE_THROUGH = 0x08 + PAGE_CACHE_DISABLE = 0x010 + PAGE_ACCESSED = 0x020 + PAGE_DIRTY = 0x040 + PAGE_PAT = 0x080 + PAGE_GLOBAL = 0x0100 + PAGE_2M_MBO = 0x080 + PAGE_2M_PAT = 0x01000 + + def NopAlign4k(s): + c = ((len(s) + 0xfff) & ~0xfff) - len(s) + return ('\x90' * c) + s + + def PageDirectoryEntries4GbOf2MbPages(baseAddress): + + s = '' + for i in range(0x800): + i = ( + baseAddress + long(i << 21) + + PAGE_2M_MBO + + PAGE_CACHE_DISABLE + + PAGE_ACCESSED + + PAGE_DIRTY + + PAGE_READ_WRITE + + PAGE_PRESENT + ) + s += pack('Q', i) + return s + + def PageDirectoryPointerTable4GbOf2MbPages(pdeBase): + s = '' + for i in range(0x200): + i = ( + pdeBase + + (min(i, 3) << 12) + + PAGE_CACHE_DISABLE + + PAGE_ACCESSED + + PAGE_READ_WRITE + + PAGE_PRESENT + ) + s += pack('Q', i) + return s + + def PageMapLevel4Table4GbOf2MbPages(pdptBase): + s = '' + for i in range(0x200): + i = ( + pdptBase + + (min(i, 0) << 12) + + PAGE_CACHE_DISABLE + + PAGE_ACCESSED + + PAGE_READ_WRITE + + PAGE_PRESENT + ) + s += pack('Q', i) + return s + + def First4GbPageEntries(topAddress): + PDE = PageDirectoryEntries4GbOf2MbPages(0L) + pml4tBase = topAddress - 0x1000 + pdptBase = pml4tBase - 0x1000 + pdeBase = pdptBase - len(PDE) + PDPT = PageDirectoryPointerTable4GbOf2MbPages(pdeBase) + PML4T = PageMapLevel4Table4GbOf2MbPages(pdptBase) + return PDE + PDPT + PML4T + + def AlignAndAddPageTables(): + d = open(sys.argv[1], 'rb').read() + code = NopAlign4k(d) + topAddress = 0x100000000 - len(code) + d = ('\x90' * 4) + First4GbPageEntries(topAddress) + code + f = open(sys.argv[1], 'wb') + f.write(d) + f.close() + + AlignAndAddPageTables() + diff --git a/Core/IntelFsp2Pkg/Include/FspDataTable.h b/Core/IntelFsp2Pkg/Include/FspDataTable.h new file mode 100644 index 0000000000..3c79f34e47 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/FspDataTable.h @@ -0,0 +1,32 @@ +/** @file + The header file of FSP data table + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_DATA_TABLE_H_ +#define _FSP_DATA_TABLE_H_ + +#pragma pack(1) + +#define FSP_DATA_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'D') + +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 FsptBase; + UINT32 FspmBase; + UINT32 FspsBase; +} FSP_DATA_TABLE; + +#pragma pack() + +#endif diff --git a/Core/IntelFsp2Pkg/Include/FspEas.h b/Core/IntelFsp2Pkg/Include/FspEas.h new file mode 100644 index 0000000000..79bb0b8e8e --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/FspEas.h @@ -0,0 +1,24 @@ +/** @file + Intel FSP definition from Intel Firmware Support Package External + Architecture Specification v2.0. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_EAS_H_ +#define _FSP_EAS_H_ + +#include +#include +#include +#include + +#endif diff --git a/Core/IntelFsp2Pkg/Include/FspEas/FspApi.h b/Core/IntelFsp2Pkg/Include/FspEas/FspApi.h new file mode 100644 index 0000000000..a2e4813baa --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/FspEas/FspApi.h @@ -0,0 +1,288 @@ +/** @file + Intel FSP API definition from Intel Firmware Support Package External + Architecture Specification v2.0. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_API_H_ +#define _FSP_API_H_ + +/// +/// FSP Reset Status code +/// These are defined in FSP EAS v2.0 section 11.2.2 - OEM Status Code +/// @{ +#define FSP_STATUS_RESET_REQUIRED_COLD 0x40000001 +#define FSP_STATUS_RESET_REQUIRED_WARM 0x40000002 +#define FSP_STATUS_RESET_REQUIRED_3 0x40000003 +#define FSP_STATUS_RESET_REQUIRED_4 0x40000004 +#define FSP_STATUS_RESET_REQUIRED_5 0x40000005 +#define FSP_STATUS_RESET_REQUIRED_6 0x40000006 +#define FSP_STATUS_RESET_REQUIRED_7 0x40000007 +#define FSP_STATUS_RESET_REQUIRED_8 0x40000008 +/// @} + +#pragma pack(1) +/// +/// FSP_UPD_HEADER Configuration. +/// +typedef struct { + /// + /// UPD Region Signature. This signature will be + /// "XXXXXX_T" for FSP-T + /// "XXXXXX_M" for FSP-M + /// "XXXXXX_S" for FSP-S + /// Where XXXXXX is an unique signature + /// + UINT64 Signature; + /// + /// Revision of the Data structure. For FSP v2.0 value is 1. + /// + UINT8 Revision; + UINT8 Reserved[23]; +} FSP_UPD_HEADER; + +/// +/// FSPM_ARCH_UPD Configuration. +/// +typedef struct { + /// + /// Revision of the structure. For FSP v2.0 value is 1. + /// + UINT8 Revision; + UINT8 Reserved[3]; + /// + /// Pointer to the non-volatile storage (NVS) data buffer. + /// If it is NULL it indicates the NVS data is not available. + /// + VOID *NvsBufferPtr; + /// + /// Pointer to the temporary stack base address to be + /// consumed inside FspMemoryInit() API. + /// + VOID *StackBase; + /// + /// Temporary stack size to be consumed inside + /// FspMemoryInit() API. + /// + UINT32 StackSize; + /// + /// Size of memory to be reserved by FSP below "top + /// of low usable memory" for bootloader usage. + /// + UINT32 BootLoaderTolumSize; + /// + /// Current boot mode. + /// + UINT32 BootMode; + UINT8 Reserved1[8]; +} FSPM_ARCH_UPD; + +/// +/// FSPT_UPD_COMMON Configuration. +/// +typedef struct { + /// + /// FSP_UPD_HEADER Configuration. + /// + FSP_UPD_HEADER FspUpdHeader; +} FSPT_UPD_COMMON; + +/// +/// FSPM_UPD_COMMON Configuration. +/// +typedef struct { + /// + /// FSP_UPD_HEADER Configuration. + /// + FSP_UPD_HEADER FspUpdHeader; + /// + /// FSPM_ARCH_UPD Configuration. + /// + FSPM_ARCH_UPD FspmArchUpd; +} FSPM_UPD_COMMON; + +/// +/// FSPS_UPD_COMMON Configuration. +/// +typedef struct { + /// + /// FSP_UPD_HEADER Configuration. + /// + FSP_UPD_HEADER FspUpdHeader; +} FSPS_UPD_COMMON; + +/// +/// Enumeration of FSP_INIT_PHASE for NOTIFY_PHASE. +/// +typedef enum { + /// + /// This stage is notified when the bootloader completes the + /// PCI enumeration and the resource allocation for the + /// PCI devices is complete. + /// + EnumInitPhaseAfterPciEnumeration = 0x20, + /// + /// This stage is notified just before the bootloader hand-off + /// to the OS loader. + /// + EnumInitPhaseReadyToBoot = 0x40, + /// + /// This stage is notified just before the firmware/Preboot + /// environment transfers management of all system resources + /// to the OS or next level execution environment. + /// + EnumInitPhaseEndOfFirmware = 0xF0 +} FSP_INIT_PHASE; + +/// +/// Definition of NOTIFY_PHASE_PARAMS. +/// +typedef struct { + /// + /// Notification phase used for NotifyPhase API + /// + FSP_INIT_PHASE Phase; +} NOTIFY_PHASE_PARAMS; + +#pragma pack() + +/** + This FSP API is called soon after coming out of reset and before memory and stack is + available. This FSP API will load the microcode update, enable code caching for the + region specified by the boot loader and also setup a temporary stack to be used until + main memory is initialized. + + A hardcoded stack can be set up with the following values, and the "esp" register + initialized to point to this hardcoded stack. + 1. The return address where the FSP will return control after setting up a temporary + stack. + 2. A pointer to the input parameter structure + + However, since the stack is in ROM and not writeable, this FSP API cannot be called + using the "call" instruction, but needs to be jumped to. + + @param[in] FsptUpdDataPtr Pointer to the FSPT_UPD data structure. + + @retval EFI_SUCCESS Temporary RAM was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR Temp RAM initialization failed. + + If this function is successful, the FSP initializes the ECX and EDX registers to point to + a temporary but writeable memory range available to the boot loader and returns with + FSP_SUCCESS in register EAX. Register ECX points to the start of this temporary + memory range and EDX points to the end of the range. Boot loader is free to use the + whole range described. Typically the boot loader can reload the ESP register to point + to the end of this returned range so that it can be used as a standard stack. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_TEMP_RAM_INIT) ( + IN VOID *FsptUpdDataPtr + ); + +/** + This FSP API is used to notify the FSP about the different phases in the boot process. + This allows the FSP to take appropriate actions as needed during different initialization + phases. The phases will be platform dependent and will be documented with the FSP + release. The current FSP supports two notify phases: + Post PCI enumeration + Ready To Boot + + @param[in] NotifyPhaseParamPtr Address pointer to the NOTIFY_PHASE_PRAMS + + @retval EFI_SUCCESS The notification was handled successfully. + @retval EFI_UNSUPPORTED The notification was not called in the proper order. + @retval EFI_INVALID_PARAMETER The notification code is invalid. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_NOTIFY_PHASE) ( + IN NOTIFY_PHASE_PARAMS *NotifyPhaseParamPtr + ); + +/** + This FSP API is called after TempRamInit and initializes the memory. + This FSP API accepts a pointer to a data structure that will be platform dependent + and defined for each FSP binary. This will be documented in Integration guide with + each FSP release. + After FspMemInit completes its execution, it passes the pointer to the HobList and + returns to the boot loader from where it was called. BootLoader is responsible to + migrate it's stack and data to Memory. + FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to + complete the silicon initialization and provides bootloader an opportunity to get + control after system memory is available and before the temporary RAM is torn down. + + @param[in] FspmUpdDataPtr Pointer to the FSPM_UPD data sructure. + @param[out] HobListPtr Pointer to receive the address of the HOB list. + + @retval EFI_SUCCESS FSP execution environment was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR FSP initialization failed. + @retval EFI_OUT_OF_RESOURCES Stack range requested by FSP is not met. + @retval FSP_STATUS_RESET_REQUIREDx A reset is reuired. These status codes will not be returned during S3. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_MEMORY_INIT) ( + IN VOID *FspmUpdDataPtr, + OUT VOID **HobListPtr + ); + + +/** + This FSP API is called after FspMemoryInit API. This FSP API tears down the temporary + memory setup by TempRamInit API. This FSP API accepts a pointer to a data structure + that will be platform dependent and defined for each FSP binary. This will be + documented in Integration Guide. + FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to + complete the silicon initialization and provides bootloader an opportunity to get + control after system memory is available and before the temporary RAM is torn down. + + @param[in] TempRamExitParamPtr Pointer to the Temp Ram Exit parameters structure. + This structure is normally defined in the Integration Guide. + And if it is not defined in the Integration Guide, pass NULL. + + @retval EFI_SUCCESS FSP execution environment was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR FSP initialization failed. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_TEMP_RAM_EXIT) ( + IN VOID *TempRamExitParamPtr + ); + + +/** + This FSP API is called after TempRamExit API. + FspMemoryInit, TempRamExit and FspSiliconInit APIs provide an alternate method to complete the + silicon initialization. + + @param[in] FspsUpdDataPtr Pointer to the FSPS_UPD data structure. + If NULL, FSP will use the default parameters. + + @retval EFI_SUCCESS FSP execution environment was initialized successfully. + @retval EFI_INVALID_PARAMETER Input parameters are invalid. + @retval EFI_UNSUPPORTED The FSP calling conditions were not met. + @retval EFI_DEVICE_ERROR FSP initialization failed. + @retval FSP_STATUS_RESET_REQUIREDx A reset is reuired. These status codes will not be returned during S3. +**/ +typedef +EFI_STATUS +(EFIAPI *FSP_SILICON_INIT) ( + IN VOID *FspsUpdDataPtr + ); + +#endif diff --git a/Core/IntelFsp2Pkg/Include/FspGlobalData.h b/Core/IntelFsp2Pkg/Include/FspGlobalData.h new file mode 100644 index 0000000000..8ac3199bab --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/FspGlobalData.h @@ -0,0 +1,66 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_GLOBAL_DATA_H_ +#define _FSP_GLOBAL_DATA_H_ + +#include + +#pragma pack(1) + +typedef enum { + TempRamInitApiIndex, + FspInitApiIndex, + NotifyPhaseApiIndex, + FspMemoryInitApiIndex, + TempRamExitApiIndex, + FspSiliconInitApiIndex, + FspApiIndexMax +} FSP_API_INDEX; + +typedef struct { + VOID *DataPtr; + UINT32 MicrocodeRegionBase; + UINT32 MicrocodeRegionSize; + UINT32 CodeRegionBase; + UINT32 CodeRegionSize; +} FSP_PLAT_DATA; + +#define FSP_GLOBAL_DATA_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'D') +#define FSP_PERFORMANCE_DATA_SIGNATURE SIGNATURE_32 ('P', 'E', 'R', 'F') + +typedef struct { + UINT32 Signature; + UINT8 Version; + UINT8 Reserved1[3]; + UINT32 CoreStack; + UINT32 StatusCode; + UINT32 Reserved2[8]; + FSP_PLAT_DATA PlatformData; + FSP_INFO_HEADER *FspInfoHeader; + VOID *UpdDataPtr; + VOID *TempRamInitUpdPtr; + VOID *MemoryInitUpdPtr; + VOID *SiliconInitUpdPtr; + UINT8 ApiIdx; + UINT8 Reserved3[31]; + UINT32 PerfSig; + UINT16 PerfLen; + UINT16 Reserved4; + UINT32 PerfIdx; + UINT64 PerfData[32]; +} FSP_GLOBAL_DATA; + +#pragma pack() + +#endif diff --git a/Core/IntelFsp2Pkg/Include/FspMeasurePointId.h b/Core/IntelFsp2Pkg/Include/FspMeasurePointId.h new file mode 100644 index 0000000000..ee103df795 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/FspMeasurePointId.h @@ -0,0 +1,62 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_MEASURE_POINT_ID_H_ +#define _FSP_MEASURE_POINT_ID_H_ + +// +// 0xD0 - 0xEF are reserved for FSP common measure point +// +#define FSP_PERF_ID_MRC_INIT_ENTRY 0xD0 +#define FSP_PERF_ID_MRC_INIT_EXIT (FSP_PERF_ID_MRC_INIT_ENTRY + 1) + +#define FSP_PERF_ID_SYSTEM_AGENT_INIT_ENTRY 0xD8 +#define FSP_PERF_ID_SYSTEM_AGENT_INIT_EXIT (FSP_PERF_ID_SYSTEM_AGENT_INIT_ENTRY + 1) + +#define FSP_PERF_ID_PCH_INIT_ENTRY 0xDA +#define FSP_PERF_ID_PCH_INIT_EXIT (FSP_PERF_ID_PCH_INIT_ENTRY + 1) + +#define FSP_PERF_ID_CPU_INIT_ENTRY 0xE0 +#define FSP_PERF_ID_CPU_INIT_EXIT (FSP_PERF_ID_CPU_INIT_ENTRY + 1) + +#define FSP_PERF_ID_GFX_INIT_ENTRY 0xE8 +#define FSP_PERF_ID_GFX_INIT_EXIT (FSP_PERF_ID_GFX_INIT_ENTRY + 1) + +#define FSP_PERF_ID_ME_INIT_ENTRY 0xEA +#define FSP_PERF_ID_ME_INIT_EXIT (FSP_PERF_ID_ME_INIT_ENTRY + 1) + +// +// 0xF0 - 0xFF are reserved for FSP API +// +#define FSP_PERF_ID_API_TEMP_RAM_INIT_ENTRY 0xF0 +#define FSP_PERF_ID_API_TEMP_RAM_INIT_EXIT (FSP_PERF_ID_API_TEMP_RAM_INIT_ENTRY + 1) + +#define FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY 0xF2 +#define FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT (FSP_PERF_ID_API_FSP_MEMORY_INIT_ENTRY + 1) + +#define FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY 0xF4 +#define FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY + 1) + +#define FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY 0xF6 +#define FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY + 1) + +#define FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY 0xF8 +#define FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + 1) + +#define FSP_PERF_ID_API_NOTIFY_READY_TO_BOOT_ENTRY 0xFA +#define FSP_PERF_ID_API_NOTIFY_READY_TO_BOOT_EXIT (FSP_PERF_ID_API_NOTIFY_READY_TO_BOOT_ENTRY + 1) + +#define FSP_PERF_ID_API_NOTIFY_END_OF_FIRMWARE_ENTRY 0xFC +#define FSP_PERF_ID_API_NOTIFY_END_OF_FIRMWARE_EXIT (FSP_PERF_ID_API_NOTIFY_END_OF_FIRMWARE_ENTRY + 1) + +#endif diff --git a/Core/IntelFsp2Pkg/Include/FspStatusCode.h b/Core/IntelFsp2Pkg/Include/FspStatusCode.h new file mode 100644 index 0000000000..c9a316e6e7 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/FspStatusCode.h @@ -0,0 +1,46 @@ +/** @file + Intel FSP status code definition + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_STATUS_CODE_H_ +#define _FSP_STATUS_CODE_H_ + +// +// FSP API - 4 BITS +// +#define FSP_STATUS_CODE_TEMP_RAM_INIT 0xF000 +#define FSP_STATUS_CODE_MEMORY_INIT 0xD000 +#define FSP_STATUS_CODE_TEMP_RAM_EXIT 0xB000 +#define FSP_STATUS_CODE_SILICON_INIT 0x9000 +#define FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION 0x6000 +#define FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION 0x4000 +#define FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION 0x2000 + +// +// MODULE - 4 BITS +// +#define FSP_STATUS_CODE_GFX_PEIM 0x0700 +#define FSP_STATUS_CODE_COMMON_CODE 0x0800 +#define FSP_STATUS_CODE_SILICON_COMMON_CODE 0x0900 +#define FSP_STATUS_CODE_SYSTEM_AGENT 0x0A00 +#define FSP_STATUS_CODE_PCH 0x0B00 +#define FSP_STATUS_CODE_CPU 0x0C00 +#define FSP_STATUS_CODE_MRC 0x0D00 +#define FSP_STATUS_CODE_ME_BIOS 0x0E00 +// +// Individual Codes - 1 BYTE +// +#define FSP_STATUS_CODE_API_ENTRY 0x0000 +#define FSP_STATUS_CODE_API_EXIT 0x007F + +#endif diff --git a/Core/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h b/Core/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h new file mode 100644 index 0000000000..96cac00124 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Guid/FspHeaderFile.h @@ -0,0 +1,204 @@ +/** @file + Intel FSP Header File definition from Intel Firmware Support Package External + Architecture Specification v2.0. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef __FSP_HEADER_FILE_H__ +#define __FSP_HEADER_FILE_H__ + +#define FSP_HEADER_REVISION_3 3 + +#define FSPE_HEADER_REVISION_1 1 +#define FSPP_HEADER_REVISION_1 1 + +/// +/// Fixed FSP header offset in the FSP image +/// +#define FSP_INFO_HEADER_OFF 0x94 + +#define OFFSET_IN_FSP_INFO_HEADER(x) (UINT32)&((FSP_INFO_HEADER *)(UINTN)0)->x + +#define FSP_INFO_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'H') + +#pragma pack(1) + +/// +/// FSP Information Header as described in FSP v2.0 Spec section 5.1.1. +/// +typedef struct { + /// + /// Byte 0x00: Signature ('FSPH') for the FSP Information Header. + /// + UINT32 Signature; + /// + /// Byte 0x04: Length of the FSP Information Header. + /// + UINT32 HeaderLength; + /// + /// Byte 0x08: Reserved. + /// + UINT8 Reserved1[2]; + /// + /// Byte 0x0A: Indicates compliance with a revision of this specification in the BCD format. + /// + UINT8 SpecVersion; + /// + /// Byte 0x0B: Revision of the FSP Information Header. + /// + UINT8 HeaderRevision; + /// + /// Byte 0x0C: Revision of the FSP binary. + /// + UINT32 ImageRevision; + /// + /// Byte 0x10: Signature string that will help match the FSP Binary to a supported HW configuration. + /// + CHAR8 ImageId[8]; + /// + /// Byte 0x18: Size of the entire FSP binary. + /// + UINT32 ImageSize; + /// + /// Byte 0x1C: FSP binary preferred base address. + /// + UINT32 ImageBase; + /// + /// Byte 0x20: Attribute for the FSP binary. + /// + UINT16 ImageAttribute; + /// + /// Byte 0x22: Attributes of the FSP Component. + /// + UINT16 ComponentAttribute; + /// + /// Byte 0x24: Offset of the FSP configuration region. + /// + UINT32 CfgRegionOffset; + /// + /// Byte 0x28: Size of the FSP configuration region. + /// + UINT32 CfgRegionSize; + /// + /// Byte 0x2C: Reserved2. + /// + UINT32 Reserved2; + /// + /// Byte 0x30: The offset for the API to setup a temporary stack till the memory is initialized. + /// + UINT32 TempRamInitEntryOffset; + /// + /// Byte 0x34: Reserved3. + /// + UINT32 Reserved3; + /// + /// Byte 0x38: The offset for the API to inform the FSP about the different stages in the boot process. + /// + UINT32 NotifyPhaseEntryOffset; + /// + /// Byte 0x3C: The offset for the API to initialize the memory. + /// + UINT32 FspMemoryInitEntryOffset; + /// + /// Byte 0x40: The offset for the API to tear down temporary RAM. + /// + UINT32 TempRamExitEntryOffset; + /// + /// Byte 0x44: The offset for the API to initialize the CPU and chipset. + /// + UINT32 FspSiliconInitEntryOffset; +} FSP_INFO_HEADER; + +/// +/// Signature of the FSP Extended Header +/// +#define FSP_INFO_EXTENDED_HEADER_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'E') + +/// +/// FSP Information Extended Header as described in FSP v2.0 Spec section 5.1.2. +/// +typedef struct { + /// + /// Byte 0x00: Signature ('FSPE') for the FSP Extended Information Header. + /// + UINT32 Signature; + /// + /// Byte 0x04: Length of the table in bytes, including all additional FSP producer defined data. + /// + UINT32 Length; + /// + /// Byte 0x08: FSP producer defined revision of the table. + /// + UINT8 Revision; + /// + /// Byte 0x09: Reserved for future use. + /// + UINT8 Reserved; + /// + /// Byte 0x0A: FSP producer identification string + /// + CHAR8 FspProducerId[6]; + /// + /// Byte 0x10: FSP producer implementation revision number. Larger numbers are assumed to be newer revisions. + /// + UINT32 FspProducerRevision; + /// + /// Byte 0x14: Size of the FSP producer defined data (n) in bytes. + /// + UINT32 FspProducerDataSize; + /// + /// Byte 0x18: FSP producer defined data of size (n) defined by FspProducerDataSize. + /// +} FSP_INFO_EXTENDED_HEADER; + +// +// A generic table search algorithm for additional tables can be implemented with a +// signature search algorithm until a terminator signature 'FSPP' is found. +// +#define FSP_FSPP_SIGNATURE SIGNATURE_32 ('F', 'S', 'P', 'P') +#define FSP_PATCH_TABLE_SIGNATURE FSP_FSPP_SIGNATURE + +/// +/// FSP Patch Table as described in FSP v2.0 Spec section 5.1.5. +/// +typedef struct { + /// + /// Byte 0x00: FSP Patch Table Signature "FSPP". + /// + UINT32 Signature; + /// + /// Byte 0x04: Size including the PatchData. + /// + UINT16 HeaderLength; + /// + /// Byte 0x06: Revision is set to 0x01. + /// + UINT8 HeaderRevision; + /// + /// Byte 0x07: Reserved for future use. + /// + UINT8 Reserved; + /// + /// Byte 0x08: Number of entries to Patch. + /// + UINT32 PatchEntryNum; + /// + /// Byte 0x0C: Patch Data. + /// +//UINT32 PatchData[]; +} FSP_PATCH_TABLE; + +#pragma pack() + +extern EFI_GUID gFspHeaderFileGuid; + +#endif diff --git a/Core/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h b/Core/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h new file mode 100644 index 0000000000..83c7f0068f --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Guid/GuidHobFspEas.h @@ -0,0 +1,23 @@ +/** @file + Intel FSP Hob Guid definition from Intel Firmware Support Package External + Architecture Specification v2.0. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef __GUID_HOB_FSP_EAS_GUID__ +#define __GUID_HOB_FSP_EAS_GUID__ + +extern EFI_GUID gFspBootLoaderTolumHobGuid; +extern EFI_GUID gFspReservedMemoryResourceHobGuid; +extern EFI_GUID gFspNonVolatileStorageHobGuid; + +#endif diff --git a/Core/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h b/Core/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h new file mode 100644 index 0000000000..6f3d068b67 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Library/CacheAsRamLib.h @@ -0,0 +1,30 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _CACHE_AS_RAM_LIB_H_ +#define _CACHE_AS_RAM_LIB_H_ + +/** + This function disable CAR. + + @param[in] DisableCar TRUE means use INVD, FALSE means use WBINVD + +**/ +VOID +EFIAPI +DisableCacheAsRam ( + IN BOOLEAN DisableCar + ); + +#endif + diff --git a/Core/IntelFsp2Pkg/Include/Library/CacheLib.h b/Core/IntelFsp2Pkg/Include/Library/CacheLib.h new file mode 100644 index 0000000000..909ae928f1 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Library/CacheLib.h @@ -0,0 +1,62 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _CACHE_LIB_H_ +#define _CACHE_LIB_H_ + +// +// EFI_MEMORY_CACHE_TYPE +// +typedef INT32 EFI_MEMORY_CACHE_TYPE; + +#define EFI_CACHE_UNCACHEABLE 0 +#define EFI_CACHE_WRITECOMBINING 1 +#define EFI_CACHE_WRITETHROUGH 4 +#define EFI_CACHE_WRITEPROTECTED 5 +#define EFI_CACHE_WRITEBACK 6 + +/** + Reset all the MTRRs to a known state. + + @retval EFI_SUCCESS All MTRRs have been reset successfully. + +**/ +EFI_STATUS +EFIAPI +ResetCacheAttributes ( + VOID + ); + +/** + Given the memory range and cache type, programs the MTRRs. + + @param[in] MemoryAddress Base Address of Memory to program MTRR. + @param[in] MemoryLength Length of Memory to program MTRR. + @param[in] MemoryCacheType Cache Type. + + @retval EFI_SUCCESS Mtrr are set successfully. + @retval EFI_LOAD_ERROR No empty MTRRs to use. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. + @retval others An error occurs when setting MTTR. + +**/ +EFI_STATUS +EFIAPI +SetCacheAttributes ( + IN EFI_PHYSICAL_ADDRESS MemoryAddress, + IN UINT64 MemoryLength, + IN EFI_MEMORY_CACHE_TYPE MemoryCacheType + ); + +#endif + diff --git a/Core/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h b/Core/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h new file mode 100644 index 0000000000..5c35eda579 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Library/DebugDeviceLib.h @@ -0,0 +1,29 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef __DEBUG_DEVICE_LIB_H__ +#define __DEBUG_DEVICE_LIB_H__ + +/** + Returns the debug print device enable state. + + @return Debug print device enable state. + +**/ +UINT8 +EFIAPI +GetDebugPrintDeviceEnable ( + VOID + ); + +#endif diff --git a/Core/IntelFsp2Pkg/Include/Library/FspCommonLib.h b/Core/IntelFsp2Pkg/Include/Library/FspCommonLib.h new file mode 100644 index 0000000000..5f7a14b9b2 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Library/FspCommonLib.h @@ -0,0 +1,303 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_COMMON_LIB_H_ +#define _FSP_COMMON_LIB_H_ + +#include +#include + +/** + This function sets the FSP global data pointer. + + @param[in] FspData Fsp global data pointer. + +**/ +VOID +EFIAPI +SetFspGlobalDataPointer ( + IN FSP_GLOBAL_DATA *FspData + ); + +/** + This function gets the FSP global data pointer. + +**/ +FSP_GLOBAL_DATA * +EFIAPI +GetFspGlobalDataPointer ( + VOID + ); + +/** + This function gets back the FSP API first parameter passed by the bootlaoder. + + @retval ApiParameter FSP API first parameter passed by the bootlaoder. +**/ +UINT32 +EFIAPI +GetFspApiParameter ( + VOID + ); + +/** + This function gets back the FSP API second parameter passed by the bootlaoder. + + @retval ApiParameter FSP API second parameter passed by the bootlaoder. +**/ +UINT32 +EFIAPI +GetFspApiParameter2 ( + VOID + ); + +/** + This function sets the FSP API parameter in the stack. + + @param[in] Value New parameter value. + +**/ +VOID +EFIAPI +SetFspApiParameter ( + IN UINT32 Value + ); + +/** + This function set the API status code returned to the BootLoader. + + @param[in] ReturnStatus Status code to return. + +**/ +VOID +EFIAPI +SetFspApiReturnStatus ( + IN UINT32 ReturnStatus + ); + +/** + This function sets the context switching stack to a new stack frame. + + @param[in] NewStackTop New core stack to be set. + +**/ +VOID +EFIAPI +SetFspCoreStackPointer ( + IN VOID *NewStackTop + ); + +/** + This function sets the platform specific data pointer. + + @param[in] PlatformData Fsp platform specific data pointer. + +**/ +VOID +EFIAPI +SetFspPlatformDataPointer ( + IN VOID *PlatformData + ); + +/** + This function gets the platform specific data pointer. + + @param[in] PlatformData Fsp platform specific data pointer. + +**/ +VOID * +EFIAPI +GetFspPlatformDataPointer ( + VOID + ); + +/** + This function sets the UPD data pointer. + + @param[in] UpdDataPtr UPD data pointer. +**/ +VOID +EFIAPI +SetFspUpdDataPointer ( + IN VOID *UpdDataPtr + ); + +/** + This function gets the UPD data pointer. + + @return UpdDataPtr UPD data pointer. +**/ +VOID * +EFIAPI +GetFspUpdDataPointer ( + VOID + ); + +/** + This function sets the memory init UPD data pointer. + + @param[in] MemoryInitUpdPtr memory init UPD data pointer. +**/ +VOID +EFIAPI +SetFspMemoryInitUpdDataPointer ( + IN VOID *MemoryInitUpdPtr + ); + +/** + This function gets the memory init UPD data pointer. + + @return memory init UPD data pointer. +**/ +VOID * +EFIAPI +GetFspMemoryInitUpdDataPointer ( + VOID + ); + +/** + This function sets the silicon init UPD data pointer. + + @param[in] SiliconInitUpdPtr silicon init UPD data pointer. +**/ +VOID +EFIAPI +SetFspSiliconInitUpdDataPointer ( + IN VOID *SiliconInitUpdPtr + ); + +/** + This function gets the silicon init UPD data pointer. + + @return silicon init UPD data pointer. +**/ +VOID * +EFIAPI +GetFspSiliconInitUpdDataPointer ( + VOID + ); + +/** + Set FSP measurement point timestamp. + + @param[in] Id Measurement point ID. + + @return performance timestamp. +**/ +UINT64 +EFIAPI +SetFspMeasurePoint ( + IN UINT8 Id + ); + +/** + This function gets the FSP info header pointer. + + @retval FspInfoHeader FSP info header pointer +**/ +FSP_INFO_HEADER * +EFIAPI +GetFspInfoHeader ( + VOID + ); + +/** + This function sets the FSP info header pointer. + + @param[in] FspInfoHeader FSP info header pointer +**/ +VOID +EFIAPI +SetFspInfoHeader ( + FSP_INFO_HEADER *FspInfoHeader + ); + +/** + This function gets the FSP info header pointer from the API context. + + @retval FspInfoHeader FSP info header pointer +**/ +FSP_INFO_HEADER * +EFIAPI +GetFspInfoHeaderFromApiContext ( + VOID + ); + +/** + This function gets the CfgRegion data pointer. + + @return CfgRegion data pointer. +**/ +VOID * +EFIAPI +GetFspCfgRegionDataPointer ( + VOID + ); + +/** + This function gets FSP API calling mode. + + @retval API calling mode +**/ +UINT8 +EFIAPI +GetFspApiCallingIndex ( + VOID + ); + +/** + This function sets FSP API calling mode. + + @param[in] Index API calling index +**/ +VOID +EFIAPI +SetFspApiCallingIndex ( + UINT8 Index + ); + +/** + This function gets FSP Phase StatusCode. + + @retval StatusCode +**/ +UINT32 +EFIAPI +GetPhaseStatusCode ( + VOID + ); + + +/** + This function sets FSP Phase StatusCode. + + @param[in] Mode Phase StatusCode +**/ +VOID +EFIAPI +SetPhaseStatusCode ( + UINT32 StatusCode + ); + +/** + This function updates the return status of the FSP API with requested reset type and returns to Boot Loader. + + @param[in] FspResetType Reset type that needs to returned as API return status + +**/ +VOID +EFIAPI +FspApiReturnStatusReset ( + IN UINT32 FspResetType + ); +#endif diff --git a/Core/IntelFsp2Pkg/Include/Library/FspPlatformLib.h b/Core/IntelFsp2Pkg/Include/Library/FspPlatformLib.h new file mode 100644 index 0000000000..61e77bdda1 --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Library/FspPlatformLib.h @@ -0,0 +1,96 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_PLATFORM_LIB_H_ +#define _FSP_PLATFORM_LIB_H_ + +/** + Get system memory resource descriptor by owner. + + @param[in] OwnerGuid resource owner guid +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +EFIAPI +FspGetResourceDescriptorByOwner ( + IN EFI_GUID *OwnerGuid + ); + +/** + Get system memory from HOB. + + @param[in,out] LowMemoryLength less than 4G memory length + @param[in,out] HighMemoryLength greater than 4G memory length +**/ +VOID +EFIAPI +FspGetSystemMemorySize ( + IN OUT UINT64 *LowMemoryLength, + IN OUT UINT64 *HighMemoryLength + ); + + +/** + Set a new stack frame for the continuation function. + +**/ +VOID +EFIAPI +FspSetNewStackFrame ( + VOID + ); + +/** + This function transfer control back to BootLoader after FspSiliconInit. + +**/ +VOID +EFIAPI +FspSiliconInitDone ( + VOID + ); + +/** + This function returns control to BootLoader after MemoryInitApi. + + @param[in,out] HobListPtr The address of HobList pointer. +**/ +VOID +EFIAPI +FspMemoryInitDone ( + IN OUT VOID **HobListPtr + ); + +/** + This function returns control to BootLoader after TempRamExitApi. + +**/ +VOID +EFIAPI +FspTempRamExitDone ( + VOID + ); + +/** + This function handle NotifyPhase API call from the BootLoader. + It gives control back to the BootLoader after it is handled. If the + Notification code is a ReadyToBoot event, this function will return + and FSP continues the remaining execution until it reaches the DxeIpl. + +**/ +VOID +EFIAPI +FspWaitForNotify ( + VOID + ); + +#endif diff --git a/Core/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h b/Core/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h new file mode 100644 index 0000000000..cf2b0ffa2e --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Library/FspSecPlatformLib.h @@ -0,0 +1,88 @@ +/** @file + + Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_SEC_PLATFORM_LIB_H_ +#define _FSP_SEC_PLATFORM_LIB_H_ + +/** + This function performs platform level initialization. + + This function must be in ASM file, because stack is not established yet. + This function is optional. If a library instance does not provide this function, the default empty one will be used. + + The callee should not use XMM6/XMM7. + The return address is saved in MM7. + + @retval in saved in EAX - 0 means platform initialization success. + other means platform initialization fail. +**/ +UINT32 +EFIAPI +SecPlatformInit ( + VOID + ); + +/** + This function loads Microcode. + + This function must be in ASM file, because stack is not established yet. + This function is optional. If a library instance does not provide this function, the default one will be used. + + The callee should not use XMM6/XMM7. + The return address is saved in MM7. + + @param[in] FsptUpdDataPtr Address pointer to the FSPT_UPD data structure. It is saved in ESP. + + @retval in saved in EAX - 0 means Microcode is loaded successfully. + other means Microcode is not loaded successfully. +**/ +UINT32 +EFIAPI +LoadMicrocode ( + IN VOID *FsptUpdDataPtr + ); + +/** + This function initializes the CAR. + + This function must be in ASM file, because stack is not established yet. + + The callee should not use XMM6/XMM7. + The return address is saved in MM7. + + @param[in] FsptUpdDataPtr Address pointer to the FSPT_UPD data structure. It is saved in ESP. + + @retval in saved in EAX - 0 means CAR initialization success. + other means CAR initialization fail. +**/ +UINT32 +EFIAPI +SecCarInit ( + IN VOID *FsptUpdDataPtr + ); + +/** + This function check the signture of UPD. + + @param[in] ApiIdx Internal index of the FSP API. + @param[in] ApiParam Parameter of the FSP API. + +**/ +EFI_STATUS +EFIAPI +FspUpdSignatureCheck ( + IN UINT32 ApiIdx, + IN VOID *ApiParam + ); + +#endif diff --git a/Core/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h b/Core/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h new file mode 100644 index 0000000000..e90b13e8da --- /dev/null +++ b/Core/IntelFsp2Pkg/Include/Library/FspSwitchStackLib.h @@ -0,0 +1,45 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _FSP_SWITCH_STACK_LIB_H_ +#define _FSP_SWITCH_STACK_LIB_H_ + +/** + + This funciton will switch the current stack to the previous saved stack. + Before calling the previous stack has to be set in FSP_GLOBAL_DATA.CoreStack. + EIP + FLAGS 16 bit FLAGS 16 bit + EDI + ESI + EBP + ESP + EBX + EDX + ECX + EAX + DWORD IDT base1 + StackPointer: DWORD IDT base2 + + @return ReturnKey After switching to the saved stack, + this value will be saved in eax before returning. + + +**/ +UINT32 +EFIAPI +Pei2LoaderSwitchStack ( + VOID + ); + +#endif diff --git a/Core/IntelFsp2Pkg/IntelFsp2Pkg.dec b/Core/IntelFsp2Pkg/IntelFsp2Pkg.dec new file mode 100644 index 0000000000..52024af4fb --- /dev/null +++ b/Core/IntelFsp2Pkg/IntelFsp2Pkg.dec @@ -0,0 +1,80 @@ +## @file +# Provides driver and definitions to build fsp in EDKII bios. +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that 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. +# +## + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = IntelFsp2Pkg + PACKAGE_GUID = A8C53B5E-D556-4F3E-874D-0D6FA2CDC7BF + PACKAGE_VERSION = 0.1 + +[Includes] + Include + +[LibraryClasses] + ## @libraryclass Provides cache-as-ram support. + CacheAsRamLib|Include/Library/CacheAsRamLib.h + + ## @libraryclass Provides cache setting on MTRR. + CacheLib|Include/Library/CacheLib.h + + ## @libraryclass Provides debug device abstraction. + DebugDeviceLib|Include/Library/DebugDeviceLib.h + + ## @libraryclass Provides FSP related services. + FspCommonLib|Include/Library/FspCommonLib.h + + ## @libraryclass Provides FSP platform related actions. + FspPlatformLib|Include/Library/FspPlatformLib.h + + ## @libraryclass Provides FSP switch stack function. + FspSwitchStackLib|Include/Library/FspSwitchStackLib.h + + ## @libraryclass Provides FSP platform sec related actions. + FspSecPlatformLib|Include/Library/FspSecPlatformLib.h + +[Guids] + # + # GUID defined in package + # + gIntelFsp2PkgTokenSpaceGuid = { 0xed6e0531, 0xf715, 0x4a3d, { 0x9b, 0x12, 0xc1, 0xca, 0x5e, 0xf6, 0x98, 0xa2 } } + + # Guid define in FSP EAS + gFspHeaderFileGuid = { 0x912740BE, 0x2284, 0x4734, { 0xB9, 0x71, 0x84, 0xB0, 0x27, 0x35, 0x3F, 0x0C } } + gFspReservedMemoryResourceHobGuid = { 0x69a79759, 0x1373, 0x4367, { 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e } } + gFspNonVolatileStorageHobGuid = { 0x721acf02, 0x4d77, 0x4c2a, { 0xb3, 0xdc, 0x27, 0x0b, 0x7b, 0xa9, 0xe4, 0xb0 } } + gFspBootLoaderTolumHobGuid = { 0x73ff4f56, 0xaa8e, 0x4451, { 0xb3, 0x16, 0x36, 0x35, 0x36, 0x67, 0xad, 0x44 } } # FSP EAS v1.1 + + gFspPerformanceDataGuid = { 0x56ed21b6, 0xba23, 0x429e, { 0x89, 0x32, 0x37, 0x6d, 0x8e, 0x18, 0x2e, 0xe3 } } + gFspEventEndOfFirmwareGuid = { 0xbd44f629, 0xeae7, 0x4198, { 0x87, 0xf1, 0x39, 0xfa, 0xb0, 0xfd, 0x71, 0x7e } } + +[PcdsFixedAtBuild] + gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress |0xFED00108|UINT32|0x00000001 + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase |0xFEF00000|UINT32|0x10001001 + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize | 0x2000|UINT32|0x10001002 + gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize | 0x1000|UINT32|0x10001003 + gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize | 0x100|UINT32|0x10001004 + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry | 32|UINT32|0x00002001 + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry | 6|UINT32|0x00002002 + gIntelFsp2PkgTokenSpaceGuid.PcdFspAreaBaseAddress |0xFFF80000|UINT32|0x10000001 + gIntelFsp2PkgTokenSpaceGuid.PcdFspAreaSize |0x00040000|UINT32|0x10000002 + gIntelFsp2PkgTokenSpaceGuid.PcdFspBootFirmwareVolumeBase|0xFFF80000|UINT32|0x10000003 + gIntelFsp2PkgTokenSpaceGuid.PcdFspHeaderSpecVersion | 0x20| UINT8|0x00000002 + + # x % of FSP temporary memory will be used for heap + # (100 - x) % of FSP temporary memory will be used for stack + gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage | 50| UINT8|0x10000004 + +[PcdsFixedAtBuild,PcdsDynamic,PcdsDynamicEx] + gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedMemoryLength |0x00100000|UINT32|0x46530000 + gIntelFsp2PkgTokenSpaceGuid.PcdBootLoaderEntry |0xFFFFFFE4|UINT32|0x46530100 diff --git a/Core/IntelFsp2Pkg/IntelFsp2Pkg.dsc b/Core/IntelFsp2Pkg/IntelFsp2Pkg.dsc new file mode 100644 index 0000000000..61eb6f1633 --- /dev/null +++ b/Core/IntelFsp2Pkg/IntelFsp2Pkg.dsc @@ -0,0 +1,79 @@ +## @file +# Provides driver and definitions to build fsp. +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that 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. +# +## + +[Defines] + PLATFORM_NAME = IntelFsp2Pkg + PLATFORM_GUID = 55CA3D18-831B-469A-A1C3-7AE719EB6A97 + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/IntelFsp2Pkg + SUPPORTED_ARCHITECTURES = IA32 + BUILD_TARGETS = DEBUG|RELEASE|NOOPT + SKUID_IDENTIFIER = DEFAULT + +[LibraryClasses] + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + DebugDeviceLib|IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf + + # FSP override + DebugLib|IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf + + # FSP specific lib + CacheAsRamLib|IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf + CacheLib|IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf + FspCommonLib|IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf + FspPlatformLib|IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf + FspSwitchStackLib|IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf + FspSecPlatformLib|IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf + +[LibraryClasses.common.PEIM] + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + +[Components] + IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf + IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf + IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf + IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf + IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf + IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf + IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf + IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf + + IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf + IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf + IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf + IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf + +[PcdsFixedAtBuild.common] + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x80080046 + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07 diff --git a/Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf b/Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf new file mode 100644 index 0000000000..bdb6744f37 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf @@ -0,0 +1,31 @@ +## @file +# NULL instance of Base cache as RAM. +# +# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCacheAsRamLibNull + FILE_GUID = 630AEB10-2106-4234-9DB3-836A3663F50D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CacheAsRamLib + +[sources.common] + DisableCacheAsRamNull.c + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + diff --git a/Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c b/Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c new file mode 100644 index 0000000000..9b45163c34 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/DisableCacheAsRamNull.c @@ -0,0 +1,41 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include +#include + +/** + This function disable CAR. + + @param[in] DisableCar TRUE means use INVD, FALSE means use WBINVD + +**/ +VOID +EFIAPI +DisableCacheAsRam ( + IN BOOLEAN DisableCar + ) +{ + // + // Disable CAR + // + + if (DisableCar) { + AsmInvd (); + } else { + AsmWbinvd(); + } + + return ; +} diff --git a/Core/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf b/Core/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf new file mode 100644 index 0000000000..7b026b1dfc --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf @@ -0,0 +1,34 @@ +## @file +# Instance of BaseCache. +# +# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseCacheLib + FILE_GUID = 8EF3A653-DA8B-4FFA-BB85-FF47406DB9F0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = CacheLib + +[sources.IA32] + CacheLib.c + CacheLibInternal.h + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + BaseMemoryLib + CacheAsRamLib + diff --git a/Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c b/Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c new file mode 100644 index 0000000000..b38dce32a8 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c @@ -0,0 +1,703 @@ +/** @file + + Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include +#include +#include +#include "CacheLibInternal.h" + +/** + Search the memory cache type for specific memory from MTRR. + + @param[in] MemoryAddress the address of target memory + @param[in] MemoryLength the length of target memory + @param[in] ValidMtrrAddressMask the MTRR address mask + @param[out] UsedMsrNum the used MSR number + @param[out] UsedMemoryCacheType the cache type for the target memory + + @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned + @retval EFI_NOT_FOUND The memory is not found in MTRR + +**/ +EFI_STATUS +SearchForExactMtrr ( + IN EFI_PHYSICAL_ADDRESS MemoryAddress, + IN UINT64 MemoryLength, + IN UINT64 ValidMtrrAddressMask, + OUT UINT32 *UsedMsrNum, + OUT EFI_MEMORY_CACHE_TYPE *MemoryCacheType + ); + +/** + Check if CacheType match current default setting. + + @param[in] MemoryCacheType input cache type to be checked. + + @retval TRUE MemoryCacheType is default MTRR setting. + @retval FALSE MemoryCacheType is NOT default MTRR setting. +**/ +BOOLEAN +IsDefaultType ( + IN EFI_MEMORY_CACHE_TYPE MemoryCacheType + ); + +/** + Return MTRR alignment requirement for base address and size. + + @param[in] BaseAddress Base address. + @param[in] Size Size. + + @retval Zero Alligned. + @retval Non-Zero Not alligned. + +**/ +UINT32 +CheckMtrrAlignment ( + IN UINT64 BaseAddress, + IN UINT64 Size + ); + +typedef struct { + UINT32 Msr; + UINT32 BaseAddress; + UINT32 Length; +} EFI_FIXED_MTRR; + +EFI_FIXED_MTRR mFixedMtrrTable[] = { + { EFI_MSR_IA32_MTRR_FIX64K_00000, 0, 0x10000}, + { EFI_MSR_IA32_MTRR_FIX16K_80000, 0x80000, 0x4000}, + { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0xA0000, 0x4000}, + { EFI_MSR_IA32_MTRR_FIX4K_C0000, 0xC0000, 0x1000}, + { EFI_MSR_IA32_MTRR_FIX4K_C8000, 0xC8000, 0x1000}, + { EFI_MSR_IA32_MTRR_FIX4K_D0000, 0xD0000, 0x1000}, + { EFI_MSR_IA32_MTRR_FIX4K_D8000, 0xD8000, 0x1000}, + { EFI_MSR_IA32_MTRR_FIX4K_E0000, 0xE0000, 0x1000}, + { EFI_MSR_IA32_MTRR_FIX4K_E8000, 0xE8000, 0x1000}, + { EFI_MSR_IA32_MTRR_FIX4K_F0000, 0xF0000, 0x1000}, + { EFI_MSR_IA32_MTRR_FIX4K_F8000, 0xF8000, 0x1000} +}; + +/** + Given the input, check if the number of MTRR is lesser. + if positive or subtractive. + + @param[in] Input Length of Memory to program MTRR. + + @retval Zero do positive. + @retval Non-Zero do subtractive. + +**/ +INT8 +CheckDirection ( + IN UINT64 Input + ) +{ + return 0; +} + +/** + Disable cache and its mtrr. + + @param[out] OldMtrr To return the Old MTRR value + +**/ +VOID +EfiDisableCacheMtrr ( + OUT UINT64 *OldMtrr + ) +{ + UINT64 TempQword; + + // + // Disable Cache MTRR + // + *OldMtrr = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE); + TempQword = (*OldMtrr) & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE & ~B_EFI_MSR_FIXED_MTRR_ENABLE; + AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword); + AsmDisableCache (); +} + +/** + Recover cache MTRR. + + @param[in] EnableMtrr Whether to enable the MTRR + @param[in] OldMtrr The saved old MTRR value to restore when not to enable the MTRR + +**/ +VOID +EfiRecoverCacheMtrr ( + IN BOOLEAN EnableMtrr, + IN UINT64 OldMtrr + ) +{ + UINT64 TempQword; + + // + // Enable Cache MTRR + // + if (EnableMtrr) { + TempQword = AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE); + TempQword |= (UINT64)(B_EFI_MSR_GLOBAL_MTRR_ENABLE | B_EFI_MSR_FIXED_MTRR_ENABLE); + } else { + TempQword = OldMtrr; + } + + AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword); + + AsmEnableCache (); +} + +/** + Programming MTRR according to Memory address, length, and type. + + @param[in] MtrrNumber the variable MTRR index number + @param[in] MemoryAddress the address of target memory + @param[in] MemoryLength the length of target memory + @param[in] MemoryCacheType the cache type of target memory + @param[in] ValidMtrrAddressMask the MTRR address mask + +**/ +VOID +EfiProgramMtrr ( + IN UINTN MtrrNumber, + IN EFI_PHYSICAL_ADDRESS MemoryAddress, + IN UINT64 MemoryLength, + IN EFI_MEMORY_CACHE_TYPE MemoryCacheType, + IN UINT64 ValidMtrrAddressMask + ) +{ + UINT64 TempQword; + UINT64 OldMtrr; + + if (MemoryLength == 0) { + return; + } + + EfiDisableCacheMtrr (&OldMtrr); + + // + // MTRR Physical Base + // + TempQword = (MemoryAddress & ValidMtrrAddressMask) | MemoryCacheType; + AsmWriteMsr64 (MtrrNumber, TempQword); + + // + // MTRR Physical Mask + // + TempQword = ~(MemoryLength - 1); + AsmWriteMsr64 (MtrrNumber + 1, (TempQword & ValidMtrrAddressMask) | B_EFI_MSR_CACHE_MTRR_VALID); + + EfiRecoverCacheMtrr (TRUE, OldMtrr); +} + +/** + Calculate the maximum value which is a power of 2, but less the MemoryLength. + + @param[in] MemoryAddress Memory address. + @param[in] MemoryLength The number to pass in. + + @return The maximum value which is align to power of 2 and less the MemoryLength + +**/ +UINT64 +Power2MaxMemory ( + IN UINT64 MemoryAddress, + IN UINT64 MemoryLength + ) +{ + UINT64 Result; + + if (MemoryLength == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Compute inital power of 2 size to return + // + Result = GetPowerOfTwo64(MemoryLength); + + // + // Special case base of 0 as all ranges are valid + // + if (MemoryAddress == 0) { + return Result; + } + + // + // Loop till a value that can be mapped to this base address is found + // + while (CheckMtrrAlignment (MemoryAddress, Result) != 0) { + // + // Need to try the next smaller power of 2 + // + Result = RShiftU64 (Result, 1); + } + + return Result; +} + +/** + Return MTRR alignment requirement for base address and size. + + @param[in] BaseAddress Base address. + @param[in] Size Size. + + @retval Zero Alligned. + @retval Non-Zero Not alligned. + +**/ +UINT32 +CheckMtrrAlignment ( + IN UINT64 BaseAddress, + IN UINT64 Size + ) +{ + UINT32 ShiftedBase; + UINT32 ShiftedSize; + + // + // Shift base and size right 12 bits to allow for larger memory sizes. The + // MTRRs do not use the first 12 bits so this is safe for now. Only supports + // up to 52 bits of physical address space. + // + ShiftedBase = (UINT32) RShiftU64 (BaseAddress, 12); + ShiftedSize = (UINT32) RShiftU64 (Size, 12); + + // + // Return the results to the caller of the MOD + // + return ShiftedBase % ShiftedSize; +} + +/** + Programs fixed MTRRs registers. + + @param[in] MemoryCacheType The memory type to set. + @param[in] Base The base address of memory range. + @param[in] Length The length of memory range. + + @retval RETURN_SUCCESS The cache type was updated successfully + @retval RETURN_UNSUPPORTED The requested range or cache type was invalid + for the fixed MTRRs. + +**/ +EFI_STATUS +ProgramFixedMtrr ( + IN EFI_MEMORY_CACHE_TYPE MemoryCacheType, + IN UINT64 *Base, + IN UINT64 *Len + ) +{ + UINT32 MsrNum; + UINT32 ByteShift; + UINT64 TempQword; + UINT64 OrMask; + UINT64 ClearMask; + + TempQword = 0; + OrMask = 0; + ClearMask = 0; + + for (MsrNum = 0; MsrNum < V_EFI_FIXED_MTRR_NUMBER; MsrNum++) { + if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) && + (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length))) { + break; + } + } + if (MsrNum == V_EFI_FIXED_MTRR_NUMBER ) { + return EFI_DEVICE_ERROR; + } + // + // We found the fixed MTRR to be programmed + // + for (ByteShift=0; ByteShift < 8; ByteShift++) { + if ( *Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) { + break; + } + } + if (ByteShift == 8 ) { + return EFI_DEVICE_ERROR; + } + for (; ((ByteShift<8) && (*Len >= mFixedMtrrTable[MsrNum].Length));ByteShift++) { + OrMask |= LShiftU64((UINT64) MemoryCacheType, (UINT32) (ByteShift* 8)); + ClearMask |= LShiftU64((UINT64) 0xFF, (UINT32) (ByteShift * 8)); + *Len -= mFixedMtrrTable[MsrNum].Length; + *Base += mFixedMtrrTable[MsrNum].Length; + } + TempQword = (AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) & (~ClearMask)) | OrMask; + AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, TempQword); + + return EFI_SUCCESS; +} + +/** + Check if there is a valid variable MTRR that overlaps the given range. + + @param[in] Start Base Address of the range to check. + @param[in] End End address of the range to check. + + @retval TRUE Mtrr overlap. + @retval FALSE Mtrr not overlap. +**/ +BOOLEAN +CheckMtrrOverlap ( + IN EFI_PHYSICAL_ADDRESS Start, + IN EFI_PHYSICAL_ADDRESS End + ) +{ + return FALSE; +} + +/** + Given the memory range and cache type, programs the MTRRs. + + @param[in] MemoryAddress Base Address of Memory to program MTRR. + @param[in] MemoryLength Length of Memory to program MTRR. + @param[in] MemoryCacheType Cache Type. + + @retval EFI_SUCCESS Mtrr are set successfully. + @retval EFI_LOAD_ERROR No empty MTRRs to use. + @retval EFI_INVALID_PARAMETER The input parameter is not valid. + @retval others An error occurs when setting MTTR. + +**/ +EFI_STATUS +EFIAPI +SetCacheAttributes ( + IN EFI_PHYSICAL_ADDRESS MemoryAddress, + IN UINT64 MemoryLength, + IN EFI_MEMORY_CACHE_TYPE MemoryCacheType + ) +{ + EFI_STATUS Status; + UINT32 MsrNum, MsrNumEnd; + UINT64 TempQword; + UINT32 LastVariableMtrrForBios; + UINT64 OldMtrr; + UINT32 UsedMsrNum; + EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType; + UINT64 ValidMtrrAddressMask; + UINT32 Cpuid_RegEax; + + AsmCpuid (CPUID_EXTENDED_FUNCTION, &Cpuid_RegEax, NULL, NULL, NULL); + if (Cpuid_RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) { + AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Cpuid_RegEax, NULL, NULL, NULL); + ValidMtrrAddressMask = (LShiftU64((UINT64) 1, (Cpuid_RegEax & 0xFF)) - 1) & (~(UINT64)0x0FFF); + } else { + ValidMtrrAddressMask = (LShiftU64((UINT64) 1, 36) - 1) & (~(UINT64)0x0FFF); + } + + // + // Check for invalid parameter + // + if ((MemoryAddress & ~ValidMtrrAddressMask) != 0 || (MemoryLength & ~ValidMtrrAddressMask) != 0) { + return EFI_INVALID_PARAMETER; + } + + if (MemoryLength == 0) { + return EFI_INVALID_PARAMETER; + } + + switch (MemoryCacheType) { + case EFI_CACHE_UNCACHEABLE: + case EFI_CACHE_WRITECOMBINING: + case EFI_CACHE_WRITETHROUGH: + case EFI_CACHE_WRITEPROTECTED: + case EFI_CACHE_WRITEBACK: + break; + + default: + return EFI_INVALID_PARAMETER; + } + + // + // Check if Fixed MTRR + // + if ((MemoryAddress + MemoryLength) <= (1 << 20)) { + Status = EFI_SUCCESS; + EfiDisableCacheMtrr (&OldMtrr); + while ((MemoryLength > 0) && (Status == EFI_SUCCESS)) { + Status = ProgramFixedMtrr (MemoryCacheType, &MemoryAddress, &MemoryLength); + } + EfiRecoverCacheMtrr (TRUE, OldMtrr); + return Status; + } + + // + // Search if the range attribute has been set before + // + Status = SearchForExactMtrr( + MemoryAddress, + MemoryLength, + ValidMtrrAddressMask, + &UsedMsrNum, + &UsedMemoryCacheType + ); + + if (!EFI_ERROR(Status)) { + // + // Compare if it has the same type as current setting + // + if (UsedMemoryCacheType == MemoryCacheType) { + return EFI_SUCCESS; + } else { + // + // Different type + // + + // + // Check if the set type is the same as Default Type + // + if (IsDefaultType(MemoryCacheType)) { + // + // Clear the MTRR + // + AsmWriteMsr64(UsedMsrNum, 0); + AsmWriteMsr64(UsedMsrNum + 1, 0); + + return EFI_SUCCESS; + } else { + // + // Modify the MTRR type + // + EfiProgramMtrr(UsedMsrNum, + MemoryAddress, + MemoryLength, + MemoryCacheType, + ValidMtrrAddressMask + ); + return EFI_SUCCESS; + } + } + } + +#if 0 + // + // @bug - Need to create memory map so that when checking for overlap we + // can determine if an overlap exists based on all caching requests. + // + // Don't waste a variable MTRR if the caching attrib is same as default in MTRR_DEF_TYPE + // + if (MemoryCacheType == (AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE)) { + if (!CheckMtrrOverlap (MemoryAddress, MemoryAddress+MemoryLength-1)) { + return EFI_SUCCESS; + } + } +#endif + + // + // Find first unused MTRR + // + MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT)); + for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) { + if ((AsmReadMsr64(MsrNum+1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0 ) { + break; + } + } + + // + // Reserve 1 MTRR pair for OS. + // + LastVariableMtrrForBios = MsrNumEnd - 1 - (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2); + if (MsrNum > LastVariableMtrrForBios) { + return EFI_LOAD_ERROR; + } + + // + // Special case for 1 MB base address + // + if (MemoryAddress == BASE_1MB) { + MemoryAddress = 0; + } + + // + // Program MTRRs + // + TempQword = MemoryLength; + + if (TempQword == Power2MaxMemory(MemoryAddress, TempQword)) { + EfiProgramMtrr(MsrNum, + MemoryAddress, + MemoryLength, + MemoryCacheType, + ValidMtrrAddressMask + ); + + } else { + // + // Fill in MTRRs with values. Direction can not be checked for this method + // as we are using WB as the default cache type and only setting areas to UC. + // + do { + // + // Do boundary check so we don't go past last MTRR register + // for BIOS use. Leave one MTRR pair for OS use. + // + if (MsrNum > LastVariableMtrrForBios) { + return EFI_LOAD_ERROR; + } + + // + // Set next power of 2 region + // + MemoryLength = Power2MaxMemory(MemoryAddress, TempQword); + EfiProgramMtrr(MsrNum, + MemoryAddress, + MemoryLength, + MemoryCacheType, + ValidMtrrAddressMask + ); + MemoryAddress += MemoryLength; + TempQword -= MemoryLength; + MsrNum += 2; + } while (TempQword != 0); + } + + return EFI_SUCCESS; +} + +/** + Reset all the MTRRs to a known state. + + @retval EFI_SUCCESS All MTRRs have been reset successfully. + +**/ +EFI_STATUS +EFIAPI +ResetCacheAttributes ( + VOID + ) +{ + UINT32 MsrNum, MsrNumEnd; + UINT16 Index; + UINT64 OldMtrr; + UINT64 CacheType; + BOOLEAN DisableCar; + Index = 0; + DisableCar = TRUE; + + // + // Determine default cache type + // + CacheType = EFI_CACHE_UNCACHEABLE; + + // + // Set default cache type + // + AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, CacheType); + + // + // Disable CAR + // + DisableCacheAsRam (DisableCar); + + EfiDisableCacheMtrr (&OldMtrr); + + // + // Reset Fixed MTRRs + // + for (Index = 0; Index < V_EFI_FIXED_MTRR_NUMBER; Index++) { + AsmWriteMsr64 (mFixedMtrrTable[Index].Msr, 0); + } + + // + // Reset Variable MTRRs + // + MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT)); + for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum++) { + AsmWriteMsr64 (MsrNum, 0); + } + + // + // Enable Fixed and Variable MTRRs + // + EfiRecoverCacheMtrr (TRUE, OldMtrr); + + return EFI_SUCCESS; +} + +/** + Search the memory cache type for specific memory from MTRR. + + @param[in] MemoryAddress the address of target memory + @param[in] MemoryLength the length of target memory + @param[in] ValidMtrrAddressMask the MTRR address mask + @param[out] UsedMsrNum the used MSR number + @param[out] UsedMemoryCacheType the cache type for the target memory + + @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned + @retval EFI_NOT_FOUND The memory is not found in MTRR + +**/ +EFI_STATUS +SearchForExactMtrr ( + IN EFI_PHYSICAL_ADDRESS MemoryAddress, + IN UINT64 MemoryLength, + IN UINT64 ValidMtrrAddressMask, + OUT UINT32 *UsedMsrNum, + OUT EFI_MEMORY_CACHE_TYPE *UsedMemoryCacheType + ) +{ + UINT32 MsrNum, MsrNumEnd; + UINT64 TempQword; + + if (MemoryLength == 0) { + return EFI_INVALID_PARAMETER; + } + + MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT)); + for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum +=2) { + TempQword = AsmReadMsr64(MsrNum+1); + if ((TempQword & B_EFI_MSR_CACHE_MTRR_VALID) == 0) { + continue; + } + + if ((TempQword & ValidMtrrAddressMask) != ((~(MemoryLength - 1)) & ValidMtrrAddressMask)) { + continue; + } + + TempQword = AsmReadMsr64 (MsrNum); + if ((TempQword & ValidMtrrAddressMask) != (MemoryAddress & ValidMtrrAddressMask)) { + continue; + } + + *UsedMemoryCacheType = (EFI_MEMORY_CACHE_TYPE)(TempQword & B_EFI_MSR_CACHE_MEMORY_TYPE); + *UsedMsrNum = MsrNum; + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +/** + Check if CacheType match current default setting. + + @param[in] MemoryCacheType input cache type to be checked. + + @retval TRUE MemoryCacheType is default MTRR setting. + @retval TRUE MemoryCacheType is NOT default MTRR setting. +**/ +BOOLEAN +IsDefaultType ( + IN EFI_MEMORY_CACHE_TYPE MemoryCacheType + ) +{ + if ((AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE) != MemoryCacheType) { + return FALSE; + } + + return TRUE; +} + diff --git a/Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h b/Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h new file mode 100644 index 0000000000..fbbf551dde --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseCacheLib/CacheLibInternal.h @@ -0,0 +1,59 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#ifndef _CACHE_LIB_INTERNAL_H_ +#define _CACHE_LIB_INTERNAL_H_ + +#define EFI_MSR_CACHE_VARIABLE_MTRR_BASE 0x00000200 +#define EFI_MSR_CACHE_VARIABLE_MTRR_END 0x0000020F +#define V_EFI_FIXED_MTRR_NUMBER 11 + +#define EFI_MSR_IA32_MTRR_FIX64K_00000 0x00000250 +#define EFI_MSR_IA32_MTRR_FIX16K_80000 0x00000258 +#define EFI_MSR_IA32_MTRR_FIX16K_A0000 0x00000259 +#define EFI_MSR_IA32_MTRR_FIX4K_C0000 0x00000268 +#define EFI_MSR_IA32_MTRR_FIX4K_C8000 0x00000269 +#define EFI_MSR_IA32_MTRR_FIX4K_D0000 0x0000026A +#define EFI_MSR_IA32_MTRR_FIX4K_D8000 0x0000026B +#define EFI_MSR_IA32_MTRR_FIX4K_E0000 0x0000026C +#define EFI_MSR_IA32_MTRR_FIX4K_E8000 0x0000026D +#define EFI_MSR_IA32_MTRR_FIX4K_F0000 0x0000026E +#define EFI_MSR_IA32_MTRR_FIX4K_F8000 0x0000026F +#define EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE 0x000002FF +#define B_EFI_MSR_CACHE_MTRR_VALID BIT11 +#define B_EFI_MSR_GLOBAL_MTRR_ENABLE BIT11 +#define B_EFI_MSR_FIXED_MTRR_ENABLE BIT10 +#define B_EFI_MSR_CACHE_MEMORY_TYPE (BIT2 | BIT1 | BIT0) + +#define EFI_MSR_VALID_MASK 0xFFFFFFFFF +#define EFI_CACHE_VALID_ADDRESS 0xFFFFFF000 +#define EFI_SMRR_CACHE_VALID_ADDRESS 0xFFFFF000 +#define EFI_CACHE_VALID_EXTENDED_ADDRESS 0xFFFFFFFFFF000 + +// Leave one MTRR pairs for OS use +#define EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS 1 +#define EFI_CACHE_LAST_VARIABLE_MTRR_FOR_BIOS (EFI_MSR_CACHE_VARIABLE_MTRR_END) - \ + (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2) + +#define EFI_MSR_IA32_MTRR_CAP 0x000000FE +#define B_EFI_MSR_IA32_MTRR_CAP_EMRR_SUPPORT BIT12 +#define B_EFI_MSR_IA32_MTRR_CAP_SMRR_SUPPORT BIT11 +#define B_EFI_MSR_IA32_MTRR_CAP_WC_SUPPORT BIT10 +#define B_EFI_MSR_IA32_MTRR_CAP_FIXED_SUPPORT BIT8 +#define B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT (BIT7 | BIT6 | BIT5 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0) + +#define CPUID_VIR_PHY_ADDRESS_SIZE 0x80000008 +#define CPUID_EXTENDED_FUNCTION 0x80000000 + +#endif + diff --git a/Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf b/Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf new file mode 100644 index 0000000000..5e4c572973 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/BaseDebugDeviceLibNull.inf @@ -0,0 +1,34 @@ +## @file +# Debug device library instance that retrieves the current enabling state for +# the platform debug output device. +# +# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseDebugDeviceLibNull + FILE_GUID = 5E975522-176F-4E2D-BB25-64ADCC7792A4 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugDeviceLib + +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources] + DebugDeviceLibNull.c + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + diff --git a/Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c b/Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c new file mode 100644 index 0000000000..95c100472c --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseDebugDeviceLibNull/DebugDeviceLibNull.c @@ -0,0 +1,31 @@ +/** @file + Debug device library instance that retrieves the current enabling state for + the platform debug output device. + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include + +/** + Returns the debug print device enable state. + + @return Debug print device enable state. + +**/ +UINT8 +EFIAPI +GetDebugPrintDeviceEnable ( + VOID + ) +{ + return 1; +} diff --git a/Core/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf b/Core/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf new file mode 100644 index 0000000000..df8803a036 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf @@ -0,0 +1,40 @@ +## @file +# Instance of FspCommonLib +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseFspCommonLib + FILE_GUID = 38BE57E8-902C-485A-AB5E-D5AEC613194D + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FspCommonLib + +[Sources] + FspCommonLib.c + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + BaseMemoryLib + FspSwitchStackLib + +[Pcd] + gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress ## CONSUMES + +[FixedPcd] + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES diff --git a/Core/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c b/Core/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c new file mode 100644 index 0000000000..660e9fc696 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspCommonLib/FspCommonLib.c @@ -0,0 +1,533 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma pack(1) + +// +// API Parameter +0x34 +// API return address +0x30 +// +// push FspInfoHeader +0x2C +// pushfd +0x28 +// cli +// pushad +0x24 +// sub esp, 8 +0x00 +// sidt fword ptr [esp] +// +typedef struct { + UINT16 IdtrLimit; + UINT32 IdtrBase; + UINT16 Reserved; + UINT32 Edi; + UINT32 Esi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Ebx; + UINT32 Edx; + UINT32 Ecx; + UINT32 Eax; + UINT16 Flags[2]; + UINT32 FspInfoHeader; + UINT32 ApiRet; + UINT32 ApiParam[2]; +} CONTEXT_STACK; + +#define CONTEXT_STACK_OFFSET(x) (UINT32)&((CONTEXT_STACK *)(UINTN)0)->x + +#pragma pack() + +/** + This function sets the FSP global data pointer. + + @param[in] FspData Fsp global data pointer. + +**/ +VOID +EFIAPI +SetFspGlobalDataPointer ( + IN FSP_GLOBAL_DATA *FspData + ) +{ + ASSERT (FspData != NULL); + *((volatile UINT32 *)(UINTN)PcdGet32(PcdGlobalDataPointerAddress)) = (UINT32)(UINTN)FspData; +} + +/** + This function gets the FSP global data pointer. + +**/ +FSP_GLOBAL_DATA * +EFIAPI +GetFspGlobalDataPointer ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = *(FSP_GLOBAL_DATA **)(UINTN)PcdGet32(PcdGlobalDataPointerAddress); + return FspData; +} + +/** + This function gets back the FSP API first parameter passed by the bootlaoder. + + @retval ApiParameter FSP API first parameter passed by the bootlaoder. +**/ +UINT32 +EFIAPI +GetFspApiParameter ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + return *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam[0])); +} + +/** + This function gets back the FSP API second parameter passed by the bootlaoder. + + @retval ApiParameter FSP API second parameter passed by the bootlaoder. +**/ +UINT32 +EFIAPI +GetFspApiParameter2 ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + return *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam[1])); +} + +/** + This function sets the FSP API parameter in the stack. + + @param[in] Value New parameter value. + +**/ +VOID +EFIAPI +SetFspApiParameter ( + IN UINT32 Value + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(ApiParam)) = Value; +} + +/** + This function set the API status code returned to the BootLoader. + + @param[in] ReturnStatus Status code to return. + +**/ +VOID +EFIAPI +SetFspApiReturnStatus ( + IN UINT32 ReturnStatus + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + *(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(Eax)) = ReturnStatus; +} + +/** + This function sets the context switching stack to a new stack frame. + + @param[in] NewStackTop New core stack to be set. + +**/ +VOID +EFIAPI +SetFspCoreStackPointer ( + IN VOID *NewStackTop + ) +{ + FSP_GLOBAL_DATA *FspData; + UINT32 *OldStack; + UINT32 *NewStack; + UINT32 StackContextLen; + + FspData = GetFspGlobalDataPointer (); + StackContextLen = sizeof(CONTEXT_STACK) / sizeof(UINT32); + + // + // Reserve space for the ContinuationFunc two parameters + // + OldStack = (UINT32 *)FspData->CoreStack; + NewStack = (UINT32 *)NewStackTop - StackContextLen - 2; + FspData->CoreStack = (UINT32)NewStack; + while (StackContextLen-- != 0) { + *NewStack++ = *OldStack++; + } +} + +/** + This function sets the platform specific data pointer. + + @param[in] PlatformData Fsp platform specific data pointer. + +**/ +VOID +EFIAPI +SetFspPlatformDataPointer ( + IN VOID *PlatformData + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + FspData->PlatformData.DataPtr = PlatformData; +} + + +/** + This function gets the platform specific data pointer. + + @param[in] PlatformData Fsp platform specific data pointer. + +**/ +VOID * +EFIAPI +GetFspPlatformDataPointer ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + return FspData->PlatformData.DataPtr; +} + + +/** + This function sets the UPD data pointer. + + @param[in] UpdDataPtr UPD data pointer. +**/ +VOID +EFIAPI +SetFspUpdDataPointer ( + IN VOID *UpdDataPtr + ) +{ + FSP_GLOBAL_DATA *FspData; + + // + // Get the Fsp Global Data Pointer + // + FspData = GetFspGlobalDataPointer (); + + // + // Set the UPD pointer. + // + FspData->UpdDataPtr = UpdDataPtr; +} + +/** + This function gets the UPD data pointer. + + @return UpdDataPtr UPD data pointer. +**/ +VOID * +EFIAPI +GetFspUpdDataPointer ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + return FspData->UpdDataPtr; +} + + +/** + This function sets the memory init UPD data pointer. + + @param[in] MemoryInitUpdPtr memory init UPD data pointer. +**/ +VOID +EFIAPI +SetFspMemoryInitUpdDataPointer ( + IN VOID *MemoryInitUpdPtr + ) +{ + FSP_GLOBAL_DATA *FspData; + + // + // Get the Fsp Global Data Pointer + // + FspData = GetFspGlobalDataPointer (); + + // + // Set the memory init UPD pointer. + // + FspData->MemoryInitUpdPtr = MemoryInitUpdPtr; +} + +/** + This function gets the memory init UPD data pointer. + + @return memory init UPD data pointer. +**/ +VOID * +EFIAPI +GetFspMemoryInitUpdDataPointer ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + return FspData->MemoryInitUpdPtr; +} + + +/** + This function sets the silicon init UPD data pointer. + + @param[in] SiliconInitUpdPtr silicon init UPD data pointer. +**/ +VOID +EFIAPI +SetFspSiliconInitUpdDataPointer ( + IN VOID *SiliconInitUpdPtr + ) +{ + FSP_GLOBAL_DATA *FspData; + + // + // Get the Fsp Global Data Pointer + // + FspData = GetFspGlobalDataPointer (); + + // + // Set the silicon init UPD data pointer. + // + FspData->SiliconInitUpdPtr = SiliconInitUpdPtr; +} + +/** + This function gets the silicon init UPD data pointer. + + @return silicon init UPD data pointer. +**/ +VOID * +EFIAPI +GetFspSiliconInitUpdDataPointer ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + return FspData->SiliconInitUpdPtr; +} + + +/** + Set FSP measurement point timestamp. + + @param[in] Id Measurement point ID. + + @return performance timestamp. +**/ +UINT64 +EFIAPI +SetFspMeasurePoint ( + IN UINT8 Id + ) +{ + FSP_GLOBAL_DATA *FspData; + + // + // Bit [55: 0] will be the timestamp + // Bit [63:56] will be the ID + // + FspData = GetFspGlobalDataPointer (); + if (FspData->PerfIdx < sizeof(FspData->PerfData) / sizeof(FspData->PerfData[0])) { + FspData->PerfData[FspData->PerfIdx] = AsmReadTsc (); + ((UINT8 *)(&FspData->PerfData[FspData->PerfIdx]))[7] = Id; + } + + return FspData->PerfData[(FspData->PerfIdx)++]; +} + +/** + This function gets the FSP info header pointer. + + @retval FspInfoHeader FSP info header pointer +**/ +FSP_INFO_HEADER * +EFIAPI +GetFspInfoHeader ( + VOID + ) +{ + return GetFspGlobalDataPointer()->FspInfoHeader; +} + +/** + This function sets the FSP info header pointer. + + @param[in] FspInfoHeader FSP info header pointer +**/ +VOID +EFIAPI +SetFspInfoHeader ( + FSP_INFO_HEADER *FspInfoHeader + ) +{ + GetFspGlobalDataPointer()->FspInfoHeader = FspInfoHeader; +} + +/** + This function gets the FSP info header pointer using the API stack context. + + @retval FspInfoHeader FSP info header pointer using the API stack context +**/ +FSP_INFO_HEADER * +EFIAPI +GetFspInfoHeaderFromApiContext ( + VOID + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + return (FSP_INFO_HEADER *)(*(UINT32 *)(UINTN)(FspData->CoreStack + CONTEXT_STACK_OFFSET(FspInfoHeader))); +} + +/** + This function gets the CfgRegion data pointer. + + @return CfgRegion data pointer. +**/ +VOID * +EFIAPI +GetFspCfgRegionDataPointer ( + VOID + ) +{ + FSP_INFO_HEADER *FspInfoHeader; + + FspInfoHeader = GetFspInfoHeader (); + return (VOID *)(FspInfoHeader->ImageBase + FspInfoHeader->CfgRegionOffset); +} + +/** + This function gets FSP API calling index. + + @retval API calling index +**/ +UINT8 +EFIAPI +GetFspApiCallingIndex ( + VOID + ) +{ + return GetFspGlobalDataPointer()->ApiIdx; +} + +/** + This function sets FSP API calling mode. + + @param[in] Index API calling index +**/ +VOID +EFIAPI +SetFspApiCallingIndex ( + UINT8 Index + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + FspData->ApiIdx = Index; +} + +/** + This function gets FSP Phase StatusCode. + + @retval StatusCode +**/ +UINT32 +EFIAPI +GetPhaseStatusCode ( + VOID + ) +{ + return GetFspGlobalDataPointer()->StatusCode; +} + +/** + This function sets FSP Phase StatusCode. + + @param[in] Mode Phase StatusCode +**/ +VOID +EFIAPI +SetPhaseStatusCode ( + UINT32 StatusCode + ) +{ + FSP_GLOBAL_DATA *FspData; + + FspData = GetFspGlobalDataPointer (); + FspData->StatusCode = StatusCode; +} + +/** + This function updates the return status of the FSP API with requested reset type and returns to Boot Loader. + + @param[in] FspResetType Reset type that needs to returned as API return status + +**/ +VOID +EFIAPI +FspApiReturnStatusReset ( + IN UINT32 FspResetType + ) +{ + volatile BOOLEAN LoopUntilReset; + + LoopUntilReset = TRUE; + DEBUG ((DEBUG_INFO, "FSP returning control to Bootloader with reset required return status %x\n",FspResetType)); + /// + /// Below code is not an infinite loop.The control will go back to API calling function in BootLoader each time BootLoader + /// calls the FSP API without honoring the reset request by FSP + /// + do { + SetFspApiReturnStatus ((EFI_STATUS)FspResetType); + Pei2LoaderSwitchStack (); + DEBUG ((DEBUG_ERROR, "!!!ERROR: FSP has requested BootLoader for reset. But BootLoader has not honored the reset\n")); + DEBUG ((DEBUG_ERROR, "!!!ERROR: Please add support in BootLoader to honour the reset request from FSP\n")); + } while (LoopUntilReset); +} diff --git a/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf b/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf new file mode 100644 index 0000000000..49adfd8c82 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/BaseFspDebugLibSerialPort.inf @@ -0,0 +1,50 @@ +## @file +# Instance of BaseFspDebugLib +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseFspDebugLibSerialPort + FILE_GUID = CEA4FF9C-D7BC-4F07-96F1-03F41F2B17AE + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = DebugLib + +# +# VALID_ARCHITECTURES = IA32 +# + +[Sources] + DebugLib.c + +[Sources.Ia32] + Ia32/FspDebug.nasm + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + SerialPortLib + BaseMemoryLib + PcdLib + PrintLib + BaseLib + DebugDeviceLib + DebugPrintErrorLevelLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES + diff --git a/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c b/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c new file mode 100644 index 0000000000..73bb08e357 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/DebugLib.c @@ -0,0 +1,328 @@ +/** @file + + Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +CONST CHAR8 *mHexTable = "0123456789ABCDEF"; + +/** + Get stack frame pointer of function call. + + @return StackFramePointer stack frame pointer of function call. +**/ +UINT32 * +EFIAPI +GetStackFramePointer ( + VOID + ); + + +/** + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function + GetDebugPrintErrorLevel (), then print the message specified by Format and the + associated variable argument list to the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + @param ... Variable argument list whose contents are accessed + based on the format string specified by Format. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CONST CHAR8 *Format, + ... + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // If Format is NULL, then ASSERT(). + // + if (!GetDebugPrintDeviceEnable ()) { + return; + } + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) { + return; + } + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Convert the DEBUG() message to an ASCII String + // + VA_START (Marker, Format); + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); + + // + // Send the print string to a Serial Port + // + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); +} + +/** + Convert an UINT32 value into HEX string sepcified by Buffer. + + @param Value The HEX value to convert to string + @param Buffer The pointer to the target buffer to be filled with HEX string + +**/ +VOID +FillHex ( + UINT32 Value, + CHAR8 *Buffer + ) +{ + INTN Idx; + for (Idx = 7; Idx >= 0; Idx--) { + Buffer[Idx] = mHexTable[Value & 0x0F]; + Value >>= 4; + } +} + +/** + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form "ASSERT (): \n" + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recursion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of "(NULL) Filename" is printed. + If Description is NULL, then a string of "(NULL) Description" is printed. + +**/ +VOID +DebugAssertInternal ( + VOID + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + UINT32 *Frame; + + Frame = (UINT32 *)GetStackFramePointer (); + + // + // Generate the ASSERT() message in Ascii format + // + AsciiStrnCpyS ( + Buffer, + sizeof(Buffer) / sizeof(CHAR8), + "-> EBP:0x00000000 EIP:0x00000000\n", + sizeof(Buffer) / sizeof(CHAR8) - 1 + ); + SerialPortWrite ((UINT8 *)"ASSERT DUMP:\n", 13); + while (Frame != NULL) { + FillHex ((UINT32)Frame, Buffer + 9); + FillHex (Frame[1], Buffer + 9 + 8 + 8); + SerialPortWrite ((UINT8 *)Buffer, AsciiStrLen (Buffer)); + if ((Frame[0] > (UINT32)Frame) && (Frame[0] < (UINT32)Frame + 0x00100000)) { + Frame = (UINT32 *)Frame[0]; + } else { + Frame = NULL; + } + } + + // + // Dead loop + // + CpuDeadLoop (); +} + +/** + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form "ASSERT (): \n" + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recursion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of "(NULL) Filename" is printed. + If Description is NULL, then a string of "(NULL) Description" is printed. + + @param FileName The pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description The pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CONST CHAR8 *FileName, + IN UINTN LineNumber, + IN CONST CHAR8 *Description + ) +{ + DebugAssertInternal (); +} + + +/** + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue. + @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue. + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return Buffer; +} + + +/** + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + Returns TRUE if DEBUG() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + +/** + Returns TRUE if DEBUG_CODE() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} + +/** + Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel. + + This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel. + + @retval TRUE Current ErrorLevel is supported. + @retval FALSE Current ErrorLevel is not supported. + +**/ +BOOLEAN +EFIAPI +DebugPrintLevelEnabled ( + IN CONST UINTN ErrorLevel + ) +{ + return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0); +} diff --git a/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm b/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm new file mode 100644 index 0000000000..fd20b0d5ac --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspDebugLibSerialPort/Ia32/FspDebug.nasm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; 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. +; +; Abstract: +; +; FSP Debug functions +; +;------------------------------------------------------------------------------ + + SECTION .text + +;------------------------------------------------------------------------------ +; UINT32 * +; EFIAPI +; GetStackFramePointer ( +; VOID +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(GetStackFramePointer) +ASM_PFX(GetStackFramePointer): + mov eax, ebp + ret + diff --git a/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf b/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf new file mode 100644 index 0000000000..d04689ef88 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf @@ -0,0 +1,50 @@ +## @file +# Instance of FspPlatformLib +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseFspPlatformLib + FILE_GUID = B6380BFB-7140-4C52-AC42-8C966C9A3F34 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FspPlatformLib + +[Sources] + FspPlatformMemory.c + FspPlatformNotify.c + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + BaseMemoryLib + MemoryAllocationLib + FspCommonLib + PerformanceLib + ReportStatusCodeLib + +[Pcd] + gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES + +[Guids] + gFspPerformanceDataGuid ## CONSUMES ## GUID + gFspEventEndOfFirmwareGuid ## PRODUCES ## GUID + +[FixedPcd] + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry ## CONSUMES diff --git a/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c b/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c new file mode 100644 index 0000000000..edb8d67223 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformMemory.c @@ -0,0 +1,122 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Get system memory resource descriptor by owner. + + @param[in] OwnerGuid resource owner guid +**/ +EFI_HOB_RESOURCE_DESCRIPTOR * +EFIAPI +FspGetResourceDescriptorByOwner ( + IN EFI_GUID *OwnerGuid + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + // + // Get the HOB list for processing + // + Hob.Raw = GetHobList (); + + // + // Collect memory ranges + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) && \ + (CompareGuid (&Hob.ResourceDescriptor->Owner, OwnerGuid))) { + return Hob.ResourceDescriptor; + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + + return NULL; +} + +/** + Get system memory from HOB. + + @param[in,out] LowMemoryLength less than 4G memory length + @param[in,out] HighMemoryLength greater than 4G memory length +**/ +VOID +EFIAPI +FspGetSystemMemorySize ( + IN OUT UINT64 *LowMemoryLength, + IN OUT UINT64 *HighMemoryLength + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + EFI_PEI_HOB_POINTERS Hob; + + ResourceAttribute = ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ); + + Status = PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR (Status); + + if (BootMode != BOOT_ON_S3_RESUME) { + ResourceAttribute |= EFI_RESOURCE_ATTRIBUTE_TESTED; + } + + *HighMemoryLength = 0; + *LowMemoryLength = SIZE_1MB; + // + // Get the HOB list for processing + // + Hob.Raw = GetHobList (); + + // + // Collect memory ranges + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + if ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) || + ((Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_RESERVED) && + (Hob.ResourceDescriptor->ResourceAttribute == ResourceAttribute))) { + // + // Need memory above 1MB to be collected here + // + if (Hob.ResourceDescriptor->PhysicalStart >= BASE_1MB && + Hob.ResourceDescriptor->PhysicalStart < (EFI_PHYSICAL_ADDRESS) BASE_4GB) { + *LowMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } else if (Hob.ResourceDescriptor->PhysicalStart >= (EFI_PHYSICAL_ADDRESS) BASE_4GB) { + *HighMemoryLength += (UINT64) (Hob.ResourceDescriptor->ResourceLength); + } + } + } + Hob.Raw = GET_NEXT_HOB (Hob); + } +} diff --git a/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c b/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c new file mode 100644 index 0000000000..66b6cdb878 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspPlatformLib/FspPlatformNotify.c @@ -0,0 +1,279 @@ +/** @file + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern EFI_GUID gFspPerformanceDataGuid; + +EFI_PEI_PPI_DESCRIPTOR mPeiPostPciEnumerationPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPciEnumerationCompleteProtocolGuid, + NULL +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiReadyToBootPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEventReadyToBootGuid, + NULL +}; + +EFI_PEI_PPI_DESCRIPTOR mPeiEndOfFirmwarePpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gFspEventEndOfFirmwareGuid, + NULL +}; + +UINT32 mFspNotifySequence[] = { + EnumInitPhaseAfterPciEnumeration, + EnumInitPhaseReadyToBoot, + EnumInitPhaseEndOfFirmware +}; + +/** + Install FSP notification. + + @param[in] NotificationCode FSP notification code + + @retval EFI_SUCCESS Notify FSP successfully + @retval EFI_INVALID_PARAMETER NotificationCode is invalid + +**/ +EFI_STATUS +EFIAPI +FspNotificationHandler ( + IN UINT32 NotificationCode + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + switch (NotificationCode) { + case EnumInitPhaseAfterPciEnumeration: + // + // Do POST PCI initialization if needed + // + DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP Post PCI Enumeration ...\n")); + PeiServicesInstallPpi (&mPeiPostPciEnumerationPpi); + break; + + case EnumInitPhaseReadyToBoot: + // + // Ready To Boot + // + DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP Ready To Boot ...\n")); + PeiServicesInstallPpi (&mPeiReadyToBootPpi); + break; + + case EnumInitPhaseEndOfFirmware: + // + // End of Firmware + // + DEBUG ((DEBUG_INFO| DEBUG_INIT, "FSP End of Firmware ...\n")); + PeiServicesInstallPpi (&mPeiEndOfFirmwarePpi); + break; + + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + return Status; +} + +/** + This function transfer control back to BootLoader after FspSiliconInit. + +**/ +VOID +EFIAPI +FspSiliconInitDone ( + VOID + ) +{ + // + // This is the end of the FspSiliconInit API + // Give control back to the boot loader + // + SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_EXIT); + DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - End\n")); + + PERF_END_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x907F); + + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); + SetFspApiReturnStatus (EFI_SUCCESS); + + Pei2LoaderSwitchStack(); + + PERF_START_EX (&gFspPerformanceDataGuid, "EventRec", NULL, 0, 0x6000); +} + +/** + This function returns control to BootLoader after MemoryInitApi. + + @param[in,out] HobListPtr The address of HobList pointer. +**/ +VOID +EFIAPI +FspMemoryInitDone ( + IN OUT VOID **HobListPtr + ) +{ + // + // Calling use FspMemoryInit API + // Update HOB and return the control directly + // + if (HobListPtr != NULL) { + *HobListPtr = (VOID *) GetHobList (); + } + + // + // This is the end of the FspMemoryInit API + // Give control back to the boot loader + // + SetFspMeasurePoint (FSP_PERF_ID_API_FSP_MEMORY_INIT_EXIT); + DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspMemoryInitApi() - End\n")); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_MEMORY_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); + SetFspApiReturnStatus (EFI_SUCCESS); + Pei2LoaderSwitchStack (); + + // + // The TempRamExitApi is called + // + if (GetFspApiCallingIndex () == TempRamExitApiIndex) { + SetPhaseStatusCode (FSP_STATUS_CODE_TEMP_RAM_EXIT); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); + SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_ENTRY); + DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - Begin\n")); + } else { + SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); + DEBUG ((DEBUG_INFO | DEBUG_INIT, "FspSiliconInitApi() - Begin\n")); + SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); + } +} + +/** + This function returns control to BootLoader after TempRamExitApi. + +**/ +VOID +EFIAPI +FspTempRamExitDone ( + VOID + ) +{ + + // + // This is the end of the TempRamExit API + // Give control back to the boot loader + // + SetFspMeasurePoint (FSP_PERF_ID_API_TEMP_RAM_EXIT_EXIT); + DEBUG ((DEBUG_INFO | DEBUG_INIT, "TempRamExitApi() - End\n")); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_TEMP_RAM_EXIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); + SetFspApiReturnStatus (EFI_SUCCESS); + Pei2LoaderSwitchStack (); + + SetPhaseStatusCode (FSP_STATUS_CODE_SILICON_INIT); + SetFspMeasurePoint (FSP_PERF_ID_API_FSP_SILICON_INIT_ENTRY); + DEBUG ((DEBUG_INFO | DEBUG_INIT, "SiliconInitApi() - Begin\n")); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_SILICON_INIT | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); +} + +/** + This function handle NotifyPhase API call from the BootLoader. + It gives control back to the BootLoader after it is handled. If the + Notification code is a ReadyToBoot event, this function will return + and FSP continues the remaining execution until it reaches the DxeIpl. + +**/ +VOID +FspWaitForNotify ( + VOID + ) +{ + EFI_STATUS Status; + UINT32 NotificationValue; + UINT32 NotificationCount; + UINT8 Count; + + NotificationCount = 0; + while (NotificationCount < sizeof(mFspNotifySequence) / sizeof(UINT32)) { + + Count = (UINT8)((NotificationCount << 1) & 0x07); + SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_ENTRY + Count); + + if (NotificationCount == 0) { + SetPhaseStatusCode (FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); + } else if (NotificationCount == 1) { + SetPhaseStatusCode (FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); + } else if (NotificationCount == 2) { + SetPhaseStatusCode (FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION); + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_ENTRY); + } + + NotificationValue = ((NOTIFY_PHASE_PARAMS *)(UINTN)GetFspApiParameter ())->Phase; + DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - Begin [Phase: %08X]\n", NotificationValue)); + if (mFspNotifySequence[NotificationCount] != NotificationValue) { + // + // Notify code does not follow the predefined order + // + DEBUG ((DEBUG_INFO, "Unsupported FSP Notification Value\n")); + Status = EFI_UNSUPPORTED; + } else { + // + // Process Notification and Give control back to the boot loader framework caller + // + Status = FspNotificationHandler (NotificationValue); + if (!EFI_ERROR(Status)) { + NotificationCount++; + } + } + + SetFspApiReturnStatus(Status); + DEBUG ((DEBUG_INFO | DEBUG_INIT, "NotifyPhaseApi() - End [Status: 0x%08X]\n", Status)); + + SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_POST_PCI_EXIT + Count); + + if ((NotificationCount - 1) == 0) { + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_POST_PCIE_ENUM_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); + } else if ((NotificationCount - 1) == 1) { + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_READY_TO_BOOT_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); + } else if ((NotificationCount - 1) == 2) { + REPORT_STATUS_CODE (EFI_PROGRESS_CODE, FSP_STATUS_CODE_END_OF_FIRMWARE_NOTIFICATION | FSP_STATUS_CODE_COMMON_CODE | FSP_STATUS_CODE_API_EXIT); + } + Pei2LoaderSwitchStack(); + } + + // + // Control goes back to the PEI Core and it dispatches further PEIMs. + // DXEIPL is the final one to transfer control back to the boot loader. + // +} + diff --git a/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf b/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf new file mode 100644 index 0000000000..b3c673a0ac --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf @@ -0,0 +1,42 @@ +## @file +# Instance of BaseFspSwitchStackLib +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseFspSwitchStackLib + FILE_GUID = 68E79161-F7CE-4A61-8C72-F4DF6FF35CAA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FspSwitchStackLib + +[Sources.IA32] + FspSwitchStackLib.c + +[Sources.IA32] + Ia32/Stack.nasm + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec + +[LibraryClasses] + BaseLib + IoLib + +[FixedPcd] + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPatchEntry ## CONSUMES + gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxPerfEntry ## CONSUMES + + + diff --git a/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c b/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c new file mode 100644 index 0000000000..42a57a27c0 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/FspSwitchStackLib.c @@ -0,0 +1,42 @@ +/** @file + + Copyright (c) 2014, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include +#include + +/** + + Switch the current stack to the previous saved stack. + + @param[in] NewStack The new stack to be switched. + + @return OldStack After switching to the saved stack, + this value will be saved in eax before returning. + + +**/ +UINT32 +SwapStack ( + IN UINT32 NewStack + ) +{ + FSP_GLOBAL_DATA *FspData; + UINT32 OldStack; + + FspData = GetFspGlobalDataPointer (); + OldStack = FspData->CoreStack; + FspData->CoreStack = NewStack; + return OldStack; +} + diff --git a/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm b/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm new file mode 100644 index 0000000000..b0d843e9d3 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/BaseFspSwitchStackLib/Ia32/Stack.nasm @@ -0,0 +1,74 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2016, Intel Corporation. All rights reserved.
+; 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. +; +; Abstract: +; +; Switch the stack from temporary memory to permenent memory. +; +;------------------------------------------------------------------------------ + + SECTION .text + +extern ASM_PFX(SwapStack) + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; Pei2LoaderSwitchStack ( +; VOID +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(Pei2LoaderSwitchStack) +ASM_PFX(Pei2LoaderSwitchStack): + xor eax, eax + jmp ASM_PFX(FspSwitchStack) + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; Loader2PeiSwitchStack ( +; VOID +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(Loader2PeiSwitchStack) +ASM_PFX(Loader2PeiSwitchStack): + jmp ASM_PFX(FspSwitchStack) + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; FspSwitchStack ( +; VOID +; ) +;------------------------------------------------------------------------------ +global ASM_PFX(FspSwitchStack) +ASM_PFX(FspSwitchStack): + ; Save current contexts + push eax + pushfd + cli + pushad + sub esp, 8 + sidt [esp] + + ; Load new stack + push esp + call ASM_PFX(SwapStack) + mov esp, eax + + ; Restore previous contexts + lidt [esp] + add esp, 8 + popad + popfd + add esp, 4 + ret + diff --git a/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm new file mode 100644 index 0000000000..122eb9eb33 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/Flat32.nasm @@ -0,0 +1,127 @@ +;; @file +; This is the code that goes from real-mode to protected mode. +; It consumes the reset vector, configures the stack. +; +; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+; 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. +;; + +; +; Define assembler characteristics +; + +extern ASM_PFX(TempRamInitApi) + +SECTION .text + +%macro RET_ESI 0 + + movd esi, mm7 ; restore ESP from MM7 + jmp esi + +%endmacro + +; +; Perform early platform initialization +; +global ASM_PFX(SecPlatformInit) +ASM_PFX(SecPlatformInit): + + RET_ESI + +; +; Protected mode portion initializes stack, configures cache, and calls C entry point +; + +;---------------------------------------------------------------------------- +; +; Procedure: ProtectedModeEntryPoint +; +; Input: Executing in 32 Bit Protected (flat) mode +; cs: 0-4GB +; ds: 0-4GB +; es: 0-4GB +; fs: 0-4GB +; gs: 0-4GB +; ss: 0-4GB +; +; Output: This function never returns +; +; Destroys: +; ecx +; edi +; esi +; esp +; +; Description: +; Perform any essential early platform initilaisation +; Setup a stack +; +;---------------------------------------------------------------------------- +global ASM_PFX(ProtectedModeEntryPoint) +ASM_PFX(ProtectedModeEntryPoint): + ; + ; Dummy function. Consume 2 API to make sure they can be linked. + ; + mov eax, ASM_PFX(TempRamInitApi) + + ; Should never return + jmp $ + +; +; ROM-based Global-Descriptor Table for the PEI Phase +; +align 16 +global ASM_PFX(BootGdtTable) + +; +; GDT[0]: 0x00: Null entry, never used. +; +NULL_SEL equ $ - GDT_BASE ; Selector [0] +GDT_BASE: +ASM_PFX(BootGdtTable): DD 0 + DD 0 +; +; Linear code segment descriptor +; +LINEAR_CODE_SEL equ $ - GDT_BASE ; Selector [0x8] + DW 0FFFFh ; limit 0xFFFF + DW 0 ; base 0 + DB 0 + DB 09Bh ; present, ring 0, data, expand-up, not-writable + DB 0CFh ; page-granular, 32-bit + DB 0 +; +; System data segment descriptor +; +SYS_DATA_SEL equ $ - GDT_BASE ; Selector [0x10] + DW 0FFFFh ; limit 0xFFFF + DW 0 ; base 0 + DB 0 + DB 093h ; present, ring 0, data, expand-up, not-writable + DB 0CFh ; page-granular, 32-bit + DB 0 + +GDT_SIZE EQU $ - GDT_BASE ; Size, in bytes + +; +; GDT Descriptor +; +GdtDesc: ; GDT descriptor + DW GDT_SIZE - 1 ; GDT limit + DD GDT_BASE ; GDT base address + +global ASM_PFX(ProtectedModeEntryLinearAddress) +global ASM_PFX(ProtectedModeEntryLinearOffset) + +ASM_PFX(ProtectedModeEntryLinearAddress): +ASM_PFX(ProtectedModeEntryLinearOffset): + DD ASM_PFX(ProtectedModeEntryPoint) ; Offset of our 32 bit code + DW LINEAR_CODE_SEL + diff --git a/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm new file mode 100644 index 0000000000..df2233cf6f --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/Ia32/SecCarInit.nasm @@ -0,0 +1,46 @@ +;; @file +; SEC CAR function +; +; Copyright (c) 2015, Intel Corporation. All rights reserved.
+; 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. +;; + +; +; Define assembler characteristics +; + +%macro RET_ESI 0 + + movd esi, mm7 ; move ReturnAddress from MM7 to ESI + jmp esi + +%endmacro + +SECTION .text + +;----------------------------------------------------------------------------- +; +; Section: SecCarInit +; +; Description: This function initializes the Cache for Data, Stack, and Code +; +;----------------------------------------------------------------------------- +global ASM_PFX(SecCarInit) +ASM_PFX(SecCarInit): + + ; + ; Set up CAR + ; + + xor eax, eax + +SecCarInitExit: + + RET_ESI + diff --git a/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c new file mode 100644 index 0000000000..7bb95a9054 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/PlatformSecLibNull.c @@ -0,0 +1,33 @@ +/** @file + Null instance of Platform Sec Lib. + + Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+ 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. + +**/ + +#include +#include + +/** + This function check the signture of UPD. + + @param[in] ApiIdx Internal index of the FSP API. + @param[in] ApiParam Parameter of the FSP API. + +**/ +EFI_STATUS +EFIAPI +FspUpdSignatureCheck ( + IN UINT32 ApiIdx, + IN VOID *ApiParam + ) +{ + return EFI_SUCCESS; +} diff --git a/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf new file mode 100644 index 0000000000..e1cab05232 --- /dev/null +++ b/Core/IntelFsp2Pkg/Library/SecFspSecPlatformLibNull/SecFspSecPlatformLibNull.inf @@ -0,0 +1,56 @@ +## @file +# NULL instance of Platform Sec Lib. +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseFspSecPlatformLibNull + FILE_GUID = C128CADC-623E-4E41-97CB-A7138E627460 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + LIBRARY_CLASS = FspSecPlatformLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 +# + +################################################################################ +# +# Sources Section - list of files that are required for the build to succeed. +# +################################################################################ + +[Sources] + PlatformSecLibNull.c + +[Sources.IA32] + Ia32/Flat32.nasm + Ia32/SecCarInit.nasm + +################################################################################ +# +# Package Dependency Section - list of Package files that are required for +# this module. +# +################################################################################ + +[Packages] + MdePkg/MdePkg.dec + IntelFsp2Pkg/IntelFsp2Pkg.dec diff --git a/Core/IntelFsp2Pkg/License.txt b/Core/IntelFsp2Pkg/License.txt new file mode 100644 index 0000000000..87ae665edf --- /dev/null +++ b/Core/IntelFsp2Pkg/License.txt @@ -0,0 +1,25 @@ +Copyright (c) 2016, Intel Corporation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Core/IntelFsp2Pkg/Tools/GenCfgOpt.py b/Core/IntelFsp2Pkg/Tools/GenCfgOpt.py new file mode 100644 index 0000000000..e8cec95aa7 --- /dev/null +++ b/Core/IntelFsp2Pkg/Tools/GenCfgOpt.py @@ -0,0 +1,1467 @@ +## @ GenCfgOpt.py +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that 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. +# +## + +import os +import re +import sys +import struct +from datetime import date + +# Generated file copyright header + +__copyright_txt__ = """## @file +# +# THIS IS AUTO-GENERATED FILE BY BUILD TOOLS AND PLEASE DO NOT MAKE MODIFICATION. +# +# This file lists all VPD informations for a platform collected by build.exe. +# +# Copyright (c) %4d, Intel Corporation. All rights reserved.
+# 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. +# +""" + +__copyright_bsf__ = """/** @file + + Boot Setting File for Platform Configuration. + + Copyright (c) %4d, Intel Corporation. All rights reserved.
+ 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. + + This file is automatically generated. Please do NOT modify !!! + +**/ + +""" + +__copyright_h__ = """/** @file + +Copyright (c) %4d, Intel Corporation. All rights reserved.
+ +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. +* Neither the name of Intel Corporation nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + + This file is automatically generated. Please do NOT modify !!! + +**/ +""" + +class CLogicalExpression: + def __init__(self): + self.index = 0 + self.string = '' + + def errExit(self, err = ''): + print "ERROR: Express parsing for:" + print " %s" % self.string + print " %s^" % (' ' * self.index) + if err: + print "INFO : %s" % err + raise SystemExit + + def getNonNumber (self, n1, n2): + if not n1.isdigit(): + return n1 + if not n2.isdigit(): + return n2 + return None + + def getCurr(self, lens = 1): + try: + if lens == -1: + return self.string[self.index :] + else: + if self.index + lens > len(self.string): + lens = len(self.string) - self.index + return self.string[self.index : self.index + lens] + except Exception: + return '' + + def isLast(self): + return self.index == len(self.string) + + def moveNext(self, len = 1): + self.index += len + + def skipSpace(self): + while not self.isLast(): + if self.getCurr() in ' \t': + self.moveNext() + else: + return + + def normNumber (self, val): + return True if val else False + + def getNumber(self, var): + var = var.strip() + if re.match('^0x[a-fA-F0-9]+$', var): + value = int(var, 16) + elif re.match('^[+-]?\d+$', var): + value = int(var, 10) + else: + value = None + return value + + def parseValue(self): + self.skipSpace() + var = '' + while not self.isLast(): + char = self.getCurr() + if re.match('^[\w.]', char): + var += char + self.moveNext() + else: + break + val = self.getNumber(var) + if val is None: + value = var + else: + value = "%d" % val + return value + + def parseSingleOp(self): + self.skipSpace() + if re.match('^NOT\W', self.getCurr(-1)): + self.moveNext(3) + op = self.parseBrace() + val = self.getNumber (op) + if val is None: + self.errExit ("'%s' is not a number" % op) + return "%d" % (not self.normNumber(int(op))) + else: + return self.parseValue() + + def parseBrace(self): + self.skipSpace() + char = self.getCurr() + if char == '(': + self.moveNext() + value = self.parseExpr() + self.skipSpace() + if self.getCurr() != ')': + self.errExit ("Expecting closing brace or operator") + self.moveNext() + return value + else: + value = self.parseSingleOp() + return value + + def parseCompare(self): + value = self.parseBrace() + while True: + self.skipSpace() + char = self.getCurr() + if char in ['<', '>']: + self.moveNext() + next = self.getCurr() + if next == '=': + op = char + next + self.moveNext() + else: + op = char + result = self.parseBrace() + test = self.getNonNumber(result, value) + if test is None: + value = "%d" % self.normNumber(eval (value + op + result)) + else: + self.errExit ("'%s' is not a valid number for comparision" % test) + elif char in ['=', '!']: + op = self.getCurr(2) + if op in ['==', '!=']: + self.moveNext(2) + result = self.parseBrace() + test = self.getNonNumber(result, value) + if test is None: + value = "%d" % self.normNumber((eval (value + op + result))) + else: + value = "%d" % self.normNumber(eval ("'" + value + "'" + op + "'" + result + "'")) + else: + break + else: + break + return value + + def parseAnd(self): + value = self.parseCompare() + while True: + self.skipSpace() + if re.match('^AND\W', self.getCurr(-1)): + self.moveNext(3) + result = self.parseCompare() + test = self.getNonNumber(result, value) + if test is None: + value = "%d" % self.normNumber(int(value) & int(result)) + else: + self.errExit ("'%s' is not a valid op number for AND" % test) + else: + break + return value + + def parseOrXor(self): + value = self.parseAnd() + op = None + while True: + self.skipSpace() + op = None + if re.match('^XOR\W', self.getCurr(-1)): + self.moveNext(3) + op = '^' + elif re.match('^OR\W', self.getCurr(-1)): + self.moveNext(2) + op = '|' + else: + break + if op: + result = self.parseAnd() + test = self.getNonNumber(result, value) + if test is None: + value = "%d" % self.normNumber(eval (value + op + result)) + else: + self.errExit ("'%s' is not a valid op number for XOR/OR" % test) + return value + + def parseExpr(self): + return self.parseOrXor() + + def getResult(self): + value = self.parseExpr() + self.skipSpace() + if not self.isLast(): + self.errExit ("Unexpected character found '%s'" % self.getCurr()) + test = self.getNumber(value) + if test is None: + self.errExit ("Result '%s' is not a number" % value) + return int(value) + + def evaluateExpress (self, Expr): + self.index = 0 + self.string = Expr + if self.getResult(): + Result = True + else: + Result = False + return Result + +class CGenCfgOpt: + def __init__(self): + self.Debug = False + self.Error = '' + self.ReleaseMode = True + + self._GlobalDataDef = """ +GlobalDataDef + SKUID = 0, "DEFAULT" +EndGlobalData + +""" + self._BuidinOptionTxt = """ +List &EN_DIS + Selection 0x1 , "Enabled" + Selection 0x0 , "Disabled" +EndList + +""" + + self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER'] + self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT'] + self._BuidinOption = {'$EN_DIS' : 'EN_DIS'} + + self._MacroDict = {} + self._PcdsDict = {} + self._CfgBlkDict = {} + self._CfgPageDict = {} + self._CfgItemList = [] + self._DscFile = '' + self._FvDir = '' + self._MapVer = 0 + + def ParseBuildMode (self, OutputStr): + if "RELEASE_" in OutputStr: + self.ReleaseMode = True + if "DEBUG_" in OutputStr: + self.ReleaseMode = False + return + + def ParseMacros (self, MacroDefStr): + # ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build'] + self._MacroDict = {} + IsExpression = False + for Macro in MacroDefStr: + if Macro.startswith('-D'): + IsExpression = True + if len(Macro) > 2: + Macro = Macro[2:] + else : + continue + if IsExpression: + IsExpression = False + Match = re.match("(\w+)=(.+)", Macro) + if Match: + self._MacroDict[Match.group(1)] = Match.group(2) + else: + Match = re.match("(\w+)", Macro) + if Match: + self._MacroDict[Match.group(1)] = '' + if len(self._MacroDict) == 0: + Error = 1 + else: + Error = 0 + if self.Debug: + print "INFO : Macro dictionary:" + for Each in self._MacroDict: + print " $(%s) = [ %s ]" % (Each , self._MacroDict[Each]) + return Error + + def EvaulateIfdef (self, Macro): + Result = Macro in self._MacroDict + if self.Debug: + print "INFO : Eval Ifdef [%s] : %s" % (Macro, Result) + return Result + + def ExpandMacros (self, Input): + Line = Input + Match = re.findall("\$\(\w+\)", Input) + if Match: + for Each in Match: + Variable = Each[2:-1] + if Variable in self._MacroDict: + Line = Line.replace(Each, self._MacroDict[Variable]) + else: + if self.Debug: + print "WARN : %s is not defined" % Each + Line = Line.replace(Each, Each[2:-1]) + return Line + + def ExpandPcds (self, Input): + Line = Input + Match = re.findall("(\w+\.\w+)", Input) + if Match: + for PcdName in Match: + if PcdName in self._PcdsDict: + Line = Line.replace(PcdName, self._PcdsDict[PcdName]) + else: + if self.Debug: + print "WARN : %s is not defined" % PcdName + return Line + + def EvaluateExpress (self, Expr): + ExpExpr = self.ExpandPcds(Expr) + ExpExpr = self.ExpandMacros(ExpExpr) + LogExpr = CLogicalExpression() + Result = LogExpr.evaluateExpress (ExpExpr) + if self.Debug: + print "INFO : Eval Express [%s] : %s" % (Expr, Result) + return Result + + def FormatListValue(self, ConfigDict): + Struct = ConfigDict['struct'] + if Struct not in ['UINT8','UINT16','UINT32','UINT64']: + return + + dataarray = [] + binlist = ConfigDict['value'][1:-1].split(',') + for each in binlist: + each = each.strip() + if each.startswith('0x'): + value = int(each, 16) + else: + value = int(each) + dataarray.append(value) + + unit = int(Struct[4:]) / 8 + if int(ConfigDict['length']) != unit * len(dataarray): + raise Exception("Array size is not proper for '%s' !" % ConfigDict['cname']) + + bytearray = [] + for each in dataarray: + value = each + for loop in xrange(unit): + bytearray.append("0x%02X" % (value & 0xFF)) + value = value >> 8 + newvalue = '{' + ','.join(bytearray) + '}' + ConfigDict['value'] = newvalue + return "" + + def ParseDscFile (self, DscFile, FvDir): + self._CfgItemList = [] + self._CfgPageDict = {} + self._CfgBlkDict = {} + self._DscFile = DscFile + self._FvDir = FvDir + + IsDefSect = False + IsPcdSect = False + IsUpdSect = False + IsVpdSect = False + + IfStack = [] + ElifStack = [] + Error = 0 + ConfigDict = {} + + DscFd = open(DscFile, "r") + DscLines = DscFd.readlines() + DscFd.close() + + while len(DscLines): + DscLine = DscLines.pop(0).strip() + Handle = False + Match = re.match("^\[(.+)\]", DscLine) + if Match is not None: + IsDefSect = False + IsPcdSect = False + IsVpdSect = False + IsUpdSect = False + if Match.group(1).lower() == "Defines".lower(): + IsDefSect = True + if Match.group(1).lower() == "PcdsFeatureFlag".lower(): + IsPcdSect = True + elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower(): + ConfigDict = {} + ConfigDict['header'] = 'ON' + ConfigDict['region'] = 'UPD' + ConfigDict['order'] = -1 + ConfigDict['page'] = '' + ConfigDict['name'] = '' + ConfigDict['find'] = '' + ConfigDict['struct'] = '' + ConfigDict['embed'] = '' + ConfigDict['comment'] = '' + ConfigDict['subreg'] = [] + IsUpdSect = True + else: + if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect: + if re.match("^!else($|\s+#.+)", DscLine): + if IfStack: + IfStack[-1] = not IfStack[-1] + else: + print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine) + raise SystemExit + elif re.match("^!endif($|\s+#.+)", DscLine): + if IfStack: + IfStack.pop() + Level = ElifStack.pop() + if Level > 0: + del IfStack[-Level:] + else: + print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine) + raise SystemExit + else: + Result = False + Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine) + if Match: + Result = self.EvaulateIfdef (Match.group(2)) + if Match.group(1) == 'ifndef': + Result = not Result + IfStack.append(Result) + ElifStack.append(0) + else: + Match = re.match("!(if|elseif)\s+(.+)", DscLine) + if Match: + Result = self.EvaluateExpress(Match.group(2)) + if Match.group(1) == "if": + ElifStack.append(0) + IfStack.append(Result) + else: #elseif + if IfStack: + IfStack[-1] = not IfStack[-1] + IfStack.append(Result) + ElifStack[-1] = ElifStack[-1] + 1 + else: + print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine) + raise SystemExit + else: + if IfStack: + Handle = reduce(lambda x,y: x and y, IfStack) + else: + Handle = True + if Handle: + Match = re.match("!include\s+(.+)", DscLine) + if Match: + IncludeFilePath = Match.group(1) + IncludeFilePath = self.ExpandMacros(IncludeFilePath) + try: + IncludeDsc = open(IncludeFilePath, "r") + except: + print("ERROR: Cannot open file '%s'" % IncludeFilePath) + raise SystemExit + NewDscLines = IncludeDsc.readlines() + IncludeDsc.close() + DscLines = NewDscLines + DscLines + else: + if DscLine.startswith('!'): + print("ERROR: Unrecoginized directive for line '%s'" % DscLine) + raise SystemExit + if not Handle: + continue + + if IsDefSect: + #DEFINE UPD_TOOL_GUID = 8C3D856A-9BE6-468E-850A-24F7A8D38E09 + #DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6 + #DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385 + #DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F + Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine) + if Match: + self._MacroDict[Match.group(1)] = Match.group(2) + if self.Debug: + print "INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2)) + elif IsPcdSect: + #gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE + #gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE + Match = re.match("^\s*([\w\.]+)\s*\|\s*(\w+)", DscLine) + if Match: + self._PcdsDict[Match.group(1)] = Match.group(2) + if self.Debug: + print "INFO : PCD %s = [ %s ]" % (Match.group(1), Match.group(2)) + else: + Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine) + if Match: + Remaining = Match.group(2) + if Match.group(1) == '!BSF' or Match.group(1) == '@Bsf': + Match = re.match("(?:^|.+\s+)PAGES:{(.+?)}", Remaining) + if Match: + # !BSF PAGES:{HSW:"Haswell System Agent", LPT:"Lynx Point PCH"} + PageList = Match.group(1).split(',') + for Page in PageList: + Page = Page.strip() + Match = re.match("(\w+):\"(.+)\"", Page) + self._CfgPageDict[Match.group(1)] = Match.group(2) + + Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining) + if Match: + self._CfgBlkDict['name'] = Match.group(1) + self._CfgBlkDict['ver'] = Match.group(2) + + for Key in self._BsfKeyList: + Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining) + if Match: + if Key in ['NAME', 'HELP', 'OPTION'] and Match.group(1).startswith('+'): + ConfigDict[Key.lower()] += Match.group(1)[1:] + else: + ConfigDict[Key.lower()] = Match.group(1) + else: + for Key in self._HdrKeyList: + Match = re.match("(?:^|.+\s+)%s:{(.+?)}" % Key, Remaining) + if Match: + ConfigDict[Key.lower()] = Match.group(1) + + Match = re.match("^\s*#\s+@Prompt\s+(.+)", DscLine) + if Match: + ConfigDict['name'] = Match.group(1) + + Match = re.match("^\s*#\s*@ValidList\s*(.+)\s*\|\s*(.+)\s*\|\s*(.+)\s*", DscLine) + if Match: + if Match.group(2).strip() in self._BuidinOption: + ConfigDict['option'] = Match.group(2).strip() + else: + OptionValueList = Match.group(2).split(',') + OptionStringList = Match.group(3).split(',') + Index = 0 + for Option in OptionValueList: + Option = Option.strip() + ConfigDict['option'] = ConfigDict['option'] + str(Option) + ':' + OptionStringList[Index].strip() + Index += 1 + if Index in range(len(OptionValueList)): + ConfigDict['option'] += ', ' + ConfigDict['type'] = "Combo" + + Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine) + if Match: + if "0x" in Match.group(2) or "0x" in Match.group(3): + ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3)) + else: + ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3)) + + Match = re.match("^\s*##\s+(.+)", DscLine) + if Match: + ConfigDict['help'] = Match.group(1) + + # Check VPD/UPD + if IsUpdSect: + Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)\s*\|\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)",DscLine) + else: + Match = re.match("^([_a-zA-Z0-9]+).([_a-zA-Z0-9]+)\s*\|\s*(0x[0-9A-F]+)(?:\s*\|\s*(.+))?", DscLine) + if Match: + ConfigDict['space'] = Match.group(1) + ConfigDict['cname'] = Match.group(2) + ConfigDict['offset'] = int (Match.group(3), 16) + if ConfigDict['order'] == -1: + ConfigDict['order'] = ConfigDict['offset'] << 8 + else: + (Major, Minor) = ConfigDict['order'].split('.') + ConfigDict['order'] = (int (Major, 16) << 8 ) + int (Minor, 16) + if IsUpdSect: + Value = Match.group(5).strip() + if Match.group(4).startswith("0x"): + Length = int (Match.group(4), 16) + else : + Length = int (Match.group(4)) + else: + Value = Match.group(4) + if Value is None: + Value = '' + Value = Value.strip() + if '|' in Value: + Match = re.match("^.+\s*\|\s*(.+)", Value) + if Match: + Value = Match.group(1) + Length = -1 + + ConfigDict['length'] = Length + Match = re.match("\$\((\w+)\)", Value) + if Match: + if Match.group(1) in self._MacroDict: + Value = self._MacroDict[Match.group(1)] + + ConfigDict['value'] = Value + if (len(Value) > 0) and (Value[0] == '{'): + Value = self.FormatListValue(ConfigDict) + + if ConfigDict['name'] == '': + # Clear BSF specific items + ConfigDict['bsfname'] = '' + ConfigDict['help'] = '' + ConfigDict['type'] = '' + ConfigDict['option'] = '' + + self._CfgItemList.append(ConfigDict.copy()) + ConfigDict['name'] = '' + ConfigDict['find'] = '' + ConfigDict['struct'] = '' + ConfigDict['embed'] = '' + ConfigDict['comment'] = '' + ConfigDict['order'] = -1 + ConfigDict['subreg'] = [] + ConfigDict['option'] = '' + else: + # It could be a virtual item as below + # !BSF FIELD:{SerialDebugPortAddress0:1} + # or + # @Bsf FIELD:{SerialDebugPortAddress0:1b} + Match = re.match("^\s*#\s+(!BSF|@Bsf)\s+FIELD:{(.+):(\d+)([Bb])?}", DscLine) + if Match: + SubCfgDict = ConfigDict.copy() + if (Match.group(4) == None) or (Match.group(4) == 'B'): + UnitBitLen = 8 + elif Match.group(4) == 'b': + UnitBitLen = 1 + else: + print("ERROR: Invalide BSF FIELD length for line '%s'" % DscLine) + raise SystemExit + SubCfgDict['cname'] = Match.group(2) + SubCfgDict['bitlength'] = int (Match.group(3)) * UnitBitLen + if SubCfgDict['bitlength'] > 0: + LastItem = self._CfgItemList[-1] + if len(LastItem['subreg']) == 0: + SubOffset = 0 + else: + SubOffset = LastItem['subreg'][-1]['bitoffset'] + LastItem['subreg'][-1]['bitlength'] + SubCfgDict['bitoffset'] = SubOffset + LastItem['subreg'].append (SubCfgDict.copy()) + ConfigDict['name'] = '' + return Error + + def GetBsfBitFields (self, subitem, bytes): + start = subitem['bitoffset'] + end = start + subitem['bitlength'] + bitsvalue = ''.join('{0:08b}'.format(i) for i in bytes[::-1]) + bitsvalue = bitsvalue[::-1] + bitslen = len(bitsvalue) + if start > bitslen or end > bitslen: + print "Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name']) + raise SystemExit + return hex(int(bitsvalue[start:end][::-1], 2)) + + def UpdateSubRegionDefaultValue (self): + Error = 0 + for Item in self._CfgItemList: + if len(Item['subreg']) == 0: + continue + bytearray = [] + if Item['value'][0] == '{': + binlist = Item['value'][1:-1].split(',') + for each in binlist: + each = each.strip() + if each.startswith('0x'): + value = int(each, 16) + else: + value = int(each) + bytearray.append(value) + else: + if Item['value'].startswith('0x'): + value = int(Item['value'], 16) + else: + value = int(Item['value']) + idx = 0 + while idx < Item['length']: + bytearray.append(value & 0xFF) + value = value >> 8 + idx = idx + 1 + for SubItem in Item['subreg']: + valuestr = self.GetBsfBitFields(SubItem, bytearray) + SubItem['value'] = valuestr + return Error + + def CreateSplitUpdTxt (self, UpdTxtFile): + GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID'] + SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS + for Index in range(len(GuidList)): + UpdTxtFile = '' + FvDir = self._FvDir + if GuidList[Index] not in self._MacroDict: + self.Error = "%s definition is missing in DSC file" % (GuidList[Index]) + return 1 + + if UpdTxtFile == '': + UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt') + + ReCreate = False + if not os.path.exists(UpdTxtFile): + ReCreate = True + else: + DscTime = os.path.getmtime(self._DscFile) + TxtTime = os.path.getmtime(UpdTxtFile) + if DscTime > TxtTime: + ReCreate = True + + if not ReCreate: + # DSC has not been modified yet + # So don't have to re-generate other files + self.Error = 'No DSC file change, skip to create UPD TXT file' + return 256 + + TxtFd = open(UpdTxtFile, "w") + TxtFd.write("%s\n" % (__copyright_txt__ % date.today().year)) + + NextOffset = 0 + SpaceIdx = 0 + StartAddr = 0 + EndAddr = 0 + Default = 'DEFAULT|' + InRange = False + for Item in self._CfgItemList: + if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]: + StartAddr = Item['offset'] + NextOffset = StartAddr + InRange = True + if Item['cname'] == 'UpdTerminator' and InRange == True: + EndAddr = Item['offset'] + InRange = False + InRange = False + for Item in self._CfgItemList: + if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == SignatureList[Index]: + InRange = True + if InRange != True: + continue + if Item['cname'] == 'UpdTerminator': + InRange = False + if Item['region'] != 'UPD': + continue + Offset = Item['offset'] + if StartAddr > Offset or EndAddr < Offset: + continue + if NextOffset < Offset: + # insert one line + TxtFd.write("%s.UnusedUpdSpace%d|%s0x%04X|0x%04X|{0}\n" % (Item['space'], SpaceIdx, Default, NextOffset - StartAddr, Offset - NextOffset)) + SpaceIdx = SpaceIdx + 1 + NextOffset = Offset + Item['length'] + if Item['cname'] == 'PcdSerialIoUartDebugEnable': + if self.ReleaseMode == False: + Item['value'] = 0x01 + TxtFd.write("%s.%s|%s0x%04X|%s|%s\n" % (Item['space'],Item['cname'],Default,Item['offset'] - StartAddr,Item['length'],Item['value'])) + TxtFd.close() + return 0 + + def ProcessMultilines (self, String, MaxCharLength): + Multilines = '' + StringLength = len(String) + CurrentStringStart = 0 + StringOffset = 0 + BreakLineDict = [] + if len(String) <= MaxCharLength: + while (StringOffset < StringLength): + if StringOffset >= 1: + if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n': + BreakLineDict.append (StringOffset + 1) + StringOffset += 1 + if BreakLineDict != []: + for Each in BreakLineDict: + Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip() + CurrentStringStart = Each + if StringLength - CurrentStringStart > 0: + Multilines += " %s\n" % String[CurrentStringStart:].lstrip() + else: + Multilines = " %s\n" % String + else: + NewLineStart = 0 + NewLineCount = 0 + FoundSpaceChar = False + while (StringOffset < StringLength): + if StringOffset >= 1: + if NewLineCount >= MaxCharLength - 1: + if String[StringOffset] == ' ' and StringLength - StringOffset > 10: + BreakLineDict.append (NewLineStart + NewLineCount) + NewLineStart = NewLineStart + NewLineCount + NewLineCount = 0 + FoundSpaceChar = True + elif StringOffset == StringLength - 1 and FoundSpaceChar == False: + BreakLineDict.append (0) + if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n': + BreakLineDict.append (StringOffset + 1) + NewLineStart = StringOffset + 1 + NewLineCount = 0 + StringOffset += 1 + NewLineCount += 1 + if BreakLineDict != []: + BreakLineDict.sort () + for Each in BreakLineDict: + if Each > 0: + Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip() + CurrentStringStart = Each + if StringLength - CurrentStringStart > 0: + Multilines += " %s\n" % String[CurrentStringStart:].lstrip() + return Multilines + + def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option): + PosName = 28 + PosComment = 30 + NameLine='' + HelpLine='' + OptionLine='' + + IsArray = False + if Length in [1,2,4,8]: + Type = "UINT%d" % (Length * 8) + else: + IsArray = True + Type = "UINT8" + + if Item and Item['value'].startswith('{'): + Type = "UINT8" + IsArray = True + + if Struct != '': + Type = Struct + if Struct in ['UINT8','UINT16','UINT32','UINT64']: + IsArray = True + Unit = int(Type[4:]) / 8 + Length = Length / Unit + else: + IsArray = False + + if IsArray: + Name = Name + '[%d]' % Length + + if len(Type) < PosName: + Space1 = PosName - len(Type) + else: + Space1 = 1 + + if BsfName != '': + NameLine=" - %s\n" % BsfName + else: + NameLine="\n" + + if Help != '': + HelpLine = self.ProcessMultilines (Help, 80) + + if Option != '': + OptionLine = self.ProcessMultilines (Option, 80) + + if Offset is None: + OffsetStr = '????' + else: + OffsetStr = '0x%04X' % Offset + + return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,) + + def PostProcessBody (self, TextBody): + NewTextBody = [] + OldTextBody = [] + IncludeLine = False + StructName = '' + VariableName = '' + IsUpdHdrDefined = False + IsUpdHeader = False + for Line in TextBody: + SplitToLines = Line.splitlines() + MatchComment = re.match("^/\*\sCOMMENT:(\w+):([\w|\W|\s]+)\s\*/\s([\s\S]*)", SplitToLines[0]) + if MatchComment: + if MatchComment.group(1) == 'FSP_UPD_HEADER': + IsUpdHeader = True + else: + IsUpdHeader = False + if IsUpdHdrDefined != True or IsUpdHeader != True: + CommentLine = " " + MatchComment.group(2) + "\n" + NewTextBody.append("/**" + CommentLine + "**/\n") + Line = Line[(len(SplitToLines[0]) + 1):] + + Match = re.match("^/\*\sEMBED_STRUCT:(\w+):(\w+):(START|END)\s\*/\s([\s\S]*)", Line) + if Match: + Line = Match.group(4) + if Match.group(1) == 'FSP_UPD_HEADER': + IsUpdHeader = True + else: + IsUpdHeader = False + + if Match and Match.group(3) == 'START': + if IsUpdHdrDefined != True or IsUpdHeader != True: + NewTextBody.append ('typedef struct {\n') + StructName = Match.group(1) + VariableName = Match.group(2) + MatchOffset = re.search('/\*\*\sOffset\s0x([a-fA-F0-9]+)', Line) + if MatchOffset: + Offset = int(MatchOffset.group(1), 16) + else: + Offset = None + Line + IncludeLine = True + OldTextBody.append (self.CreateField (None, VariableName, 0, Offset, StructName, '', '', '')) + if IncludeLine: + if IsUpdHdrDefined != True or IsUpdHeader != True: + NewTextBody.append (Line) + else: + OldTextBody.append (Line) + + if Match and Match.group(3) == 'END': + if (StructName != Match.group(1)) or (VariableName != Match.group(2)): + print "Unmatched struct name '%s' and '%s' !" % (StructName, Match.group(1)) + else: + if IsUpdHdrDefined != True or IsUpdHeader != True: + NewTextBody.append ('} %s;\n\n' % StructName) + IsUpdHdrDefined = True + IncludeLine = False + NewTextBody.extend(OldTextBody) + return NewTextBody + + def CreateHeaderFile (self, InputHeaderFile): + FvDir = self._FvDir + + HeaderFileName = 'FspUpd.h' + HeaderFile = os.path.join(FvDir, HeaderFileName) + + # Check if header needs to be recreated + ReCreate = False + + TxtBody = [] + for Item in self._CfgItemList: + if str(Item['cname']) == 'Signature' and Item['length'] == 8: + Value = int(Item['value'], 16) + Chars = [] + while Value != 0x0: + Chars.append(chr(Value & 0xFF)) + Value = Value >> 8 + SignatureStr = ''.join(Chars) + # Signature will be _T / _M / _S for FSPT / FSPM / FSPS accordingly + if '_T' in SignatureStr[6:6+2]: + TxtBody.append("#define FSPT_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr)) + elif '_M' in SignatureStr[6:6+2]: + TxtBody.append("#define FSPM_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr)) + elif '_S' in SignatureStr[6:6+2]: + TxtBody.append("#define FSPS_UPD_SIGNATURE %s /* '%s' */\n\n" % (Item['value'], SignatureStr)) + TxtBody.append("\n") + + for Region in ['UPD']: + UpdOffsetTable = [] + UpdSignature = ['0x545F', '0x4D5F', '0x535F'] #['_T', '_M', '_S'] signature for FSPT, FSPM, FSPS + UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD'] + for Item in self._CfgItemList: + if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature: + UpdOffsetTable.append (Item["offset"]) + + for UpdIdx in range(len(UpdOffsetTable)): + CommentLine = "" + for Item in self._CfgItemList: + if Item["comment"] != '' and Item["offset"] >= UpdOffsetTable[UpdIdx]: + MatchComment = re.match("^(U|V)PD_DATA_REGION:([\w|\W|\s]+)", Item["comment"]) + if MatchComment and MatchComment.group(1) == Region[0]: + CommentLine = " " + MatchComment.group(2) + "\n" + TxtBody.append("/**" + CommentLine + "**/\n") + elif Item["offset"] >= UpdOffsetTable[UpdIdx] and Item["comment"] == '': + Match = re.match("^FSP([\w|\W|\s])_UPD", UpdStructure[UpdIdx]) + if Match: + TxtBody.append("/** Fsp " + Match.group(1) + " UPD Configuration\n**/\n") + TxtBody.append("typedef struct {\n") + NextOffset = 0 + SpaceIdx = 0 + Offset = 0 + + LastVisible = True + ResvOffset = 0 + ResvIdx = 0 + LineBuffer = [] + InRange = False + for Item in self._CfgItemList: + if Item['cname'] == 'Signature' and str(Item['value'])[0:6] == UpdSignature[UpdIdx] or Region[0] == 'V': + InRange = True + if InRange != True: + continue + if Item['cname'] == 'UpdTerminator': + InRange = False + + if Item['region'] != Region: + continue + + if Item["offset"] < UpdOffsetTable[UpdIdx]: + continue + + NextVisible = LastVisible + + if LastVisible and (Item['header'] == 'OFF'): + NextVisible = False + ResvOffset = Item['offset'] + elif (not LastVisible) and Item['header'] == 'ON': + NextVisible = True + Name = "Reserved" + Region[0] + "pdSpace%d" % ResvIdx + ResvIdx = ResvIdx + 1 + TxtBody.append(self.CreateField (Item, Name, Item["offset"] - ResvOffset, ResvOffset, '', '', '', '')) + + if Offset < Item["offset"]: + if LastVisible: + Name = "Unused" + Region[0] + "pdSpace%d" % SpaceIdx + LineBuffer.append(self.CreateField (Item, Name, Item["offset"] - Offset, Offset, '', '', '', '')) + SpaceIdx = SpaceIdx + 1 + Offset = Item["offset"] + + LastVisible = NextVisible + + Offset = Offset + Item["length"] + if LastVisible: + for Each in LineBuffer: + TxtBody.append (Each) + LineBuffer = [] + Comment = Item["comment"] + Embed = Item["embed"].upper() + if Embed.endswith(':START') or Embed.endswith(':END'): + if not Comment == '' and Embed.endswith(':START'): + Marker = '/* COMMENT:%s */ \n' % Item["comment"] + Marker = Marker + '/* EMBED_STRUCT:%s */ ' % Item["embed"] + else: + Marker = '/* EMBED_STRUCT:%s */ ' % Item["embed"] + else: + if Embed == '': + Marker = '' + else: + self.Error = "Invalid embedded structure format '%s'!\n" % Item["embed"] + return 4 + Line = Marker + self.CreateField (Item, Item["cname"], Item["length"], Item["offset"], Item['struct'], Item['name'], Item['help'], Item['option']) + TxtBody.append(Line) + if Item['cname'] == 'UpdTerminator': + break + TxtBody.append("} " + UpdStructure[UpdIdx] + ";\n\n") + + # Handle the embedded data structure + TxtBody = self.PostProcessBody (TxtBody) + + HeaderTFileName = 'FsptUpd.h' + HeaderMFileName = 'FspmUpd.h' + HeaderSFileName = 'FspsUpd.h' + + UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION + UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG + UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE'] + ExcludedSpecificUpd = 'FSPM_ARCH_UPD' + + if InputHeaderFile != '': + if not os.path.exists(InputHeaderFile): + self.Error = "Input header file '%s' does not exist" % InputHeaderFile + return 6 + + InFd = open(InputHeaderFile, "r") + IncLines = InFd.readlines() + InFd.close() + + for item in range(len(UpdRegionCheck)): + if UpdRegionCheck[item] == 'FSPT': + HeaderFd = open(os.path.join(FvDir, HeaderTFileName), "w") + FileBase = os.path.basename(os.path.join(FvDir, HeaderTFileName)) + elif UpdRegionCheck[item] == 'FSPM': + HeaderFd = open(os.path.join(FvDir, HeaderMFileName), "w") + FileBase = os.path.basename(os.path.join(FvDir, HeaderMFileName)) + elif UpdRegionCheck[item] == 'FSPS': + HeaderFd = open(os.path.join(FvDir, HeaderSFileName), "w") + FileBase = os.path.basename(os.path.join(FvDir, HeaderSFileName)) + FileName = FileBase.replace(".", "_").upper() + HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year)) + HeaderFd.write("#ifndef __%s__\n" % FileName) + HeaderFd.write("#define __%s__\n\n" % FileName) + HeaderFd.write("#include <%s>\n\n" % HeaderFileName) + HeaderFd.write("#pragma pack(push, 1)\n\n") + + Export = False + for Line in IncLines: + Match = re.search ("!EXPORT\s+([A-Z]+)\s+EXTERNAL_BOOTLOADER_STRUCT_(BEGIN|END)\s+", Line) + if Match: + if Match.group(2) == "BEGIN" and Match.group(1) == UpdRegionCheck[item]: + Export = True + continue + else: + Export = False + continue + if Export: + HeaderFd.write(Line) + HeaderFd.write("\n") + + Index = 0 + StartIndex = 0 + EndIndex = 0 + StructStart = [] + StructStartWithComment = [] + StructEnd = [] + for Line in TxtBody: + Index += 1 + Match = re.match("(typedef struct {)", Line) + if Match: + StartIndex = Index - 1 + Match = re.match("}\s([_A-Z0-9]+);", Line) + if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)): + EndIndex = Index + StructStart.append(StartIndex) + StructEnd.append(EndIndex) + Index = 0 + for Line in TxtBody: + Index += 1 + for Item in range(len(StructStart)): + if Index == StructStart[Item]: + Match = re.match("^(/\*\*\s*)", Line) + if Match: + StructStartWithComment.append(StructStart[Item]) + else: + StructStartWithComment.append(StructStart[Item] + 1) + Index = 0 + for Line in TxtBody: + Index += 1 + for Item in range(len(StructStart)): + if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]: + HeaderFd.write (Line) + HeaderFd.write("#pragma pack(pop)\n\n") + HeaderFd.write("#endif\n") + HeaderFd.close() + + HeaderFd = open(HeaderFile, "w") + FileBase = os.path.basename(HeaderFile) + FileName = FileBase.replace(".", "_").upper() + HeaderFd.write("%s\n" % (__copyright_h__ % date.today().year)) + HeaderFd.write("#ifndef __%s__\n" % FileName) + HeaderFd.write("#define __%s__\n\n" % FileName) + HeaderFd.write("#include \n\n") + HeaderFd.write("#pragma pack(push, 1)\n\n") + + for item in range(len(UpdRegionCheck)): + Index = 0 + StartIndex = 0 + EndIndex = 0 + StructStart = [] + StructStartWithComment = [] + StructEnd = [] + for Line in TxtBody: + Index += 1 + Match = re.match("(typedef struct {)", Line) + if Match: + StartIndex = Index - 1 + Match = re.match("#define\s([_A-Z0-9]+)\s*", Line) + if Match and (UpdSignatureCheck[item] in Match.group(1) or UpdSignatureCheck[item] in Match.group(1)): + StructStart.append(Index - 1) + StructEnd.append(Index) + Index = 0 + for Line in TxtBody: + Index += 1 + for Item in range(len(StructStart)): + if Index == StructStart[Item]: + Match = re.match("^(/\*\*\s*)", Line) + if Match: + StructStartWithComment.append(StructStart[Item]) + else: + StructStartWithComment.append(StructStart[Item] + 1) + Index = 0 + for Line in TxtBody: + Index += 1 + for Item in range(len(StructStart)): + if Index >= StructStartWithComment[Item] and Index <= StructEnd[Item]: + HeaderFd.write (Line) + HeaderFd.write("#pragma pack(pop)\n\n") + HeaderFd.write("#endif\n") + HeaderFd.close() + + return 0 + + def WriteBsfStruct (self, BsfFd, Item): + if Item['type'] == "None": + Space = "gPlatformFspPkgTokenSpaceGuid" + else: + Space = Item['space'] + Line = " $%s_%s" % (Space, Item['cname']) + Match = re.match("\s*\{([x0-9a-fA-F,\s]+)\}\s*", Item['value']) + if Match: + DefaultValue = Match.group(1).strip() + else: + DefaultValue = Item['value'].strip() + if 'bitlength' in Item: + BsfFd.write(" %s%s%4d bits $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['bitlength'], DefaultValue)) + else: + BsfFd.write(" %s%s%4d bytes $_DEFAULT_ = %s\n" % (Line, ' ' * (64 - len(Line)), Item['length'], DefaultValue)) + TmpList = [] + if Item['type'] == "Combo": + if not Item['option'] in self._BuidinOption: + OptList = Item['option'].split(',') + for Option in OptList: + Option = Option.strip() + (OpVal, OpStr) = Option.split(':') + TmpList.append((OpVal, OpStr)) + return TmpList + + def WriteBsfOption (self, BsfFd, Item): + PcdName = Item['space'] + '_' + Item['cname'] + WriteHelp = 0 + if Item['type'] == "Combo": + if Item['option'] in self._BuidinOption: + Options = self._BuidinOption[Item['option']] + else: + Options = PcdName + BsfFd.write(' %s $%s, "%s", &%s,\n' % (Item['type'], PcdName, Item['name'], Options)) + WriteHelp = 1 + elif Item['type'].startswith("EditNum"): + Match = re.match("EditNum\s*,\s*(HEX|DEC)\s*,\s*\((\d+|0x[0-9A-Fa-f]+)\s*,\s*(\d+|0x[0-9A-Fa-f]+)\)", Item['type']) + if Match: + BsfFd.write(' EditNum $%s, "%s", %s,\n' % (PcdName, Item['name'], Match.group(1))) + WriteHelp = 2 + elif Item['type'].startswith("EditText"): + BsfFd.write(' %s $%s, "%s",\n' % (Item['type'], PcdName, Item['name'])) + WriteHelp = 1 + elif Item['type'] == "Table": + Columns = Item['option'].split(',') + if len(Columns) != 0: + BsfFd.write(' %s $%s "%s",' % (Item['type'], PcdName, Item['name'])) + for Col in Columns: + Fmt = Col.split(':') + if len(Fmt) != 3: + raise Exception("Column format '%s' is invalid !" % Fmt) + try: + Dtype = int(Fmt[1].strip()) + except: + raise Exception("Column size '%s' is invalid !" % Fmt[1]) + BsfFd.write('\n Column "%s", %d bytes, %s' % (Fmt[0].strip(), Dtype, Fmt[2].strip())) + BsfFd.write(',\n') + WriteHelp = 1 + + if WriteHelp > 0: + HelpLines = Item['help'].split('\\n\\r') + FirstLine = True + for HelpLine in HelpLines: + if FirstLine: + FirstLine = False + BsfFd.write(' Help "%s"\n' % (HelpLine)) + else: + BsfFd.write(' "%s"\n' % (HelpLine)) + if WriteHelp == 2: + BsfFd.write(' "Valid range: %s ~ %s"\n' % (Match.group(2), Match.group(3))) + + def GenerateBsfFile (self, BsfFile): + + if BsfFile == '': + self.Error = "BSF output file '%s' is invalid" % BsfFile + return 1 + + Error = 0 + OptionDict = {} + BsfFd = open(BsfFile, "w") + BsfFd.write("%s\n" % (__copyright_bsf__ % date.today().year)) + BsfFd.write("%s\n" % self._GlobalDataDef) + BsfFd.write("StructDef\n") + NextOffset = -1 + for Item in self._CfgItemList: + if Item['find'] != '': + BsfFd.write('\n Find "%s"\n' % Item['find']) + NextOffset = Item['offset'] + Item['length'] + if Item['name'] != '': + if NextOffset != Item['offset']: + BsfFd.write(" Skip %d bytes\n" % (Item['offset'] - NextOffset)) + if len(Item['subreg']) > 0: + NextOffset = Item['offset'] + BitsOffset = NextOffset * 8 + for SubItem in Item['subreg']: + BitsOffset += SubItem['bitlength'] + if SubItem['name'] == '': + if 'bitlength' in SubItem: + BsfFd.write(" Skip %d bits\n" % (SubItem['bitlength'])) + else: + BsfFd.write(" Skip %d bytes\n" % (SubItem['length'])) + else: + Options = self.WriteBsfStruct(BsfFd, SubItem) + if len(Options) > 0: + OptionDict[SubItem['space']+'_'+SubItem['cname']] = Options + + NextBitsOffset = (Item['offset'] + Item['length']) * 8 + if NextBitsOffset > BitsOffset: + BitsGap = NextBitsOffset - BitsOffset + BitsRemain = BitsGap % 8 + if BitsRemain: + BsfFd.write(" Skip %d bits\n" % BitsRemain) + BitsGap -= BitsRemain + BytesRemain = BitsGap / 8 + if BytesRemain: + BsfFd.write(" Skip %d bytes\n" % BytesRemain) + NextOffset = Item['offset'] + Item['length'] + else: + NextOffset = Item['offset'] + Item['length'] + Options = self.WriteBsfStruct(BsfFd, Item) + if len(Options) > 0: + OptionDict[Item['space']+'_'+Item['cname']] = Options + BsfFd.write("\nEndStruct\n\n") + + BsfFd.write("%s" % self._BuidinOptionTxt) + + for Each in OptionDict: + BsfFd.write("List &%s\n" % Each) + for Item in OptionDict[Each]: + BsfFd.write(' Selection %s , "%s"\n' % (Item[0], Item[1])) + BsfFd.write("EndList\n\n") + + BsfFd.write("BeginInfoBlock\n") + BsfFd.write(' PPVer "%s"\n' % (self._CfgBlkDict['ver'])) + BsfFd.write(' Description "%s"\n' % (self._CfgBlkDict['name'])) + BsfFd.write("EndInfoBlock\n\n") + + for Each in self._CfgPageDict: + BsfFd.write('Page "%s"\n' % self._CfgPageDict[Each]) + BsfItems = [] + for Item in self._CfgItemList: + if Item['name'] != '': + if Item['page'] != Each: + continue + if len(Item['subreg']) > 0: + for SubItem in Item['subreg']: + if SubItem['name'] != '': + BsfItems.append(SubItem) + else: + BsfItems.append(Item) + + BsfItems.sort(key=lambda x: x['order']) + + for Item in BsfItems: + self.WriteBsfOption (BsfFd, Item) + BsfFd.write("EndPage\n\n") + + BsfFd.close() + return Error + + +def Usage(): + print "GenCfgOpt Version 0.52" + print "Usage:" + print " GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]" + print " GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]" + print " GenCfgOpt GENBSF PlatformDscFile BuildFvDir BsfOutFile [-D Macros]" + +def Main(): + # + # Parse the options and args + # + GenCfgOpt = CGenCfgOpt() + argc = len(sys.argv) + if argc < 4: + Usage() + return 1 + else: + DscFile = sys.argv[2] + if not os.path.exists(DscFile): + print "ERROR: Cannot open DSC file '%s' !" % DscFile + return 2 + + OutFile = '' + if argc > 4: + if sys.argv[4][0] == '-': + Start = 4 + else: + OutFile = sys.argv[4] + Start = 5 + GenCfgOpt.ParseBuildMode(sys.argv[3]) + if GenCfgOpt.ParseMacros(sys.argv[Start:]) != 0: + print "ERROR: Macro parsing failed !" + return 3 + + FvDir = sys.argv[3] + if not os.path.exists(FvDir): + os.makedirs(FvDir) + + if GenCfgOpt.ParseDscFile(DscFile, FvDir) != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 5 + + if GenCfgOpt.UpdateSubRegionDefaultValue() != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 7 + + if sys.argv[1] == "UPDTXT": + Ret = GenCfgOpt.CreateSplitUpdTxt(OutFile) + if Ret != 0: + # No change is detected + if Ret == 256: + print "INFO: %s !" % (GenCfgOpt.Error) + else : + print "ERROR: %s !" % (GenCfgOpt.Error) + return Ret + elif sys.argv[1] == "HEADER": + if GenCfgOpt.CreateHeaderFile(OutFile) != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 8 + elif sys.argv[1] == "GENBSF": + if GenCfgOpt.GenerateBsfFile(OutFile) != 0: + print "ERROR: %s !" % GenCfgOpt.Error + return 9 + else: + if argc < 5: + Usage() + return 1 + print "ERROR: Unknown command '%s' !" % sys.argv[1] + Usage() + return 1 + return 0 + return 0 + + +if __name__ == '__main__': + sys.exit(Main()) diff --git a/Core/IntelFsp2Pkg/Tools/PatchFv.py b/Core/IntelFsp2Pkg/Tools/PatchFv.py new file mode 100644 index 0000000000..fc2ee19bcd --- /dev/null +++ b/Core/IntelFsp2Pkg/Tools/PatchFv.py @@ -0,0 +1,947 @@ +## @ PatchFv.py +# +# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that 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. +# +## + +import os +import re +import sys + +# +# Read data from file +# +# param [in] binfile Binary file +# param [in] offset Offset +# param [in] len Length +# +# retval value Value +# +def readDataFromFile (binfile, offset, len=1): + fd = open(binfile, "r+b") + fsize = os.path.getsize(binfile) + offval = offset & 0xFFFFFFFF + if (offval & 0x80000000): + offval = fsize - (0xFFFFFFFF - offval + 1) + fd.seek(offval) + bytearray = [ord(b) for b in fd.read(len)] + value = 0 + idx = len - 1 + while idx >= 0: + value = value << 8 | bytearray[idx] + idx = idx - 1 + fd.close() + return value + +# +# Check FSP header is valid or not +# +# param [in] binfile Binary file +# +# retval boolean True: valid; False: invalid +# +def IsFspHeaderValid (binfile): + fd = open (binfile, "rb") + bindat = fd.read(0x200) # only read first 0x200 bytes + fd.close() + HeaderList = ['FSPH' , 'FSPP' , 'FSPE'] # Check 'FSPH', 'FSPP', and 'FSPE' in the FSP header + OffsetList = [] + for each in HeaderList: + if each in bindat: + idx = bindat.index(each) + else: + idx = 0 + OffsetList.append(idx) + if not OffsetList[0] or not OffsetList[1]: # If 'FSPH' or 'FSPP' is missing, it will return false + return False + Revision = ord(bindat[OffsetList[0] + 0x0B]) + # + # if revision is bigger than 1, it means it is FSP v1.1 or greater revision, which must contain 'FSPE'. + # + if Revision > 1 and not OffsetList[2]: + return False # If FSP v1.1 or greater without 'FSPE', then return false + return True + +# +# Patch data in file +# +# param [in] binfile Binary file +# param [in] offset Offset +# param [in] value Patch value +# param [in] len Length +# +# retval len Length +# +def patchDataInFile (binfile, offset, value, len=1): + fd = open(binfile, "r+b") + fsize = os.path.getsize(binfile) + offval = offset & 0xFFFFFFFF + if (offval & 0x80000000): + offval = fsize - (0xFFFFFFFF - offval + 1) + bytearray = [] + idx = 0 + while idx < len: + bytearray.append(value & 0xFF) + value = value >> 8 + idx = idx + 1 + fd.seek(offval) + fd.write("".join(chr(b) for b in bytearray)) + fd.close() + return len + + +class Symbols: + def __init__(self): + self.dictSymbolAddress = {} + self.dictGuidNameXref = {} + self.dictFfsOffset = {} + self.dictVariable = {} + self.dictModBase = {} + self.fdFile = None + self.string = "" + self.fdBase = 0xFFFFFFFF + self.fdSize = 0 + self.index = 0 + self.fvList = [] + self.parenthesisOpenSet = '([{<' + self.parenthesisCloseSet = ')]}>' + + # + # Get FD file + # + # retval self.fdFile Retrieve FD file + # + def getFdFile (self): + return self.fdFile + + # + # Get FD size + # + # retval self.fdSize Retrieve the size of FD file + # + def getFdSize (self): + return self.fdSize + + def parseFvInfFile (self, infFile): + fvInfo = {} + fvFile = infFile[0:-4] + ".Fv" + fvInfo['Name'] = os.path.splitext(os.path.basename(infFile))[0] + fvInfo['Offset'] = self.getFvOffsetInFd(fvFile) + fvInfo['Size'] = readDataFromFile (fvFile, 0x20, 4) + fdIn = open(infFile, "r") + rptLines = fdIn.readlines() + fdIn.close() + fvInfo['Base'] = 0 + for rptLine in rptLines: + match = re.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine) + if match: + fvInfo['Base'] = int(match.group(1), 16) + break + self.fvList.append(dict(fvInfo)) + return 0 + + # + # Create dictionaries + # + # param [in] fvDir FV's directory + # param [in] fvNames All FV's names + # + # retval 0 Created dictionaries successfully + # + def createDicts (self, fvDir, fvNames): + # + # If the fvDir is not a dirctory, then raise an exception + # + if not os.path.isdir(fvDir): + raise Exception ("'%s' is not a valid directory!" % FvDir) + + # + # If the Guid.xref is not existing in fvDir, then raise an exception + # + xrefFile = os.path.join(fvDir, "Guid.xref") + if not os.path.exists(xrefFile): + raise Exception("Cannot open GUID Xref file '%s'!" % xrefFile) + + # + # Add GUID reference to dictionary + # + self.dictGuidNameXref = {} + self.parseGuidXrefFile(xrefFile) + + # + # Split up each FV from fvNames and get the fdBase + # + fvList = fvNames.split(":") + fdBase = fvList.pop() + if len(fvList) == 0: + fvList.append(fdBase) + + # + # If the FD file is not existing, then raise an exception + # + fdFile = os.path.join(fvDir, fdBase.strip() + ".fd") + if not os.path.exists(fdFile): + raise Exception("Cannot open FD file '%s'!" % fdFile) + + # + # Get the size of the FD file + # + self.fdFile = fdFile + self.fdSize = os.path.getsize(fdFile) + + # + # If the INF file, which is the first element of fvList, is not existing, then raise an exception + # + infFile = os.path.join(fvDir, fvList[0].strip()) + ".inf" + if not os.path.exists(infFile): + raise Exception("Cannot open INF file '%s'!" % infFile) + + # + # Parse INF file in order to get fdBase and then assign those values to dictVariable + # + self.parseInfFile(infFile) + self.dictVariable = {} + self.dictVariable["FDSIZE"] = self.fdSize + self.dictVariable["FDBASE"] = self.fdBase + + # + # Collect information from FV MAP file and FV TXT file then + # put them into dictionaries + # + self.fvList = [] + self.dictSymbolAddress = {} + self.dictFfsOffset = {} + for file in fvList: + + # + # If the .Fv.map file is not existing, then raise an exception. + # Otherwise, parse FV MAP file + # + fvFile = os.path.join(fvDir, file.strip()) + ".Fv" + mapFile = fvFile + ".map" + if not os.path.exists(mapFile): + raise Exception("Cannot open MAP file '%s'!" % mapFile) + + infFile = fvFile[0:-3] + ".inf" + self.parseFvInfFile(infFile) + self.parseFvMapFile(mapFile) + + # + # If the .Fv.txt file is not existing, then raise an exception. + # Otherwise, parse FV TXT file + # + fvTxtFile = fvFile + ".txt" + if not os.path.exists(fvTxtFile): + raise Exception("Cannot open FV TXT file '%s'!" % fvTxtFile) + + self.parseFvTxtFile(fvTxtFile) + + for fv in self.fvList: + self.dictVariable['_BASE_%s_' % fv['Name']] = fv['Base'] + # + # Search all MAP files in FFS directory if it exists then parse MOD MAP file + # + ffsDir = os.path.join(fvDir, "Ffs") + if (os.path.isdir(ffsDir)): + for item in os.listdir(ffsDir): + if len(item) <= 0x24: + continue + mapFile =os.path.join(ffsDir, item, "%s.map" % item[0:0x24]) + if not os.path.exists(mapFile): + continue + self.parseModMapFile(item[0x24:], mapFile) + + return 0 + + # + # Get FV offset in FD file + # + # param [in] fvFile FV file + # + # retval offset Got FV offset successfully + # + def getFvOffsetInFd(self, fvFile): + # + # Check if the first 0x70 bytes of fvFile can be found in fdFile + # + fvHandle = open(fvFile, "r+b") + fdHandle = open(self.fdFile, "r+b") + offset = fdHandle.read().find(fvHandle.read(0x70)) + fvHandle.close() + fdHandle.close() + if offset == -1: + raise Exception("Could not locate FV file %s in FD!" % fvFile) + return offset + + # + # Parse INF file + # + # param [in] infFile INF file + # + # retval 0 Parsed INF file successfully + # + def parseInfFile(self, infFile): + # + # Get FV offset and search EFI_BASE_ADDRESS in the FD file + # then assign the value of EFI_BASE_ADDRESS to fdBase + # + fvOffset = self.getFvOffsetInFd(infFile[0:-4] + ".Fv") + fdIn = open(infFile, "r") + rptLine = fdIn.readline() + self.fdBase = 0xFFFFFFFF + while (rptLine != "" ): + #EFI_BASE_ADDRESS = 0xFFFDF400 + match = re.match("^EFI_BASE_ADDRESS\s*=\s*(0x[a-fA-F0-9]+)", rptLine) + if match is not None: + self.fdBase = int(match.group(1), 16) - fvOffset + rptLine = fdIn.readline() + fdIn.close() + if self.fdBase == 0xFFFFFFFF: + raise Exception("Could not find EFI_BASE_ADDRESS in INF file!" % fvFile) + return 0 + + # + # Parse FV TXT file + # + # param [in] fvTxtFile .Fv.txt file + # + # retval 0 Parsed FV TXT file successfully + # + def parseFvTxtFile(self, fvTxtFile): + fvName = os.path.basename(fvTxtFile)[0:-7].upper() + # + # Get information from .Fv.txt in order to create a dictionary + # For example, + # self.dictFfsOffset[912740BE-2284-4734-B971-84B027353F0C] = 0x000D4078 + # + fvOffset = self.getFvOffsetInFd(fvTxtFile[0:-4]) + fdIn = open(fvTxtFile, "r") + rptLine = fdIn.readline() + while (rptLine != "" ): + match = re.match("(0x[a-fA-F0-9]+)\s([0-9a-fA-F\-]+)", rptLine) + if match is not None: + if match.group(2) in self.dictFfsOffset: + self.dictFfsOffset[fvName + ':' + match.group(2)] = "0x%08X" % (int(match.group(1), 16) + fvOffset) + else: + self.dictFfsOffset[match.group(2)] = "0x%08X" % (int(match.group(1), 16) + fvOffset) + rptLine = fdIn.readline() + fdIn.close() + return 0 + + # + # Parse FV MAP file + # + # param [in] mapFile .Fv.map file + # + # retval 0 Parsed FV MAP file successfully + # + def parseFvMapFile(self, mapFile): + # + # Get information from .Fv.map in order to create dictionaries + # For example, + # self.dictModBase[FspSecCore:BASE] = 4294592776 (0xfffa4908) + # self.dictModBase[FspSecCore:ENTRY] = 4294606552 (0xfffa7ed8) + # self.dictModBase[FspSecCore:TEXT] = 4294593080 (0xfffa4a38) + # self.dictModBase[FspSecCore:DATA] = 4294612280 (0xfffa9538) + # self.dictSymbolAddress[FspSecCore:_SecStartup] = 0x00fffa4a38 + # + fdIn = open(mapFile, "r") + rptLine = fdIn.readline() + modName = "" + foundModHdr = False + while (rptLine != "" ): + if rptLine[0] != ' ': + #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958) + #(GUID=86D70125-BAA3-4296-A62F-602BEBBB9081 .textbaseaddress=0x00fffb4398 .databaseaddress=0x00fffb4178) + match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+)\)", rptLine) + if match is not None: + foundModHdr = True + modName = match.group(1) + if len(modName) == 36: + modName = self.dictGuidNameXref[modName.upper()] + self.dictModBase['%s:BASE' % modName] = int (match.group(2), 16) + self.dictModBase['%s:ENTRY' % modName] = int (match.group(3), 16) + match = re.match("\(GUID=([A-Z0-9\-]+)\s+\.textbaseaddress=(0x[0-9a-fA-F]+)\s+\.databaseaddress=(0x[0-9a-fA-F]+)\)", rptLine) + if match is not None: + if foundModHdr: + foundModHdr = False + else: + modName = match.group(1) + if len(modName) == 36: + modName = self.dictGuidNameXref[modName.upper()] + self.dictModBase['%s:TEXT' % modName] = int (match.group(2), 16) + self.dictModBase['%s:DATA' % modName] = int (match.group(3), 16) + else: + # 0x00fff8016c __ModuleEntryPoint + foundModHdr = False + match = re.match("^\s+(0x[a-z0-9]+)\s+([_a-zA-Z0-9]+)", rptLine) + if match is not None: + self.dictSymbolAddress["%s:%s"%(modName, match.group(2))] = match.group(1) + rptLine = fdIn.readline() + fdIn.close() + return 0 + + # + # Parse MOD MAP file + # + # param [in] moduleName Module name + # param [in] mapFile .Fv.map file + # + # retval 0 Parsed MOD MAP file successfully + # retval 1 There is no moduleEntryPoint in modSymbols + # + def parseModMapFile(self, moduleName, mapFile): + # + # Get information from mapFile by moduleName in order to create a dictionary + # For example, + # self.dictSymbolAddress[FspSecCore:___guard_fids_count] = 0x00fffa4778 + # + modSymbols = {} + fdIn = open(mapFile, "r") + reportLines = fdIn.readlines() + fdIn.close() + + moduleEntryPoint = "__ModuleEntryPoint" + reportLine = reportLines[0] + if reportLine.strip().find("Archive member included") != -1: + #GCC + # 0x0000000000001d55 IoRead8 + patchMapFileMatchString = "\s+(0x[0-9a-fA-F]{16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s" + matchKeyGroupIndex = 2 + matchSymbolGroupIndex = 1 + prefix = '_' + else: + #MSFT + #0003:00000190 _gComBase 00007a50 SerialPo + patchMapFileMatchString = "^\s[0-9a-fA-F]{4}:[0-9a-fA-F]{8}\s+(\w+)\s+([0-9a-fA-F]{8}\s+)" + matchKeyGroupIndex = 1 + matchSymbolGroupIndex = 2 + prefix = '' + + for reportLine in reportLines: + match = re.match(patchMapFileMatchString, reportLine) + if match is not None: + modSymbols[prefix + match.group(matchKeyGroupIndex)] = match.group(matchSymbolGroupIndex) + + # Handle extra module patchable PCD variable in Linux map since it might have different format + # .data._gPcd_BinaryPatch_PcdVpdBaseAddress + # 0x0000000000003714 0x4 /tmp/ccmytayk.ltrans1.ltrans.o + handleNext = False + if matchSymbolGroupIndex == 1: + for reportLine in reportLines: + if handleNext: + handleNext = False + pcdName = match.group(1) + match = re.match("\s+(0x[0-9a-fA-F]{16})\s+", reportLine) + if match is not None: + modSymbols[prefix + pcdName] = match.group(1) + else: + match = re.match("^\s\.data\.(_gPcd_BinaryPatch[_a-zA-Z0-9\-]+)", reportLine) + if match is not None: + handleNext = True + continue + + if not moduleEntryPoint in modSymbols: + return 1 + + modEntry = '%s:%s' % (moduleName,moduleEntryPoint) + if not modEntry in self.dictSymbolAddress: + modKey = '%s:ENTRY' % moduleName + if modKey in self.dictModBase: + baseOffset = self.dictModBase['%s:ENTRY' % moduleName] - int(modSymbols[moduleEntryPoint], 16) + else: + return 2 + else: + baseOffset = int(self.dictSymbolAddress[modEntry], 16) - int(modSymbols[moduleEntryPoint], 16) + for symbol in modSymbols: + fullSym = "%s:%s" % (moduleName, symbol) + if not fullSym in self.dictSymbolAddress: + self.dictSymbolAddress[fullSym] = "0x00%08x" % (baseOffset+ int(modSymbols[symbol], 16)) + return 0 + + # + # Parse Guid.xref file + # + # param [in] xrefFile the full directory of Guid.xref file + # + # retval 0 Parsed Guid.xref file successfully + # + def parseGuidXrefFile(self, xrefFile): + # + # Get information from Guid.xref in order to create a GuidNameXref dictionary + # The dictGuidNameXref, for example, will be like + # dictGuidNameXref [1BA0062E-C779-4582-8566-336AE8F78F09] = FspSecCore + # + fdIn = open(xrefFile, "r") + rptLine = fdIn.readline() + while (rptLine != "" ): + match = re.match("([0-9a-fA-F\-]+)\s([_a-zA-Z0-9]+)", rptLine) + if match is not None: + self.dictGuidNameXref[match.group(1).upper()] = match.group(2) + rptLine = fdIn.readline() + fdIn.close() + return 0 + + # + # Get current character + # + # retval elf.string[self.index] + # retval '' Exception + # + def getCurr(self): + try: + return self.string[self.index] + except Exception: + return '' + + # + # Check to see if it is last index + # + # retval self.index + # + def isLast(self): + return self.index == len(self.string) + + # + # Move to next index + # + def moveNext(self): + self.index += 1 + + # + # Skip space + # + def skipSpace(self): + while not self.isLast(): + if self.getCurr() in ' \t': + self.moveNext() + else: + return + + # + # Parse value + # + # retval value + # + def parseValue(self): + self.skipSpace() + var = '' + while not self.isLast(): + char = self.getCurr() + if char.lower() in '_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789:-': + var += char + self.moveNext() + else: + break + + if ':' in var: + partList = var.split(':') + lenList = len(partList) + if lenList != 2 and lenList != 3: + raise Exception("Unrecognized expression %s" % var) + modName = partList[lenList-2] + modOff = partList[lenList-1] + if ('-' not in modName) and (modOff[0] in '0123456789'): + # MOD: OFFSET + var = self.getModGuid(modName) + ":" + modOff + if '-' in var: # GUID:OFFSET + value = self.getGuidOff(var) + else: + value = self.getSymbols(var) + self.synUsed = True + else: + if var[0] in '0123456789': + value = self.getNumber(var) + else: + value = self.getVariable(var) + return int(value) + + # + # Parse single operation + # + # retval ~self.parseBrace() or self.parseValue() + # + def parseSingleOp(self): + self.skipSpace() + char = self.getCurr() + if char == '~': + self.moveNext() + return ~self.parseBrace() + else: + return self.parseValue() + + # + # Parse symbol of Brace([, {, <) + # + # retval value or self.parseSingleOp() + # + def parseBrace(self): + self.skipSpace() + char = self.getCurr() + parenthesisType = self.parenthesisOpenSet.find(char) + if parenthesisType >= 0: + self.moveNext() + value = self.parseExpr() + self.skipSpace() + if self.getCurr() != self.parenthesisCloseSet[parenthesisType]: + raise Exception("No closing brace") + self.moveNext() + if parenthesisType == 1: # [ : Get content + value = self.getContent(value) + elif parenthesisType == 2: # { : To address + value = self.toAddress(value) + elif parenthesisType == 3: # < : To offset + value = self.toOffset(value) + return value + else: + return self.parseSingleOp() + + # + # Parse symbol of Multiplier(*) + # + # retval value or self.parseSingleOp() + # + def parseMul(self): + values = [self.parseBrace()] + while True: + self.skipSpace() + char = self.getCurr() + if char == '*': + self.moveNext() + values.append(self.parseBrace()) + else: + break + value = 1 + for each in values: + value *= each + return value + + # + # Parse symbol of And(&) and Or(|) + # + # retval value + # + def parseAndOr(self): + value = self.parseMul() + op = None + while True: + self.skipSpace() + char = self.getCurr() + if char == '&': + self.moveNext() + value &= self.parseMul() + elif char == '|': + div_index = self.index + self.moveNext() + value |= self.parseMul() + else: + break + + return value + + # + # Parse symbol of Add(+) and Minus(-) + # + # retval sum(values) + # + def parseAddMinus(self): + values = [self.parseAndOr()] + while True: + self.skipSpace() + char = self.getCurr() + if char == '+': + self.moveNext() + values.append(self.parseAndOr()) + elif char == '-': + self.moveNext() + values.append(-1 * self.parseAndOr()) + else: + break + return sum(values) + + # + # Parse expression + # + # retval self.parseAddMinus() + # + def parseExpr(self): + return self.parseAddMinus() + + # + # Get result + # + # retval value + # + def getResult(self): + value = self.parseExpr() + self.skipSpace() + if not self.isLast(): + raise Exception("Unexpected character found '%s'" % self.getCurr()) + return value + + # + # Get module GUID + # + # retval value + # + def getModGuid(self, var): + guid = (guid for guid,name in self.dictGuidNameXref.items() if name==var) + try: + value = guid.next() + except Exception: + raise Exception("Unknown module name %s !" % var) + return value + + # + # Get variable + # + # retval value + # + def getVariable(self, var): + value = self.dictVariable.get(var, None) + if value == None: + raise Exception("Unrecognized variable '%s'" % var) + return value + + # + # Get number + # + # retval value + # + def getNumber(self, var): + var = var.strip() + if var.startswith('0x'): # HEX + value = int(var, 16) + else: + value = int(var, 10) + return value + + # + # Get content + # + # param [in] value + # + # retval value + # + def getContent(self, value): + return readDataFromFile (self.fdFile, self.toOffset(value), 4) + + # + # Change value to address + # + # param [in] value + # + # retval value + # + def toAddress(self, value): + if value < self.fdSize: + value = value + self.fdBase + return value + + # + # Change value to offset + # + # param [in] value + # + # retval value + # + def toOffset(self, value): + offset = None + for fvInfo in self.fvList: + if (value >= fvInfo['Base']) and (value < fvInfo['Base'] + fvInfo['Size']): + offset = value - fvInfo['Base'] + fvInfo['Offset'] + if not offset: + if (value >= self.fdBase) and (value < self.fdBase + self.fdSize): + offset = value - self.fdBase + else: + offset = value + if offset >= self.fdSize: + raise Exception("Invalid file offset 0x%08x !" % value) + return offset + + # + # Get GUID offset + # + # param [in] value + # + # retval value + # + def getGuidOff(self, value): + # GUID:Offset + symbolName = value.split(':') + if len(symbolName) == 3: + fvName = symbolName[0].upper() + keyName = '%s:%s' % (fvName, symbolName[1]) + offStr = symbolName[2] + elif len(symbolName) == 2: + keyName = symbolName[0] + offStr = symbolName[1] + if keyName in self.dictFfsOffset: + value = (int(self.dictFfsOffset[keyName], 16) + int(offStr, 16)) & 0xFFFFFFFF + else: + raise Exception("Unknown GUID %s !" % value) + return value + + # + # Get symbols + # + # param [in] value + # + # retval ret + # + def getSymbols(self, value): + if self.dictSymbolAddress.has_key(value): + # Module:Function + ret = int (self.dictSymbolAddress[value], 16) + else: + raise Exception("Unknown symbol %s !" % value) + return ret + + # + # Evaluate symbols + # + # param [in] expression + # param [in] isOffset + # + # retval value & 0xFFFFFFFF + # + def evaluate(self, expression, isOffset): + self.index = 0 + self.synUsed = False + self.string = expression + value = self.getResult() + if isOffset: + if self.synUsed: + # Consider it as an address first + value = self.toOffset(value) + if value & 0x80000000: + # Consider it as a negative offset next + offset = (~value & 0xFFFFFFFF) + 1 + if offset < self.fdSize: + value = self.fdSize - offset + if value >= self.fdSize: + raise Exception("Invalid offset expression !") + return value & 0xFFFFFFFF + +# +# Print out the usage +# +def usage(): + print "Usage: \n\tPatchFv FvBuildDir [FvFileBaseNames:]FdFileBaseNameToPatch \"Offset, Value\"" + +def main(): + # + # Parse the options and args + # + symTables = Symbols() + + # + # If the arguments are less than 4, then return an error. + # + if len(sys.argv) < 4: + Usage() + return 1 + + # + # If it fails to create dictionaries, then return an error. + # + if symTables.createDicts(sys.argv[1], sys.argv[2]) != 0: + print "ERROR: Failed to create symbol dictionary!!" + return 2 + + # + # Get FD file and size + # + fdFile = symTables.getFdFile() + fdSize = symTables.getFdSize() + + try: + # + # Check to see if FSP header is valid + # + ret = IsFspHeaderValid(fdFile) + if ret == False: + raise Exception ("The FSP header is not valid. Stop patching FD.") + comment = "" + for fvFile in sys.argv[3:]: + # + # Check to see if it has enough arguments + # + items = fvFile.split(",") + if len (items) < 2: + raise Exception("Expect more arguments for '%s'!" % fvFile) + + comment = "" + command = "" + params = [] + for item in items: + item = item.strip() + if item.startswith("@"): + comment = item[1:] + elif item.startswith("$"): + command = item[1:] + else: + if len(params) == 0: + isOffset = True + else : + isOffset = False + # + # Parse symbols then append it to params + # + params.append (symTables.evaluate(item, isOffset)) + + # + # Patch a new value into FD file if it is not a command + # + if command == "": + # Patch a DWORD + if len (params) == 2: + offset = params[0] + value = params[1] + oldvalue = readDataFromFile(fdFile, offset, 4) + ret = patchDataInFile (fdFile, offset, value, 4) - 4 + else: + raise Exception ("Patch command needs 2 parameters !") + + if ret: + raise Exception ("Patch failed for offset 0x%08X" % offset) + else: + print "Patched offset 0x%08X:[%08X] with value 0x%08X # %s" % (offset, oldvalue, value, comment) + + elif command == "COPY": + # + # Copy binary block from source to destination + # + if len (params) == 3: + src = symTables.toOffset(params[0]) + dest = symTables.toOffset(params[1]) + clen = symTables.toOffset(params[2]) + if (dest + clen <= fdSize) and (src + clen <= fdSize): + oldvalue = readDataFromFile(fdFile, src, clen) + ret = patchDataInFile (fdFile, dest, oldvalue, clen) - clen + else: + raise Exception ("Copy command OFFSET or LENGTH parameter is invalid !") + else: + raise Exception ("Copy command needs 3 parameters !") + + if ret: + raise Exception ("Copy failed from offset 0x%08X to offset 0x%08X!" % (src, dest)) + else : + print "Copied %d bytes from offset 0x%08X ~ offset 0x%08X # %s" % (clen, src, dest, comment) + else: + raise Exception ("Unknown command %s!" % command) + return 0 + + except Exception as (ex): + print "ERROR: %s" % ex + return 1 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/Core/IntelFsp2Pkg/Tools/SplitFspBin.py b/Core/IntelFsp2Pkg/Tools/SplitFspBin.py new file mode 100644 index 0000000000..ef759f0dc4 --- /dev/null +++ b/Core/IntelFsp2Pkg/Tools/SplitFspBin.py @@ -0,0 +1,679 @@ +## @ FspTool.py +# +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
+# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License that 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. +# +## + +import os +import sys +import uuid +import copy +import struct +import argparse +from ctypes import * + +""" +This utility supports some operations for Intel FSP 2.0 image. +It supports: + - Display FSP 2.0 information header + - Split FSP 2.0 image into individual FSP-T/M/S/O component + - Rebase FSP 2.0 components to a different base address + - Generate FSP mapping C header file +""" + +CopyRightHeaderFile = """/* + * + * Automatically generated file; DO NOT EDIT. + * FSP mapping file + * + */ +""" + +class c_uint24(Structure): + """Little-Endian 24-bit Unsigned Integer""" + _pack_ = 1 + _fields_ = [('Data', (c_uint8 * 3))] + + def __init__(self, val=0): + self.set_value(val) + + def __str__(self, indent=0): + return '0x%.6x' % self.value + + def __int__(self): + return self.get_value() + + def set_value(self, val): + self.Data[0:3] = Val2Bytes(val, 3) + + def get_value(self): + return Bytes2Val(self.Data[0:3]) + + value = property(get_value, set_value) + +class EFI_FIRMWARE_VOLUME_HEADER(Structure): + _fields_ = [ + ('ZeroVector', ARRAY(c_uint8, 16)), + ('FileSystemGuid', ARRAY(c_uint8, 16)), + ('FvLength', c_uint64), + ('Signature', ARRAY(c_char, 4)), + ('Attributes', c_uint32), + ('HeaderLength', c_uint16), + ('Checksum', c_uint16), + ('ExtHeaderOffset', c_uint16), + ('Reserved', c_uint8), + ('Revision', c_uint8) + ] + +class EFI_FIRMWARE_VOLUME_EXT_HEADER(Structure): + _fields_ = [ + ('FvName', ARRAY(c_uint8, 16)), + ('ExtHeaderSize', c_uint32) + ] + +class EFI_FFS_INTEGRITY_CHECK(Structure): + _fields_ = [ + ('Header', c_uint8), + ('File', c_uint8) + ] + +class EFI_FFS_FILE_HEADER(Structure): + _fields_ = [ + ('Name', ARRAY(c_uint8, 16)), + ('IntegrityCheck', EFI_FFS_INTEGRITY_CHECK), + ('Type', c_uint8), + ('Attributes', c_uint8), + ('Size', c_uint24), + ('State', c_uint8) + ] + +class EFI_COMMON_SECTION_HEADER(Structure): + _fields_ = [ + ('Size', c_uint24), + ('Type', c_uint8) + ] + +class FSP_COMMON_HEADER(Structure): + _fields_ = [ + ('Signature', ARRAY(c_char, 4)), + ('HeaderLength', c_uint32) + ] + +class FSP_INFORMATION_HEADER(Structure): + _fields_ = [ + ('Signature', ARRAY(c_char, 4)), + ('HeaderLength', c_uint32), + ('Reserved1', c_uint16), + ('SpecVersion', c_uint8), + ('HeaderRevision', c_uint8), + ('ImageRevision', c_uint32), + ('ImageId', ARRAY(c_char, 8)), + ('ImageSize', c_uint32), + ('ImageBase', c_uint32), + ('ImageAttribute', c_uint16), + ('ComponentAttribute', c_uint16), + ('CfgRegionOffset', c_uint32), + ('CfgRegionSize', c_uint32), + ('Reserved2', c_uint32), + ('TempRamInitEntryOffset', c_uint32), + ('Reserved3', c_uint32), + ('NotifyPhaseEntryOffset', c_uint32), + ('FspMemoryInitEntryOffset', c_uint32), + ('TempRamExitEntryOffset', c_uint32), + ('FspSiliconInitEntryOffset', c_uint32) + ] + +class FSP_PATCH_TABLE(Structure): + _fields_ = [ + ('Signature', ARRAY(c_char, 4)), + ('HeaderLength', c_uint16), + ('HeaderRevision', c_uint8), + ('Reserved', c_uint8), + ('PatchEntryNum', c_uint32) + ] + +class EFI_IMAGE_DATA_DIRECTORY(Structure): + _fields_ = [ + ('VirtualAddress', c_uint32), + ('Size', c_uint32) + ] + +class EFI_TE_IMAGE_HEADER(Structure): + _fields_ = [ + ('Signature', ARRAY(c_char, 2)), + ('Machine', c_uint16), + ('NumberOfSections', c_uint8), + ('Subsystem', c_uint8), + ('StrippedSize', c_uint16), + ('AddressOfEntryPoint', c_uint32), + ('BaseOfCode', c_uint32), + ('ImageBase', c_uint64), + ('DataDirectoryBaseReloc', EFI_IMAGE_DATA_DIRECTORY), + ('DataDirectoryDebug', EFI_IMAGE_DATA_DIRECTORY) + ] + +class PE_RELOC_BLOCK_HEADER(Structure): + _fields_ = [ + ('PageRVA', c_uint32), + ('BlockSize', c_uint32) + ] + +class EFI_FV_FILETYPE: + ALL = 0x00 + RAW = 0x01 + FREEFORM = 0x02 + SECURITY_CORE = 0x03 + PEI_CORE = 0x04 + DXE_CORE = 0x05 + PEIM = 0x06 + DRIVER = 0x07 + COMBINED_PEIM_DRIVER = 0x08 + APPLICATION = 0x09 + SMM = 0x0a + FIRMWARE_VOLUME_IMAGE = 0x0b + COMBINED_SMM_DXE = 0x0c + SMM_CORE = 0x0d + OEM_MIN = 0xc0 + OEM_MAX = 0xdf + DEBUG_MIN = 0xe0 + DEBUG_MAX = 0xef + FFS_MIN = 0xf0 + FFS_MAX = 0xff + FFS_PAD = 0xf0 + +class EFI_SECTION_TYPE: + """Enumeration of all valid firmware file section types.""" + ALL = 0x00 + COMPRESSION = 0x01 + GUID_DEFINED = 0x02 + DISPOSABLE = 0x03 + PE32 = 0x10 + PIC = 0x11 + TE = 0x12 + DXE_DEPEX = 0x13 + VERSION = 0x14 + USER_INTERFACE = 0x15 + COMPATIBILITY16 = 0x16 + FIRMWARE_VOLUME_IMAGE = 0x17 + FREEFORM_SUBTYPE_GUID = 0x18 + RAW = 0x19 + PEI_DEPEX = 0x1b + SMM_DEPEX = 0x1c + +def AlignPtr (offset, alignment = 8): + return (offset + alignment - 1) & ~(alignment - 1) + +def Bytes2Val (bytes): + return reduce(lambda x,y: (x<<8)|y, bytes[::-1] ) + +def Val2Bytes (value, blen): + return [(value>>(i*8) & 0xff) for i in range(blen)] + +def OutputStruct (obj, indent = 0, plen = 0): + if indent: + body = '' + else: + body = (' ' * indent + '<%s>:\n') % obj.__class__.__name__ + + if plen == 0: + plen = sizeof(obj) + + max_key_len = 26 + pstr = (' ' * (indent + 1) + '{0:<%d} = {1}\n') % max_key_len + + for field in obj._fields_: + key = field[0] + val = getattr(obj, key) + rep = '' + if not isinstance(val, c_uint24) and isinstance(val, Structure): + body += pstr.format(key, val.__class__.__name__) + body += OutputStruct (val, indent + 1) + plen -= sizeof(val) + else: + if type(val) is str: + rep = "0x%X ('%s')" % (Bytes2Val(bytearray(val)), val) + elif type(val) in (int, long): + rep = '0x%X' % val + elif isinstance(val, c_uint24): + rep = '0x%X' % val.get_value() + elif 'c_ubyte_Array' in str(type(val)): + if sizeof(val) == 16: + rep = str(uuid.UUID(bytes = str(bytearray(val)))).upper() + else: + res = ['0x%02X'%i for i in bytearray(val)] + rep = '[%s]' % (','.join(res)) + else: + rep = str(val) + plen -= sizeof(field[1]) + body += pstr.format(key, rep) + if plen <= 0: + break + return body + +class Section: + def __init__(self, offset, secdata): + self.SecHdr = EFI_COMMON_SECTION_HEADER.from_buffer (secdata, 0) + self.SecData = secdata[0:int(self.SecHdr.Size)] + self.Offset = offset + +class FirmwareFile: + def __init__(self, offset, filedata): + self.FfsHdr = EFI_FFS_FILE_HEADER.from_buffer (filedata, 0) + self.FfsData = filedata[0:int(self.FfsHdr.Size)] + self.Offset = offset + self.SecList = [] + + def ParseFfs(self): + ffssize = len(self.FfsData) + offset = sizeof(self.FfsHdr) + if self.FfsHdr.Name != '\xff' * 16: + while offset < ffssize: + sechdr = EFI_COMMON_SECTION_HEADER.from_buffer (self.FfsData, offset) + sec = Section (offset, self.FfsData[offset:offset + int(sechdr.Size)]) + self.SecList.append(sec) + offset += int(sechdr.Size) + offset = AlignPtr(offset, 4) + +class FirmwareVolume: + def __init__(self, offset, fvdata): + self.FvHdr = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (fvdata, 0) + self.FvData = fvdata[0 : self.FvHdr.FvLength] + self.Offset = offset + if self.FvHdr.ExtHeaderOffset > 0: + self.FvExtHdr = EFI_FIRMWARE_VOLUME_EXT_HEADER.from_buffer (self.FvData, self.FvHdr.ExtHeaderOffset) + else: + self.FvExtHdr = None + self.FfsList = [] + + def ParseFv(self): + fvsize = len(self.FvData) + if self.FvExtHdr: + offset = self.FvHdr.ExtHeaderOffset + self.FvExtHdr.ExtHeaderSize + else: + offset = self.FvHdr.HeaderLength + offset = AlignPtr(offset) + while offset < fvsize: + ffshdr = EFI_FFS_FILE_HEADER.from_buffer (self.FvData, offset) + if (ffshdr.Name == '\xff' * 16) and (int(ffshdr.Size) == 0xFFFFFF): + offset = fvsize + else: + ffs = FirmwareFile (offset, self.FvData[offset:offset + int(ffshdr.Size)]) + ffs.ParseFfs() + self.FfsList.append(ffs) + offset += int(ffshdr.Size) + offset = AlignPtr(offset) + +class FspImage: + def __init__(self, offset, fih, fihoff, patch): + self.Fih = fih + self.FihOffset = fihoff + self.Offset = offset + self.FvIdxList = [] + self.Type = "XTMSXXXXOXXXXXXX"[(fih.ComponentAttribute >> 12) & 0x0F] + self.PatchList = patch + self.PatchList.append(fihoff + 0x1C) + + def AppendFv(self, FvIdx): + self.FvIdxList.append(FvIdx) + + def Patch(self, delta, fdbin): + count = 0 + applied = 0 + for idx, patch in enumerate(self.PatchList): + ptype = (patch>>24) & 0x0F + if ptype not in [0x00, 0x0F]: + raise Exception('ERROR: Invalid patch type %d !' % ptype) + if patch & 0x80000000: + patch = self.Fih.ImageSize - (0x1000000 - (patch & 0xFFFFFF)) + else: + patch = patch & 0xFFFFFF + if (patch < self.Fih.ImageSize) and (patch + sizeof(c_uint32) <= self.Fih.ImageSize): + offset = patch + self.Offset + value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)]) + value += delta + fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, sizeof(c_uint32)) + applied += 1 + count += 1 + # Don't count the FSP base address patch entry appended at the end + if count != 0: + count -= 1 + applied -= 1 + return (count, applied) + +class FirmwareDevice: + def __init__(self, offset, fdfile): + self.FvList = [] + self.FspList = [] + self.FdFile = fdfile + self.Offset = 0 + hfsp = open (self.FdFile, 'rb') + self.FdData = bytearray(hfsp.read()) + hfsp.close() + + def ParseFd(self): + offset = 0 + fdsize = len(self.FdData) + self.FvList = [] + while offset < fdsize: + fvh = EFI_FIRMWARE_VOLUME_HEADER.from_buffer (self.FdData, offset) + if '_FVH' != fvh.Signature: + raise Exception("ERROR: Invalid FV header !") + fv = FirmwareVolume (offset, self.FdData[offset:offset + fvh.FvLength]) + fv.ParseFv () + self.FvList.append(fv) + offset += fv.FvHdr.FvLength + + def CheckFsp (self): + if len(self.FspList) == 0: + return + + fih = None + for fsp in self.FspList: + if fsp.Fih.HeaderRevision < 3: + raise Exception("ERROR: FSP 1.x is not supported by this tool !") + if not fih: + fih = fsp.Fih + else: + newfih = fsp.Fih + if (newfih.ImageId != fih.ImageId) or (newfih.ImageRevision != fih.ImageRevision): + raise Exception("ERROR: Inconsistent FSP ImageId or ImageRevision detected !") + + def ParseFsp(self): + flen = 0 + for idx, fv in enumerate(self.FvList): + # Check if this FV contains FSP header + if flen == 0: + if len(fv.FfsList) == 0: + continue + ffs = fv.FfsList[0] + if len(ffs.SecList) == 0: + continue + sec = ffs.SecList[0] + if sec.SecHdr.Type != EFI_SECTION_TYPE.RAW: + continue + fihoffset = ffs.Offset + sec.Offset + sizeof(sec.SecHdr) + fspoffset = fv.Offset + offset = fspoffset + fihoffset + fih = FSP_INFORMATION_HEADER.from_buffer (self.FdData, offset) + if 'FSPH' != fih.Signature: + continue + + offset += fih.HeaderLength + offset = AlignPtr(offset, 4) + plist = [] + while True: + fch = FSP_COMMON_HEADER.from_buffer (self.FdData, offset) + if 'FSPP' != fch.Signature: + offset += fch.HeaderLength + offset = AlignPtr(offset, 4) + else: + fspp = FSP_PATCH_TABLE.from_buffer (self.FdData, offset) + offset += sizeof(fspp) + pdata = (c_uint32 * fspp.PatchEntryNum).from_buffer(self.FdData, offset) + plist = list(pdata) + break + + fsp = FspImage (fspoffset, fih, fihoffset, plist) + fsp.AppendFv (idx) + self.FspList.append(fsp) + flen = fsp.Fih.ImageSize - fv.FvHdr.FvLength + else: + fsp.AppendFv (idx) + flen -= fv.FvHdr.FvLength + if flen < 0: + raise Exception("ERROR: Incorrect FV size in image !") + self.CheckFsp () + +class TeImage: + def __init__(self, offset, tedata): + self.Offset = offset + self.TeHdr = EFI_TE_IMAGE_HEADER.from_buffer (tedata, 0) + self.TeData = tedata + self.RelocList = [] + + def ParseReloc(self): + rsize = self.TeHdr.DataDirectoryBaseReloc.Size + roffset = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + self.TeHdr.DataDirectoryBaseReloc.VirtualAddress + alignment = 4 + offset = roffset + while offset < roffset + rsize: + offset = AlignPtr(offset, 4) + blkhdr = PE_RELOC_BLOCK_HEADER.from_buffer(self.TeData, offset) + offset += sizeof(blkhdr) + # Read relocation type,offset pairs + rlen = blkhdr.BlockSize - sizeof(PE_RELOC_BLOCK_HEADER) + rnum = rlen/sizeof(c_uint16) + rdata = (c_uint16 * rnum).from_buffer(self.TeData, offset) + for each in rdata: + roff = each & 0xfff + rtype = each >> 12 + if rtype == 0: # IMAGE_REL_BASED.ABSOLUTE: + continue + if rtype != 3: # IMAGE_REL_BASED_HIGHLOW + raise Exception("ERROR: Unsupported relocation type %d!" % rtype) + # Calculate the offset of the relocation + aoff = sizeof(self.TeHdr) - self.TeHdr.StrippedSize + blkhdr.PageRVA + roff + self.RelocList.append((rtype, aoff)) + offset += sizeof(rdata) + + def Rebase(self, delta, fdbin): + count = 0 + if delta == 0: + return count + + for (rtype, roff) in self.RelocList: + if rtype == 0x03: # HIGHLOW + offset = roff + self.Offset + value = Bytes2Val(fdbin[offset:offset+sizeof(c_uint32)]) + value += delta + fdbin[offset:offset+sizeof(c_uint32)] = Val2Bytes(value, sizeof(c_uint32)) + count += 1 + else: + raise Exception('ERROR: Unknown relocation type %d !' % rtype) + + tehdr = self.TeHdr + tehdr.ImageBase += delta + offset = self.Offset + fdbin[offset:offset+sizeof(tehdr)] = bytearray(tehdr) + + return count + +def ShowFspInfo (fspfile): + fd = FirmwareDevice(0, fspfile) + fd.ParseFd () + fd.ParseFsp () + + print ("\nFound the following %d Firmware Volumes in FSP binary:" % (len(fd.FvList))) + for idx, fv in enumerate(fd.FvList): + name = fv.FvExtHdr.FvName + if not name: + name = '\xff' * 16 + else: + name = str(bytearray(name)) + guid = uuid.UUID(bytes = name) + print ("FV%d:" % idx) + print (" GUID : %s" % str(guid).upper()) + print (" Offset : 0x%08X" % fv.Offset) + print (" Length : 0x%08X" % fv.FvHdr.FvLength) + print ("\n") + + for fsp in fd.FspList: + fvlist = map(lambda x : 'FV%d' % x, fsp.FvIdxList) + print ("FSP_%s contains %s" % (fsp.Type, ','.join(fvlist))) + print ("%s" % (OutputStruct(fsp.Fih, 0, fsp.Fih.HeaderLength))) + +def GenFspHdr (fspfile, outdir, hfile): + fd = FirmwareDevice(0, fspfile) + fd.ParseFd () + fd.ParseFsp () + + if not hfile: + hfile = os.path.splitext(os.path.basename(fspfile))[0] + '.h' + fspname, ext = os.path.splitext(os.path.basename(hfile)) + filename = os.path.join(outdir, fspname + ext) + hfsp = open(filename, 'w') + hfsp.write ('%s\n\n' % CopyRightHeaderFile) + + firstfv = True + for fsp in fd.FspList: + fih = fsp.Fih + if firstfv: + hfsp.write("#define FSP_IMAGE_ID 0x%016X /* '%s' */\n" % (Bytes2Val(bytearray(fih.ImageId)), fih.ImageId)) + hfsp.write("#define FSP_IMAGE_REV 0x%08X \n\n" % fih.ImageRevision) + firstfv = False + fv = fd.FvList[fsp.FvIdxList[0]] + hfsp.write ('#define FSP%s_BASE 0x%08X\n' % (fsp.Type, fih.ImageBase)) + hfsp.write ('#define FSP%s_OFFSET 0x%08X\n' % (fsp.Type, fv.Offset)) + hfsp.write ('#define FSP%s_LENGTH 0x%08X\n\n' % (fsp.Type, fih.ImageSize)) + + hfsp.close() + +def SplitFspBin (fspfile, outdir, nametemplate): + fd = FirmwareDevice(0, fspfile) + fd.ParseFd () + fd.ParseFsp () + + for fsp in fd.FspList: + ftype = fsp.Type + if not nametemplate: + nametemplate = fspfile + fspname, ext = os.path.splitext(os.path.basename(nametemplate)) + filename = os.path.join(outdir, fspname + '_' + fsp.Type + ext) + hfsp = open(filename, 'wb') + print ("Ceate FSP component file '%s'" % filename) + for fvidx in fsp.FvIdxList: + fv = fd.FvList[fvidx] + hfsp.write(fv.FvData) + hfsp.close() + +def RebaseFspBin (FspBinary, FspComponent, FspBase, OutputDir, OutputFile): + fd = FirmwareDevice(0, FspBinary) + fd.ParseFd () + fd.ParseFsp () + + numcomp = len(FspComponent) + baselist = FspBase + if numcomp != len(baselist): + print "ERROR: Required number of base does not match number of FSP component !" + return + + newfspbin = fd.FdData[:] + + for idx, fspcomp in enumerate(FspComponent): + + found = False + for fsp in fd.FspList: + ftype = fsp.Type.lower() + if ftype == fspcomp: + found = True + break + + if not found: + print "ERROR: Could not find FSP_%c component to rebase !" % fspcomp.upper() + return + + fspbase = baselist[idx] + if fspbase.startswith('0x'): + newbase = int(fspbase, 16) + else: + newbase = int(fspbase) + oldbase = fsp.Fih.ImageBase + delta = newbase - oldbase + print "Rebase FSP-%c from 0x%08X to 0x%08X:" % (ftype.upper(),oldbase,newbase) + + telist = [] + for fvidx in fsp.FvIdxList: + fv = fd.FvList[fvidx] + for ffs in fv.FfsList: + for sec in ffs.SecList: + if sec.SecHdr.Type == EFI_SECTION_TYPE.TE: # TE + offset = fd.Offset + fv.Offset + ffs.Offset + sec.Offset + sizeof(sec.SecHdr) + telist.append ((offset, len(sec.SecData) - sizeof(sec.SecHdr))) + elif sec.SecHdr.Type == EFI_SECTION_TYPE.PE32: # PE + raise Exception("ERROR: PE32 Section is not supported !") + + fcount = 0 + tecount = 0 + for (teoffset, telen) in telist: + tehdr = EFI_TE_IMAGE_HEADER.from_buffer (fd.FdData, teoffset) + if 'VZ' != tehdr.Signature: + raise Exception("ERROR: Invalid TE header !") + te = TeImage(teoffset, fd.FdData[teoffset:teoffset + telen]) + te.ParseReloc() + tecount += te.Rebase(delta, newfspbin) + fcount += 1 + print " Patched %d entries in %d TE images." % (tecount, fcount) + + (count, applied) = fsp.Patch(delta, newfspbin) + print " Patched %d entries using FSP patch table." % applied + if count != applied: + print " %d invalid entries are ignored !" % (count - applied) + + if OutputFile == '': + filename = os.path.basename(FspBinary) + base, ext = os.path.splitext(filename) + OutputFile = base + "_%08X" % newbase + ext + + fspname, ext = os.path.splitext(os.path.basename(OutputFile)) + filename = os.path.join(OutputDir, fspname + ext) + fd = open(filename, "wb") + fd.write(newfspbin) + fd.close() + +def main (): + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(title='commands') + + parser_rebase = subparsers.add_parser('rebase', help='rebase a FSP into a new base address') + parser_rebase.set_defaults(which='rebase') + parser_rebase.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True) + parser_rebase.add_argument('-c', '--fspcomp', choices=['t','m','s','o'], nargs='+', dest='FspComponent', type=str, help='FSP component to rebase', default = "['t']", required = True) + parser_rebase.add_argument('-b', '--newbase', dest='FspBase', nargs='+', type=str, help='Rebased FSP binary file name', default = '', required = True) + parser_rebase.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.') + parser_rebase.add_argument('-n', '--outfile', dest='OutputFile', type=str, help='Rebased FSP binary file name', default = '') + + parser_split = subparsers.add_parser('split', help='split a FSP into multiple components') + parser_split.set_defaults(which='split') + parser_split.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True) + parser_split.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.') + parser_split.add_argument('-n', '--nametpl', dest='NameTemplate', type=str, help='Output name template', default = '') + + parser_genhdr = subparsers.add_parser('genhdr', help='generate a header file for FSP binary') + parser_genhdr.set_defaults(which='genhdr') + parser_genhdr.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True) + parser_genhdr.add_argument('-o', '--outdir' , dest='OutputDir', type=str, help='Output directory path', default = '.') + parser_genhdr.add_argument('-n', '--hfile', dest='HFileName', type=str, help='Output header file name', default = '') + + parser_info = subparsers.add_parser('info', help='display FSP information') + parser_info.set_defaults(which='info') + parser_info.add_argument('-f', '--fspbin' , dest='FspBinary', type=str, help='FSP binary file path', required = True) + + args = parser.parse_args() + if args.which in ['rebase', 'split', 'genhdr', 'info']: + if not os.path.exists(args.FspBinary): + raise Exception ("ERROR: Could not locate FSP binary file '%s' !" % args.FspBinary) + if hasattr(args, 'OutputDir') and not os.path.exists(args.OutputDir): + raise Exception ("ERROR: Invalid output directory '%s' !" % args.OutputDir) + + if args.which == 'rebase': + RebaseFspBin (args.FspBinary, args.FspComponent, args.FspBase, args.OutputDir, args.OutputFile) + elif args.which == 'split': + SplitFspBin (args.FspBinary, args.OutputDir, args.NameTemplate) + elif args.which == 'genhdr': + GenFspHdr (args.FspBinary, args.OutputDir, args.HFileName) + elif args.which == 'info': + ShowFspInfo (args.FspBinary) + else: + pass + + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/Core/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.docx b/Core/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.docx new file mode 100644 index 0000000000..c8766d5775 Binary files /dev/null and b/Core/IntelFsp2Pkg/Tools/UserManuals/GenCfgOptUserManual.docx differ diff --git a/Core/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.docx b/Core/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.docx new file mode 100644 index 0000000000..ab1eda993e Binary files /dev/null and b/Core/IntelFsp2Pkg/Tools/UserManuals/PatchFvUserManual.docx differ diff --git a/Core/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md b/Core/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md new file mode 100644 index 0000000000..064e0ac845 --- /dev/null +++ b/Core/IntelFsp2Pkg/Tools/UserManuals/SplitFspBinUserManual.md @@ -0,0 +1,69 @@ +# SplitFspBin.py is a python script to support some operations on Intel FSP 2.0 image. + +It supports: + +- Split Intel FSP 2.0 image into individual FSP-T/M/S/O component + +- Rebase Intel FSP 2.0 components to different base addresses + +- Generate Intel FSP 2.0 C header file + +- Display Intel FSP 2.0 information header for each FSP component + +## Split Intel FSP 2.0 image + +To split individual FSP component in Intel FSP 2.0 image, the following +command can be used: + + **python SplitFspBin.py split [-h] -f FSPBINARY [-o OUTPUTDIR] [-n NAMETEMPLATE]** + +For example: + + `python SplitFspBin.py split -f FSP.bin` + + It will create FSP_T.bin, FSP_M.bin and FSP_S.bin in current directory. + +## Rebase Intel FSP 2.0 components + +To rebase one or multiple FSP components in Intel FSP 2.0 image, the following +command can be used: + + **python SplitFspBin.py rebase [-h] -f FSPBINARY -c {t,m,s,o} [{t,m,s,o} ...] -b FSPBASE [FSPBASE ...] [-o OUTPUTDIR] [-n OUTPUTFILE]** + +For example: + + `python SplitFspBin.py rebase -f FSP.bin –c t –b 0xFFF00000 –n FSP_new.bin` + + It will rebase FSP-T component inside FSP.bin to new base 0xFFF00000 and save the + rebased Intel FSP 2.0 image into file FSP_new.bin. + + `python SplitFspBin.py rebase -f FSP.bin –c t m –b 0xFFF00000 0xFEF80000 –n FSP_new.bin` + + It will rebase FSP-T and FSP-M components inside FSP.bin to new base 0xFFF00000 + and 0xFEF80000 respectively, and save the rebased Intel FSP 2.0 image into file + FSP_new.bin file. + +## Generate Intel FSP 2.0 C header file + +To generate Intel FSP 2.0 C header file, the following command can be used: + + **Python SplitFspBin.py genhdr [-h] -f FSPBINARY [-o OUTPUTDIR] [-n HFILENAME]** + +For example: + + `python SplitFspBin.py genhdr -f FSP.bin –n FSP.h` + + It will create the C header file FSP.h containing the image ID, revision, offset + and size for each individual FSP component. + +## Display Intel FSP 2.0 information header + +To display Intel FSP 2.0 information headers, the following command can be used: + + **Python SplitFspBin.py info [-h] -f FSPBINARY** + +For example: + + `python SplitFspBin.py info -f FSP.bin` + + It will print out the FSP information header for each FSP component. -- cgit v1.2.3