From nobody Mon Sep 16 19:55:59 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+114075+1787277+3901457@groups.io; arc=fail (BodyHash is different from the expected one) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1705676275133813.8885827828165; Fri, 19 Jan 2024 06:57:55 -0800 (PST) Return-Path: DKIM-Signature: a=rsa-sha256; bh=c+qlE/4AnVZxTylBqVwUyWy5vzxUOCgOTJovAHoWMlU=; c=relaxed/simple; d=groups.io; h=ARC-Seal:ARC-Message-Signature:ARC-Authentication-Results:Received-SPF:From:To:CC:Subject:Date:Message-ID:In-Reply-To:References:MIME-Version:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Transfer-Encoding:Content-Type; s=20140610; t=1705676274; v=1; b=FxobvYKhH0uSIyf+UcuhDkiy3O/zFY0eQMIcWn4hkEr2KRfqUXNg5yeDMxNOs55UKtUm2vod 1w1iNiwTPunOaUL7VfMnZgZevrc//+4ODbzJT+pQ23Ed4Nf+UlD6PaeidatMZs/c4zn5vt0Hyng hg+eFXlhe+eKGe7pjVtgUahA= X-Received: by 127.0.0.2 with SMTP id PtoQYY1788612xHfKPr8E6WV; Fri, 19 Jan 2024 06:57:54 -0800 X-Received: from NAM11-DM6-obe.outbound.protection.outlook.com (NAM11-DM6-obe.outbound.protection.outlook.com [40.107.223.49]) by mx.groups.io with SMTP id smtpd.web11.5912.1705560770354008850 for ; Wed, 17 Jan 2024 22:52:50 -0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=KqdwzJDZTabSpXwJKpetgs4insNYD85A4Dc8sV/e/Mvj0djh6PjrvV7ZySQUtTcUXi9DZOwd7pIkwrtc1Sv5tfbmsOCiqKHFz9QQnAGWfYLVUpPCxuLIjlPR4hp1RawRBEfTpuluX75HxOHbco6OUo1Y22s30trrMJfftafHY5+bQPrSq0KJNHASB8438jCR38zINKgodfZmqz8afaWQoPIgFwNrVRFfOKjYCacTfjpmhPnaNS8yBDe9x12y3iZvR10NRH1NHNAlmF13Nh0RKK2AGHC+gRiqYc87g+ucFfyT3LJ2ZIjDoNVZR/EaaeILyfCjIYjfUoVQC0d/MlZPQA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=TIKUfA3J6s3vEGNLkj17naWpqUXJVIfuDLZw8m7PkMo=; b=HP6q8Wq0Yd3SNANQ8INHZpk1ck6AckKqLQxA+itI3GZ5g+ivs25UxfCRfLsCJtoTmn6I8jNIKrLLJqt9edr1QBlPhwQni51mIn2x92VXWL2ulJrSffbRDvU1C8DKSIWCR4bmYkiqSGvqqqUicRsCcwomV+XpwuwAxUnTjDocuJU/BxshtR8RSzzlVnmJ6Ae6zu1kJq8aPpKFvBHto1o0EG5J3MyM811I6KWXUkf7hg2+sXrkkxU8j2vC/rMg8TahGdJIl6+RQpYk5oXjl5qgSVqqF/stEbGfhwvv4+RYIL61swPAUXPGyaevEUK7qbVnJUu1EHDiEziLmmla+xMXQQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) X-Received: from BYAPR08CA0020.namprd08.prod.outlook.com (2603:10b6:a03:100::33) by MN0PR12MB6174.namprd12.prod.outlook.com (2603:10b6:208:3c5::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7202.23; Thu, 18 Jan 2024 06:52:45 +0000 X-Received: from CO1PEPF000044F5.namprd05.prod.outlook.com (2603:10b6:a03:100:cafe::ed) by BYAPR08CA0020.outlook.office365.com (2603:10b6:a03:100::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7202.23 via Frontend Transport; Thu, 18 Jan 2024 06:52:44 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+114075+1787277+3901457@groups.io; helo=mail02.groups.io; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB03.amd.com; pr=C X-Received: from SATLEXMB03.amd.com (165.204.84.17) by CO1PEPF000044F5.mail.protection.outlook.com (10.167.241.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7202.16 via Frontend Transport; Thu, 18 Jan 2024 06:52:44 +0000 X-Received: from SATLEXMB06.amd.com (10.181.40.147) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Thu, 18 Jan 2024 00:52:41 -0600 X-Received: from SATLEXMB03.amd.com (10.181.40.144) by SATLEXMB06.amd.com (10.181.40.147) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.34; Thu, 18 Jan 2024 00:52:37 -0600 X-Received: from SHA-LX-MINGXZHA.amd.com (10.180.168.240) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server id 15.1.2507.34 via Frontend Transport; Thu, 18 Jan 2024 00:52:36 -0600 From: "duke.zhai via groups.io" To: CC: Eric Xing , Duke Zhai , Igniculus Fu , Abner Chang Subject: [edk2-devel] [PATCH 25/33] AMD/VanGoghBoard: Check in PlatformInitPei module. Date: Thu, 18 Jan 2024 14:50:38 +0800 Message-ID: <20240118065046.961-26-duke.zhai@amd.com> In-Reply-To: <20240118065046.961-1-duke.zhai@amd.com> References: <20240118065046.961-1-duke.zhai@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000044F5:EE_|MN0PR12MB6174:EE_ X-MS-Office365-Filtering-Correlation-Id: 30db42d7-d74a-4526-70c3-08dc17f212e2 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Message-Info: vCMeb2A74pGcMwyf5xNIC037eAJit6okIF4oEpNiH8G0CnJaTmcESrIF42+Or7YAG3RWrKtfBNXE3w8sdj7C8MPKOEubDpJXvIPXdvL48pXWdxnR1RZ8I2vIlf5GlFn4f5/fyzNnioDnWhdiPj5bmuSy6ZsMeSaY0mda9KlEGyLkRMp8fbWZaYnG5f+rHk9JDHoJGs34W5Mx0F7u79aqN+pDG7RzJg8wQtWmXfdEitRtMYhL8qfX93qXuNVMVDDDCYi0y0RVqd70c62MCkeuWo61J1L8bzyWQvSgUDaOw7aELTPsHeqeVIWPk/wDEX79FusmoUWIZFwdfuHqOeuIRpDjn55RsJ3/WEfwX5xBBbau9xZwFfDfaK2AyoKLEqeagVzL6PMlnxXK7WlhSJwjYnCmLLxQ+psWV5Bn/XEQCTdkBK/KwlXoJhEO+GYTx4ev7b2KmswomXK8znwEIEHkOnd6J7jdiM7uXMxOT6fWTMJFTc0+uHdQDnL6UrtJwz3++WvFNAPzboENKf7mIhuACn3TCoH8JEFsk88zE6YCwP7c0AgAAsSO5nqqp2d5sd8F7mSoSa5vImcyqwbnp0UvQ2QQ7OsTHIxZukKEXwyl/Qx8F8iaJwtnTbuO94zehgSFfxO8TNC61lKt4wSjYqf0fXmHNGnwFkdPyATpQVm75fNq6tXLDMaN9kT742JyVmMoxXUxgR9iDgeHmQyuvcrFA7mt9gCqefOnkyAND/GDx1mRWEtwKnu9yvzN3sxCMUJRqmUTLoHFXv0AsHCHHhIYgw== X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jan 2024 06:52:44.4715 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 30db42d7-d74a-4526-70c3-08dc17f212e2 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[SATLEXMB03.amd.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000044F5.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN0PR12MB6174 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,duke.zhai@amd.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: AofMLv6SBgSr8BYpOeD20jzox1787277AA= Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1705676277002100039 Content-Type: text/plain; charset="utf-8" From: Duke Zhai BZ #:4640 Initial PlatformInitPei module. This is the Platform module to initialize whole platform on PEI phase. Signed-off-by: Ken Yao Cc: Eric Xing Cc: Duke Zhai Cc: Igniculus Fu Cc: Abner Chang --- .../Universal/PlatformInitPei/BootMode.c | 287 ++++++ .../Universal/PlatformInitPei/CommonHeader.h | 244 +++++ .../PlatformInitPei/MemoryCallback.c | 308 ++++++ .../Universal/PlatformInitPei/MemoryInstall.c | 953 ++++++++++++++++++ .../Universal/PlatformInitPei/MemoryInstall.h | 229 +++++ .../Universal/PlatformInitPei/MemoryPeim.c | 385 +++++++ .../Universal/PlatformInitPei/PlatformInit.c | 176 ++++ .../PlatformInitPei/PlatformInit.inf | 114 +++ .../Universal/PlatformInitPei/Stall.c | 122 +++ 9 files changed, 2818 insertions(+) create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Boo= tMode.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Com= monHeader.h create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Mem= oryCallback.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Mem= oryInstall.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Mem= oryInstall.h create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Mem= oryPeim.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Pla= tformInit.c create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Pla= tformInit.inf create mode 100644 Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Sta= ll.c diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/BootMode.c= b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/BootMode.c new file mode 100644 index 0000000000..9102ae2b86 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/BootMode.c @@ -0,0 +1,287 @@ +/** @file + Implements BootMode.C + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file +This file provide the function to detect boot mode + +Copyright (c) 2013 Intel Corporation. + +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 IMPLI= ED. + +**/ + +#include "CommonHeader.h" + +EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode =3D { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiBootInRecoveryModePpiGuid, + NULL +}; +STATIC EFI_PEI_PPI_DESCRIPTOR CapsulePpi =3D { + EFI_PEI_PPI_DESCRIPTOR_PPI|EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gCapsuleUpdateDetectedPpiGuid, + NULL +}; + +/** + +Routine Description: + + This function is used to verify if the FV header is validate. + + @param FwVolHeader - The FV header that to be verified. + + @retval EFI_SUCCESS - The Fv header is valid. + @retval EFI_NOT_FOUND - The Fv header is invalid. + +**/ +EFI_STATUS +ValidateFvHeader ( + EFI_BOOT_MODE *BootMode + ) +{ + UINT16 *Ptr; + UINT16 HeaderLength; + UINT16 Checksum; + + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + if (BOOT_IN_RECOVERY_MODE =3D=3D *BootMode) { + DEBUG ((EFI_D_INFO, "Boot mode recovery\n")); + return EFI_SUCCESS; + } + + // + // Let's check whether FvMain header is valid, if not enter into recover= y mode + // + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdFlashF= vMainBase); + if ((FwVolHeader->Revision !=3D EFI_FVH_REVISION) || + (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength =3D=3D ((UINT64)-1)) || + ((FwVolHeader->HeaderLength & 0x01) !=3D 0) + ) + { + return EFI_NOT_FOUND; + } + + // + // Verify the header checksum + // + HeaderLength =3D (UINT16)(FwVolHeader->HeaderLength / 2); + Ptr =3D (UINT16 *)FwVolHeader; + Checksum =3D 0; + while (HeaderLength > 0) { + Checksum =3D Checksum +*Ptr; + Ptr++; + HeaderLength--; + } + + if (Checksum !=3D 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Peform the boot mode determination logic + + @param PeiServices General purpose services available to every PEIM. + + @param BootMode The detected boot mode. + + @retval EFI_SUCCESS if the boot mode could be set +**/ +EFI_STATUS +UpdateBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +{ + EFI_STATUS Status; + UINT16 SleepType; + CHAR16 *strBootMode; + EFI_BOOT_MODE NewBootMode; + EFI_PEI_CAPSULE_PPI *Capsule; + BOOLEAN IsFirstBoot; + + // + // Let's assume things are OK if not told otherwise + // + NewBootMode =3D BOOT_WITH_FULL_CONFIGURATION; + + // + // When this boot is WDT reset, the system needs booting with CrashDump = function eanbled. + // Check Power Button, click the power button, the system will boot in f= ast boot mode, + // if it is pressed and hold for a second, it will boot in FullConfigura= tion/setup mode. + // + IsFirstBoot =3D PcdGetBool (PcdBootState); + + if (!IsFirstBoot) { + NewBootMode =3D BOOT_WITH_MINIMAL_CONFIGURATION; + } + + // + // Check if we need to boot in forced recovery mode + // + if (ValidateFvHeader (&NewBootMode) !=3D EFI_SUCCESS) { + NewBootMode =3D BOOT_IN_RECOVERY_MODE; + DEBUG ((EFI_D_ERROR, "RECOVERY from corrupt FV\n")); + } + + if (NewBootMode =3D=3D BOOT_IN_RECOVERY_MODE) { + Status =3D (*PeiServices)->InstallPpi ( + PeiServices, + &mPpiListRecoveryBootMode + ); + ASSERT_EFI_ERROR (Status); + } else { + if (GetSleepTypeAfterWakeup (PeiServices, &SleepType)) { + switch (SleepType) { + case V_SLP_TYPE_S3: + NewBootMode =3D BOOT_ON_S3_RESUME; + break; + + case V_SLP_TYPE_S4: + NewBootMode =3D BOOT_ON_S4_RESUME; + break; + + case V_SLP_TYPE_S5: + NewBootMode =3D BOOT_ON_S5_RESUME; + break; + } // switch (SleepType) + } + + // + // Determine if we're in capsule update mode + // + Status =3D (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiCapsulePpiGuid, + 0, + NULL, + (void **)&Capsule + ); + + if (Status =3D=3D EFI_SUCCESS) { + if (Capsule->CheckCapsuleUpdate ((EFI_PEI_SERVICES **)PeiServices) = =3D=3D EFI_SUCCESS) { + NewBootMode =3D BOOT_ON_FLASH_UPDATE; + DEBUG ((EFI_D_ERROR, "Setting BootMode to %x\n", BOOT_ON_FLASH_UPD= ATE)); + + (*PeiServices)->InstallPpi (PeiServices, &CapsulePpi); + } + } + + // + // Check for Safe Mode + // + } + + switch (NewBootMode) { + case BOOT_WITH_FULL_CONFIGURATION: + strBootMode =3D L"BOOT_WITH_FULL_CONFIGURATION"; + break; + case BOOT_WITH_MINIMAL_CONFIGURATION: + strBootMode =3D L"BOOT_WITH_MINIMAL_CONFIGURATION"; + break; + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + strBootMode =3D L"BOOT_ASSUMING_NO_CONFIGURATION_CHANGES"; + break; + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + strBootMode =3D L"BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS"; + break; + case BOOT_WITH_DEFAULT_SETTINGS: + strBootMode =3D L"BOOT_WITH_DEFAULT_SETTINGS"; + break; + case BOOT_ON_S4_RESUME: + strBootMode =3D L"BOOT_ON_S4_RESUME"; + break; + case BOOT_ON_S5_RESUME: + strBootMode =3D L"BOOT_ON_S5_RESUME"; + break; + case BOOT_ON_S2_RESUME: + strBootMode =3D L"BOOT_ON_S2_RESUME"; + break; + case BOOT_ON_S3_RESUME: + strBootMode =3D L"BOOT_ON_S3_RESUME"; + break; + case BOOT_ON_FLASH_UPDATE: + strBootMode =3D L"BOOT_ON_FLASH_UPDATE"; + break; + case BOOT_IN_RECOVERY_MODE: + strBootMode =3D L"BOOT_IN_RECOVERY_MODE"; + break; + default: + strBootMode =3D L"Unknown boot mode"; + } // switch (BootMode) + + DEBUG ((EFI_D_INFO, "Setting BootMode to %s\n", strBootMode)); + Status =3D (*PeiServices)->SetBootMode ( + PeiServices, + NewBootMode + ); + ASSERT_EFI_ERROR (Status); + + *BootMode =3D NewBootMode; + + return Status; +} + +/** + Get sleep type after wakeup + + @param PeiServices Pointer to the PEI Service Table. + @param SleepType Sleep type to be returned. + + @retval TRUE A wake event occured without power failure. + @retval FALSE Power failure occured or not a wakeup. + +**/ +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ) + +{ + UINTN AcpiPm1CntBlk; + UINT16 Pm1Cnt; + + AcpiPm1CntBlk =3D MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG= 62); + + Pm1Cnt =3D IoRead16 (AcpiPm1CntBlk); + // + // check power failur/loss when in S3 resume type. + // Get sleep type if a wake event occurred and there is no power failure + // + if ((Pm1Cnt & B_SLP_TYPE) =3D=3D V_SLP_TYPE_S3) { + *SleepType =3D Pm1Cnt & B_SLP_TYPE; + return TRUE; + } else if ((Pm1Cnt & B_SLP_TYPE) =3D=3D V_SLP_TYPE_S4) { + *SleepType =3D Pm1Cnt & B_SLP_TYPE; + return TRUE; + } + + *SleepType =3D 0; + Pm1Cnt &=3D (~B_SLP_TYPE); + IoWrite16 (AcpiPm1CntBlk, Pm1Cnt); + return FALSE; +} diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/CommonHead= er.h b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/CommonHeader.h new file mode 100644 index 0000000000..ffc53cec00 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/CommonHeader.h @@ -0,0 +1,244 @@ +/** @file + Implements CommonHeader.h + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file +Common header file shared by all source files. + +This file includes package header files, library classes and protocol, PPI= & GUID definitions. + +Copyright (c) 2013 - 2016 Intel Corporation. + +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 IMPLI= ED. +**/ + +#ifndef __COMMON_HEADER_H_ +#define __COMMON_HEADER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "MemoryInstall.h" + +#define B_SLP_TYPE (BIT10 + BIT11 + BIT12) +#define V_SLP_TYPE_S0 (0 << 10) +#define V_SLP_TYPE_S1 (1 << 10) +#define V_SLP_TYPE_S3 (3 << 10) +#define V_SLP_TYPE_S4 (4 << 10) +#define V_SLP_TYPE_S5 (5 << 10) +#define B_ACPI_SLP_EN BIT13 +#define V_ACPI_SLP_EN BIT13 +#define SPI_BASE 0xFEC10000ul +#define EFI_CPUID_EXTENDED_FUNCTION 0x80000000 +#define EFI_CPUID_VIRT_PHYS_ADDRESS_SIZE 0x80000008 + +#define ACPI_MMIO_BASE 0xFED80000ul +#define SMI_BASE 0x200 // DWORD +#define FCH_PMIOA_REG60 0x60 // AcpiPm1EvtBlk +#define FCH_PMIOA_REG62 0x62 // AcpiPm1CntBlk +#define FCH_PMIOA_REG64 0x64 // AcpiPmTmrBlk +#define PMIO_BASE 0x300 // DWORD +#define FCH_SMI_REGA0 0xA0 +#define FCH_SMI_REGC4 0xC4 +#define R_FCH_ACPI_PM_CONTROL 0x04 + +/** + + This function set different memory range cache attribute. + + @param PeiServices Pointer to the PEI Service Table. + +**/ +EFI_STATUS +EFIAPI +SetPeiCacheMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ); + +/** + + Waits for at least the given number of microseconds. + + @param PeiServices General purpose services available to every PEIM. + @param This PPI instance structure. + @param Microseconds Desired length of time to wait. + + @retval EFI_SUCCESS If the desired amount of time was passed. + +*/ +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ); + +/** + Peform the boot mode determination logic + + @param PeiServices General purpose services available to every PEIM. + + @param BootMode The detected boot mode. + + @retval EFI_SUCCESS if the boot mode could be set +**/ +EFI_STATUS +EFIAPI +UpdateBootMode ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE *BootMode + ); + +/** + + This function returns the different avaiable memory length. + + @param PeiServices Pointer to the PEI Service Table. + @param LowMemoryLength Avaiable memory length below 4G address. + @param HighMemoryLength Avaiable memory length above 4G address. + @param GraphicMemoryBase Avaiable UMA base address. + @param GraphicMemoryLength Avaiable UMA length. + + @retval LowMemoryLength Avaiable memory length below 4G address. + @retval HighMemoryLength Avaiable memory length above 4G address. + @retval GraphicMemoryBase Avaiable UMA base address. + @retval GraphicMemoryLength Avaiable UMA length. + +**/ +EFI_STATUS +GetMemorySize ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT64 *LowMemoryLength, + OUT UINT64 *HighMemoryLength, + OUT UINT64 *GraphicMemoryBase OPTIONAL, + OUT UINT64 *GraphicMemoryLength OPTIONAL + ); + +/** + + This function returns the memory ranges to be enabled, along with inform= ation + describing how the range should be used. + + @param MemoryMap Buffer to record details of the memory ranges. + @param NumRanges On input, this contains the maximum number of memo= ry ranges that can be described + in the MemoryMap buffer. + + @retval MemoryMap The buffer will be filled in + @retval NumRanges will contain the actual number of memory ranges th= at are to be anabled. + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetAvailableMemoryRanges ( + IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap, + IN OUT UINT8 *NumRanges + ); + +/** + + This function returns the memory ranges to be reserved, along with infor= mation + describing how the range should be used. + + @param MemoryMap Buffer to record details of the memory ranges. + @param NumRanges On input, this contains the maximum number of memo= ry ranges that can be described + in the MemoryMap buffer. + + @retval MemoryMap The buffer will be filled in + @retval NumRanges will contain the actual number of memory ranges th= at are to be reserved. + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetReservedMemoryRanges ( + IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap, + IN OUT UINT8 *NumRanges + ); + +/** + + Callback function after Memory discovered. + + @param PeiServices PEI Services table. + @param NotifyDescriptor Notify Descriptor. + @param Ppi Ppi + + @return EFI_STATUS If the function completed successfully. + +**/ +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + + Callback function after Memory Info Hob Installed. + + @param PeiServices PEI Services table. + @param NotifyDescriptor Notify Descriptor. + @param Ppi Ppi + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +MemoryInfoHobPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +/** + Get sleep type after wakeup + + @param PeiServices Pointer to the PEI Service Table. + @param SleepType Sleep type to be returned. + + @retval TRUE A wake event occured without power failure. + @retval FALSE Power failure occured or not a wakeup. + +**/ +BOOLEAN +GetSleepTypeAfterWakeup ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT16 *SleepType + ); + +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryCall= back.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryCallback= .c new file mode 100644 index 0000000000..9ab78b7135 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryCallback.c @@ -0,0 +1,308 @@ +/** @file + Implements MemoryCallback.C + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file +This file includes a memory call back function notified when MRC is done, +following action is performed in this file, + 1. ICH initialization after MRC. + 2. SIO initialization. + 3. Install ResetSystem and FinvFv PPI. + 4. Set MTRR for PEI + 5. Create FV HOB and Flash HOB + +Copyright (c) 2013 - 2016, Intel Corporation. + +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 IMPLI= ED. + +**/ + +#include "CommonHeader.h" +#include + +EFI_STATUS +EFIAPI +S3PostScriptTableCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +EFI_STATUS +EFIAPI +S3EndOfPeiSignalCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnS3ResumeList[] =3D { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + &gPeiPostScriptTablePpiGuid, + S3PostScriptTableCallback + }, + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMI= NATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + S3EndOfPeiSignalCallback + } +}; + +/** + + Trigger the S3 PostScriptTable notify SW SMI + + @param PeiServices PEI Services table. + @param NotifyDescriptor Notify Descriptor. + @param Ppi Ppi + + @return EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +EFIAPI +S3PostScriptTableCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + PEI_SMM_CONTROL_PPI *SmmControl; + UINT16 SmiCommand; + UINTN SmiCommandSize; + + Status =3D PeiServicesLocatePpi ( + &gPeiSmmControlPpiGuid, + 0, + NULL, + (VOID **)&SmmControl + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "PeiServicesLocatePpi gPeiSmmControlPpiGuid: %r \= n", Status)); + return Status; + } + + SmiCommand =3D PcdGet8 (PcdFchOemBeforePciRestoreSwSmi); + DEBUG ((EFI_D_INFO, "Trigger SW SMI PcdFchOemBeforePciRestoreSwSmi: 0x%X= \n", SmiCommand)); + SmiCommandSize =3D sizeof (SmiCommand); + Status =3D SmmControl->Trigger ( + (EFI_PEI_SERVICES **)GetPeiServicesTableP= ointer (), + SmmControl, + (INT8 *)&SmiCommand, + &SmiCommandSize, + FALSE, + 0 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +/** + + Trigger the S3 EndOfPeiSignal notify SW SMI + + @param PeiServices PEI Services table. + @param NotifyDescriptor Notify Descriptor. + @param Ppi Ppi + + @return EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +EFIAPI +S3EndOfPeiSignalCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + PEI_SMM_CONTROL_PPI *SmmControl; + UINT16 SmiCommand; + UINTN SmiCommandSize; + + Status =3D PeiServicesLocatePpi ( + &gPeiSmmControlPpiGuid, + 0, + NULL, + (VOID **)&SmmControl + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "PeiServicesLocatePpi gPeiSmmControlPpiGuid: %r \= n", Status)); + return Status; + } + + SmiCommand =3D PcdGet8 (AcpiRestoreSwSmi); + DEBUG ((EFI_D_INFO, "Trigger SW SMI AcpiRestoreSwSmi: 0x%X\n", SmiComman= d)); + SmiCommandSize =3D sizeof (SmiCommand); + Status =3D SmmControl->Trigger ( + (EFI_PEI_SERVICES **)GetPeiServicesTableP= ointer (), + SmmControl, + (INT8 *)&SmiCommand, + &SmiCommandSize, + FALSE, + 0 + ); + ASSERT_EFI_ERROR (Status); + + SmiCommand =3D PcdGet8 (PcdFchOemAfterPciRestoreSwSmi); + DEBUG ((EFI_D_INFO, "Trigger SW SMI PcdFchOemAfterPciRestoreSwSmi: 0x%X\= n", SmiCommand)); + SmiCommandSize =3D sizeof (SmiCommand); + Status =3D SmmControl->Trigger ( + (EFI_PEI_SERVICES **)GetPeiServicesTableP= ointer (), + SmmControl, + (INT8 *)&SmiCommand, + &SmiCommandSize, + FALSE, + 0 + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + + Callback function after Memory discovered. + + @param PeiServices PEI Services table. + @param NotifyDescriptor Notify Descriptor. + @param Ppi Ppi + + @return EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + UINT8 CpuAddressWidth; + UINT32 RegEax; + + #ifndef FV_RECOVERY_MAIN_COMBINE_SUPPORT + UINT32 Pages; + VOID *Memory; + #endif + + // + // Get boot mode + // + Status =3D PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR (Status); + + if (BootMode =3D=3D BOOT_ON_S3_RESUME) { + Status =3D PeiServicesNotifyPpi (&mNotifyOnS3ResumeList[0]); + ASSERT_EFI_ERROR (Status); + } + + if (PcdGet8 (PcdFspModeSelection) =3D=3D 0) { + // Dispatch Mode + SetPeiCacheMode ((const struct _EFI_PEI_SERVICES **)PeiServices); + } + + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED |= EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + SPI_BASE, + 0x1000 + ); + + // + // Local APIC + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED |= EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + PcdGet32 (PcdCpuLocalApicBaseAddress), + 0x1000 + ); + + // + // IO APIC + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED |= EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + PcdGet32 (PcdIoApicBaseAddress), + 0x1000 + ); + + AsmCpuid (0x80000001, &RegEax, NULL, NULL, NULL); + if (((RegEax >> 20) & 0xFF) =3D=3D 0x8) { + // For F17: Reserved memory from BootFvBase - (BootFvBase+BootFvSize-1) + DEBUG ((EFI_D_INFO, "Family 17: Reserved memory for BFV\n")); + BuildMemoryAllocationHob ( + PcdGet32 (PcdMemoryFvRecoveryBase), + PcdGet32 (PcdFlashFvRecoverySize), + EfiReservedMemoryType + ); + } + + DEBUG ((EFI_D_INFO, "PcdMemoryFvRecoveryBase: %x,PcdFlashFvMainBase: %x\= n", PcdGet32 (PcdMemoryFvRecoveryBase), PcdGet32 (PcdFlashFvMainBase))); + + if ((BootMode !=3D BOOT_ON_S3_RESUME) && (BootMode !=3D BOOT_IN_RECOVERY= _MODE)) { + #ifndef FV_RECOVERY_MAIN_COMBINE_SUPPORT + Pages =3D PcdGet32 (PcdFlashFvMainSize)/0x1000; + Memory =3D AllocatePages (Pages); + CopyMem (Memory, (VOID *)PcdGet32 (PcdFlashFvMainBase), PcdGet32 (PcdF= lashFvMainSize)); + #endif + // + // DXE FV + // + PeiServicesInstallFvInfoPpi ( + NULL, + #ifdef FV_RECOVERY_MAIN_COMBINE_SUPPORT + (VOID *)PcdGet32 (PcdFlashFvMainBase), + #else + (VOID *)Memory, + #endif + PcdGet32 (PcdFlashFvMainSize), + NULL, + NULL + ); + } + + // + // Adding the Flashpart to the E820 memory table as type 2 memory. + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_FIRMWARE_DEVICE, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED |= EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + FixedPcdGet32 (PcdFlashAreaBaseAddress), + FixedPcdGet32 (PcdFlashAreaSize) + ); + DEBUG ((EFI_D_INFO, "FLASH_BASE_ADDRESS : 0x%x\n", FixedPcdGet32 (PcdFla= shAreaBaseAddress))); + + // + // Create a CPU hand-off information + // + CpuAddressWidth =3D 36; + + BuildCpuHob (CpuAddressWidth, 16); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInst= all.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.c new file mode 100644 index 0000000000..f58645f2cd --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.c @@ -0,0 +1,953 @@ +/** @file + Implements MemoryInstall.C + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file +Framework PEIM to initialize memory on a Quark Memory Controller. + +Copyright (c) 2013 - 2016, Intel Corporation. + +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 IMPLI= ED. + +**/ + +#include "CommonHeader.h" + +EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] =3D { + { EfiACPIReclaimMemory, 0x80 }, + { EfiACPIMemoryNVS, 0x3000 }, + { EfiReservedMemoryType, 0x1000 }, + { EfiMemoryMappedIO, 0 }, + { EfiMemoryMappedIOPortSpace, 0 }, + { EfiPalCode, 0 }, + { EfiRuntimeServicesCode, 0x800 }, + { EfiRuntimeServicesData, 0x1000 }, + { EfiLoaderCode, 0x200 }, + { EfiLoaderData, 0 }, + { EfiBootServicesCode, 0x2000 }, + { EfiBootServicesData, 0xA000 }, + { EfiConventionalMemory, 0x0 }, + { EfiUnusableMemory, 0 }, + { EfiMaxMemoryType, 0 } +}; + +/** + + This function returns the memory ranges to be enabled, along with inform= ation + describing how the range should be used. + + @param PeiServices PEI Services Table. + @param MemoryMap Buffer to record details of the memory ranges tobe= enabled. + @param NumRanges On input, this contains the maximum number of memo= ry ranges that can be described + in the MemoryMap buffer. + + @retval MemoryMap The buffer will be filled in + @retval NumRanges will contain the actual number of memory ranges th= at are to be anabled. + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetMemoryMap ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap, + IN OUT UINT8 *NumRanges + ) +{ + EFI_PHYSICAL_ADDRESS MemorySize; + EFI_PHYSICAL_ADDRESS RowLength; + PEI_MEMORY_RANGE_SMRAM SmramMask; + PEI_MEMORY_RANGE_SMRAM TsegMask; + UINT32 BlockNum; + UINT8 ExtendedMemoryIndex; + UINT8 Index; + UINT64 SmRamTsegBase; + UINT64 SmRamTsegLength; + UINT64 SmRamTsegMask; + UINT64 LowMemoryLength; + PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE TemMemoryMap[MAX_RANGES]; + UINT8 TemNumRanges; + + if ((*NumRanges) < MAX_RANGES) { + return EFI_BUFFER_TOO_SMALL; + } + + // + // Get the Memory Map + // + TemNumRanges =3D MAX_RANGES; + LowMemoryLength =3D 0; + *NumRanges =3D 0; + ZeroMem (TemMemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * = MAX_RANGES); + + GetAvailableMemoryRanges (TemMemoryMap, &TemNumRanges); + + for (Index =3D 0; Index < TemNumRanges; Index++) { + if (TemMemoryMap[Index].CpuAddress < SIZE_4GB) { + LowMemoryLength +=3D TemMemoryMap[Index].RangeLength; + } else { + // + // Memory Map information Upper than 4G + // + MemoryMap[*NumRanges].PhysicalAddress =3D TemMemoryMap[Index].Physic= alAddress; + MemoryMap[*NumRanges].CpuAddress =3D TemMemoryMap[Index].CpuAdd= ress; + MemoryMap[*NumRanges].RangeLength =3D TemMemoryMap[Index].RangeL= ength; + MemoryMap[*NumRanges].Type =3D DualChannelDdrMainMemory; + (*NumRanges)++; + } + } + + TemNumRanges =3D MAX_RANGES; + ZeroMem (TemMemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * = MAX_RANGES); + + GetReservedMemoryRanges (TemMemoryMap, &TemNumRanges); + for (Index =3D 0; Index < TemNumRanges; Index++) { + MemoryMap[*NumRanges].PhysicalAddress =3D TemMemoryMap[Index].Physical= Address; + MemoryMap[*NumRanges].CpuAddress =3D TemMemoryMap[Index].CpuAddre= ss; + MemoryMap[*NumRanges].RangeLength =3D TemMemoryMap[Index].RangeLen= gth; + MemoryMap[*NumRanges].Type =3D DualChannelDdrReservedMemory; + (*NumRanges)++; + } + + // + // Choose regions to reserve for SMM use (AB/H SEG and TSEG). Size is in= 128K blocks + // + SmramMask =3D PEI_MR_SMRAM_ABSEG_128K_NOCACHE | PEI_MR_SMRAM_TSEG_4096K_= CACHE; + + // + // Generate Memory ranges for the memory map. + // + MemorySize =3D 0; + + RowLength =3D LowMemoryLength; + + // + // Add memory below 640KB to the memory map. Make sure memory between + // 640KB and 1MB are reserved, even if not used for SMRAM + // + MemoryMap[*NumRanges].PhysicalAddress =3D MemorySize; + MemoryMap[*NumRanges].CpuAddress =3D MemorySize; + MemoryMap[*NumRanges].RangeLength =3D 0xA0000; + MemoryMap[*NumRanges].Type =3D DualChannelDdrMainMemory; + (*NumRanges)++; + + // Reserve ABSEG or HSEG SMRAM if needed + // + if (SmramMask & (PEI_MR_SMRAM_ABSEG_MASK | PEI_MR_SMRAM_HSEG_MASK)) { + MemoryMap[*NumRanges].PhysicalAddress =3D MC_ABSEG_HSEG_PHYSICAL_START; + MemoryMap[*NumRanges].RangeLength =3D MC_ABSEG_HSEG_LENGTH; + MemoryMap[*NumRanges].CpuAddress =3D (SmramMask & PEI_MR_SMRAM_AB= SEG_MASK) ? + MC_ABSEG_CPU_START : MC_HSEG_C= PU_START; + // + // Chipset only supports cacheable SMRAM + // + MemoryMap[*NumRanges].Type =3D DualChannelDdrSmramCacheable; + } else { + // + // Just mark this range reserved + // + MemoryMap[*NumRanges].PhysicalAddress =3D 0xA0000; + MemoryMap[*NumRanges].CpuAddress =3D 0xA0000; + MemoryMap[*NumRanges].RangeLength =3D 0x60000; + MemoryMap[*NumRanges].Type =3D DualChannelDdrReservedMemory; + } + + (*NumRanges)++; + + RowLength -=3D (0x100000 - MemorySize); + MemorySize =3D 0x100000; + + // + // Add remaining memory to the memory map + // + MemoryMap[*NumRanges].PhysicalAddress =3D MemorySize; + MemoryMap[*NumRanges].CpuAddress =3D MemorySize; + MemoryMap[*NumRanges].RangeLength =3D RowLength; + MemoryMap[*NumRanges].Type =3D DualChannelDdrMainMemory; + (*NumRanges)++; + MemorySize +=3D RowLength; + + ExtendedMemoryIndex =3D (UINT8)(*NumRanges - 1); + + // See if we need to trim TSEG out of the highest memory range + // + if (SmramMask & PEI_MR_SMRAM_TSEG_MASK) { + // pcd + // + // Create the new range for TSEG and remove that range from the previo= us SdrDdrMainMemory range + // + TsegMask =3D (SmramMask & PEI_MR_SMRAM_SIZE_MASK); + + BlockNum =3D 1; + while (TsegMask) { + TsegMask >>=3D 1; + BlockNum <<=3D 1; + } + + BlockNum >>=3D 1; + + if (BlockNum) { + SmRamTsegBase =3D MemorySize; + SmRamTsegLength =3D (UINT64)(BlockNum * = 128 * 1024); + MemoryMap[*NumRanges].RangeLength =3D SmRamTsegLength; + MemorySize -=3D MemoryMap[*NumRanges= ].RangeLength; + MemoryMap[*NumRanges].PhysicalAddress =3D MemorySize; + MemoryMap[*NumRanges].CpuAddress =3D MemorySize; + MemoryMap[ExtendedMemoryIndex].RangeLength -=3D MemoryMap[*NumRanges= ].RangeLength; + + // + // Turn On Smram + // + SmRamTsegMask =3D (0x0000010000000000L-SmRamTsegLength) & 0xFFFFFFF= E0000UL; // TSegMask[47:17] + SmRamTsegMask |=3D 0x4403; = // enable both ASeg and TSeg, and both address range memory type s= et to write through + AsmWriteMsr64 (0xC0010112, SmRamTsegBase); + AsmWriteMsr64 (0xC0010113, SmRamTsegMask); // enable + } + + // + // Chipset only supports non-cacheable SMRAM + // + MemoryMap[*NumRanges].Type =3D DualChannelDdrSmramNonCacheable; + + (*NumRanges)++; + } + + return EFI_SUCCESS; +} + +/** + + This function installs memory. + + @param PeiServices PEI Services table. + @param BootMode The specific boot path that is being followed + @param Mch Pointer to the DualChannelDdrMemoryInit PPI + @param RowConfArray Row configuration information for each row in th= e system. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER One of the input parameters was invalid. + @retval EFI_ABORTED An error occurred. + +**/ +EFI_STATUS +InstallEfiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +{ + EFI_PHYSICAL_ADDRESS PeiMemoryBaseAddress; + EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock; + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES]; + UINT8 Index; + UINT8 NumRanges; + UINT8 SmramIndex; + UINT8 SmramRanges; + UINT64 PeiMemoryLength; + UINTN BufferSize; + UINTN PeiMemoryIndex; + EFI_RESOURCE_ATTRIBUTE_TYPE Attribute; + EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable; + VOID *CapsuleBuffer; + UINTN CapsuleBufferLength; + EFI_PEI_CAPSULE_PPI *Capsule; + VOID *LargeMemRangeBuf; + UINTN LargeMemRangeBufLen; + + // + // Get the Memory Map + // + NumRanges =3D MAX_RANGES; + + ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * Num= Ranges); + + Status =3D GetMemoryMap ( + PeiServices, + (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *)MemoryMap, + &NumRanges + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "NumRanges: %d\n", NumRanges)); + + DEBUG ((EFI_D_INFO, "GetMemoryMap:\n")); + for (Index =3D 0; Index < NumRanges; Index++) { + DEBUG ((EFI_D_INFO, "Index: %d ", Index)); + DEBUG ((EFI_D_INFO, "RangeLength: 0x%016lX\t", MemoryMap[Index].RangeL= ength)); + DEBUG ((EFI_D_INFO, "PhysicalAddress: 0x%016lX\t", MemoryMap[Index].Ph= ysicalAddress)); + DEBUG ((EFI_D_INFO, "CpuAddress: 0x%016lX\t", MemoryMap[Index].CpuAddr= ess)); + DEBUG ((EFI_D_INFO, "Type: %d\n", MemoryMap[Index].Type)); + } + + // + // Find the highest memory range in processor native address space to gi= ve to + // PEI. Then take the top. + // + PeiMemoryBaseAddress =3D 0; + + // + // Query the platform for the minimum memory size + // + + Status =3D GetPlatformMemorySize ( + PeiServices, + BootMode, + &PeiMemoryLength + ); + ASSERT_EFI_ERROR (Status); + PeiMemoryLength =3D (PeiMemoryLength > PEI_MIN_MEMORY_SIZE) ? PeiMemoryL= ength : PEI_MIN_MEMORY_SIZE; + // + + PeiMemoryIndex =3D 0; + + for (Index =3D 0; Index < NumRanges; Index++) { + DEBUG ((EFI_D_INFO, "Found 0x%lx bytes at ", MemoryMap[Index].RangeLen= gth)); + DEBUG ((EFI_D_INFO, "0x%lx.\t", MemoryMap[Index].PhysicalAddress)); + DEBUG ((EFI_D_INFO, "Type: %d.\n", MemoryMap[Index].Type)); + + if ((MemoryMap[Index].Type =3D=3D DualChannelDdrMainMemory) && + (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength <= MAX_ADDRESS) && + (MemoryMap[Index].PhysicalAddress >=3D PeiMemoryBaseAddress) && + (MemoryMap[Index].RangeLength >=3D PeiMemoryLength)) + { + PeiMemoryBaseAddress =3D MemoryMap[Index].PhysicalAddress + + MemoryMap[Index].RangeLength - + PeiMemoryLength; + PeiMemoryIndex =3D Index; + } + } + + // + // Find the largest memory range excluding that given to PEI. + // + LargeMemRangeBuf =3D NULL; + LargeMemRangeBufLen =3D 0; + for (Index =3D 0; Index < NumRanges; Index++) { + if ((MemoryMap[Index].Type =3D=3D DualChannelDdrMainMemory) && + (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength <= MAX_ADDRESS)) + { + if (Index !=3D PeiMemoryIndex) { + if (MemoryMap[Index].RangeLength > LargeMemRangeBufLen) { + LargeMemRangeBuf =3D (VOID *)((UINTN)MemoryMap[Index].Physica= lAddress); + LargeMemRangeBufLen =3D (UINTN)MemoryMap[Index].RangeLength; + } + } else { + if ((MemoryMap[Index].RangeLength - PeiMemoryLength) >=3D LargeMem= RangeBufLen) { + LargeMemRangeBuf =3D (VOID *)((UINTN)MemoryMap[Index].Physica= lAddress); + LargeMemRangeBufLen =3D (UINTN)(MemoryMap[Index].RangeLength - P= eiMemoryLength); + } + } + } + } + + Capsule =3D NULL; + CapsuleBuffer =3D NULL; + CapsuleBufferLength =3D 0; + if (BootMode =3D=3D BOOT_ON_FLASH_UPDATE) { + Status =3D PeiServicesLocatePpi ( + &gEfiPeiCapsulePpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + (VOID **)&Capsule // PPI + ); + ASSERT_EFI_ERROR (Status); + + if (Status =3D=3D EFI_SUCCESS) { + CapsuleBuffer =3D LargeMemRangeBuf; + CapsuleBufferLength =3D LargeMemRangeBufLen; + DEBUG ((EFI_D_INFO, "CapsuleBuffer: %x, CapsuleBufferLength: %x\n", = CapsuleBuffer, CapsuleBufferLength)); + + // + // Call the Capsule PPI Coalesce function to coalesce the capsule da= ta. + // + Status =3D Capsule->Coalesce ( + PeiServices, + &CapsuleBuffer, + &CapsuleBufferLength + ); + // + // If it failed, then NULL out our capsule PPI pointer so that the c= apsule + // HOB does not get created below. + // + if (Status !=3D EFI_SUCCESS) { + Capsule =3D NULL; + } + } + } + + // + // Carve out the top memory reserved for PEI + // + Status =3D PeiServicesInstallPeiMemory (PeiMemoryBaseAddress, PeiMemoryL= ength); + ASSERT_EFI_ERROR (Status); + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + PeiMemoryBaseAddress, // MemoryBegin + PeiMemoryLength // MemoryLength + ); + + // Report first 640KB of system memory + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + (EFI_PHYSICAL_ADDRESS)(0), + (UINT64)(0xA0000) + ); + + // + // Install physical memory descriptor hobs for each memory range. + // + SmramRanges =3D 0; + for (Index =3D 0; Index < NumRanges; Index++) { + Attribute =3D 0; + if (MemoryMap[Index].Type =3D=3D DualChannelDdrMainMemory) { + if (Index =3D=3D PeiMemoryIndex) { + // + // This is a partially tested Main Memory range, give it to EFI + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_TESTED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ), + MemoryMap[Index].PhysicalAddress, + MemoryMap[Index].RangeLength - PeiMemoryLength + ); + } else { + // + // This is an untested Main Memory range, give it to EFI + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, // MemoryType, + ( + 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 + ), + MemoryMap[Index].PhysicalAddress, // MemoryBegin + MemoryMap[Index].RangeLength // MemoryLength + ); + } + } else { + // + // Only report TSEG range to align AcpiVariableHobOnSmramReserveHobT= hunk + // + if ((MemoryMap[Index].PhysicalAddress > 0x100000) && + ((MemoryMap[Index].Type =3D=3D DualChannelDdrSmramCacheable) || + (MemoryMap[Index].Type =3D=3D DualChannelDdrSmramNonCacheable))) + { + SmramRanges++; + } + + // + // AMD CPU has different flow to SMM and normal mode cache attribute. + // SmmIPL will set TSEG and HSEG as UC when exit SMM. + // the Attribute only support 0 then it will fail to set them to UC + // otherwise the SmmIPL will hang at set memory attribute. + // + if (MemoryMap[Index].Type =3D=3D DualChannelDdrGraphicsMemoryNonCach= eable) { + Attribute |=3D EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE; + } + + if (MemoryMap[Index].Type =3D=3D DualChannelDdrGraphicsMemoryCacheab= le) { + Attribute |=3D EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | EFI_R= ESOURCE_ATTRIBUTE_UNCACHEABLE; + } + + if (MemoryMap[Index].Type =3D=3D DualChannelDdrReservedMemory) { + Attribute |=3D EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE; + } + + // + // Make sure non-system memory is marked as reserved + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_RESERVED, // MemoryType, + Attribute, // MemoryAttribute + MemoryMap[Index].PhysicalAddress, // MemoryBegin + MemoryMap[Index].RangeLength // MemoryLength + ); + } + } + + // + // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM m= emory that contains a pointer + // to the SMM Services Table that is required on the S3 resume path + // + ASSERT (SmramRanges > 0); + BufferSize =3D sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK); + if (SmramRanges > 0) { + BufferSize +=3D ((SmramRanges) * sizeof (EFI_SMRAM_DESCRIPTOR)); + } + + Hob.Raw =3D BuildGuidHob ( + &gEfiSmmPeiSmramMemoryReserveGuid, + BufferSize + ); + ASSERT (Hob.Raw); + + SmramHobDescriptorBlock =3D (EFI_SMRAM_HOB_D= ESCRIPTOR_BLOCK *)(Hob.Raw); + SmramHobDescriptorBlock->NumberOfSmmReservedRegions =3D SmramRanges + 1; + + SmramIndex =3D 0; + for (Index =3D 0; Index < NumRanges; Index++) { + if ((MemoryMap[Index].PhysicalAddress > 0x100000) && + ((MemoryMap[Index].Type =3D=3D DualChannelDdrSmramCacheable) || + (MemoryMap[Index].Type =3D=3D DualChannelDdrSmramNonCacheable))) + { + // + // This is an SMRAM range, create an SMRAM descriptor + // + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart =3D Me= moryMap[Index].PhysicalAddress; + SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart =3D Me= moryMap[Index].CpuAddress; + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize =3D Me= moryMap[Index].RangeLength; + if (MemoryMap[Index].Type =3D=3D DualChannelDdrSmramCacheable) { + SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState =3D EF= I_SMRAM_CLOSED | EFI_CACHEABLE; + } else { + SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState =3D EF= I_SMRAM_CLOSED; + } + + if ( SmramIndex =3D=3D SmramRanges - 1) { + // + // one extra EFI_SMRAM_DESCRIPTOR for a page of SMRAM memory + // + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize =3D E= FI_PAGE_SIZE; + SmramIndex++; + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart =3D= MemoryMap[Index].PhysicalAddress + EFI_PAGE_SIZE; + SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart =3D= MemoryMap[Index].CpuAddress + EFI_PAGE_SIZE; + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize =3D= MemoryMap[Index].RangeLength - EFI_PAGE_SIZE; + SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState =3D= SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState; + SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState |=3D= EFI_ALLOCATED; + } + + SmramIndex++; + } + } + + // + // Build a HOB with the location of the reserved memory range. + // + CopyMem (&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[S= mramRanges-1], sizeof (EFI_SMRAM_DESCRIPTOR)); + DescriptorAcpiVariable.CpuStart +=3D RESERVED_CPU_S3_SAVE_OFFSET; + DEBUG ((EFI_D_INFO, "gEfiAcpiVariableGuid CpuStart: 0x%X\n", (UINTN)Desc= riptorAcpiVariable.CpuStart)); + BuildGuidDataHob ( + &gEfiAcpiVariableGuid, + &DescriptorAcpiVariable, + sizeof (EFI_SMRAM_DESCRIPTOR) + ); + + // + // If we found the capsule PPI (and we didn't have errors), then + // call the capsule PEIM to allocate memory for the capsule. + // + if (Capsule !=3D NULL) { + Status =3D Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBu= fferLength); + } + + return EFI_SUCCESS; +} + +/** + + Find memory that is reserved so PEI has some to use. + + @param PeiServices PEI Services table. + @param VariableSevices Variable PPI instance. + + @retval EFI_SUCCESS The function completed successfully. + Error value from LocatePpi() + +**/ +EFI_STATUS +InstallS3Memory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +{ + EFI_STATUS Status; + UINTN S3MemoryBase; + UINTN S3MemorySize; + UINT8 SmramRanges; + UINT8 NumRanges; + UINT8 Index; + UINT8 SmramIndex; + UINTN BufferSize; + EFI_PEI_HOB_POINTERS Hob; + EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock; + PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE MemoryMap[MAX_RANGES]; + RESERVED_ACPI_S3_RANGE *S3MemoryRangeData; + EFI_SMRAM_DESCRIPTOR DescriptorAcpiVariable; + + // + // Get the Memory Map + // + NumRanges =3D MAX_RANGES; + + ZeroMem (MemoryMap, sizeof (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE) * Num= Ranges); + + Status =3D GetMemoryMap ( + PeiServices, + (PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *)MemoryMap, + &NumRanges + ); + ASSERT_EFI_ERROR (Status); + DEBUG ((EFI_D_INFO, "NumRanges =3D 0x%x\n", NumRanges)); + + // + // Install physical memory descriptor hobs for each memory range. + // + SmramRanges =3D 0; + DEBUG ((EFI_D_INFO, "GetMemoryMap:\n")); + for (Index =3D 0; Index < NumRanges; Index++) { + DEBUG ((EFI_D_INFO, "Index: %d ", Index)); + DEBUG ((EFI_D_INFO, "RangeLength: 0x%016lX\t", MemoryMap[Index].RangeL= ength)); + DEBUG ((EFI_D_INFO, "PhysicalAddress: 0x%016lX\t", MemoryMap[Index].Ph= ysicalAddress)); + DEBUG ((EFI_D_INFO, "CpuAddress: 0x%016lX\t", MemoryMap[Index].CpuAddr= ess)); + DEBUG ((EFI_D_INFO, "Type: %d\n", MemoryMap[Index].Type)); + if ((MemoryMap[Index].PhysicalAddress > 0x100000) && + ((MemoryMap[Index].Type =3D=3D DualChannelDdrSmramCacheable) || + (MemoryMap[Index].Type =3D=3D DualChannelDdrSmramNonCacheable))) + { + SmramRanges++; + } + } + + ASSERT (SmramRanges > 0); + DEBUG ((EFI_D_INFO, "SmramRanges =3D 0x%x\n", SmramRanges)); + + // + // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM m= emory that contains a pointer + // to the SMM Services Table that is required on the S3 resume path + // + BufferSize =3D sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK); + if (SmramRanges > 0) { + BufferSize +=3D ((SmramRanges) * sizeof (EFI_SMRAM_DESCRIPTOR)); + } + + DEBUG ((EFI_D_INFO, "BufferSize =3D 0x%x\n", BufferSize)); + + Hob.Raw =3D BuildGuidHob ( + &gEfiSmmPeiSmramMemoryReserveGuid, + BufferSize + ); + ASSERT (Hob.Raw); + DEBUG ((EFI_D_INFO, "gEfiSmmPeiSmramMemoryReserveGuid/SmramHobDescriptor= Block: 0x%X \n", (UINTN)Hob.Raw)); + + SmramHobDescriptorBlock =3D (EFI_SMRAM_HOB_D= ESCRIPTOR_BLOCK *)(Hob.Raw); + SmramHobDescriptorBlock->NumberOfSmmReservedRegions =3D SmramRanges + 1; + + SmramIndex =3D 0; + for (Index =3D 0; Index < NumRanges; Index++) { + DEBUG ((EFI_D_INFO, "Index: 0x%X \t", Index)); + DEBUG ((EFI_D_INFO, "SmramIndex: 0x%X \n", SmramIndex)); + if ((MemoryMap[Index].PhysicalAddress > 0x100000) && + ((MemoryMap[Index].Type =3D=3D DualChannelDdrSmramCacheable) || + (MemoryMap[Index].Type =3D=3D DualChannelDdrSmramNonCacheable)) + ) + { + // + // This is an SMRAM range, create an SMRAM descriptor + // + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart =3D Me= moryMap[Index].PhysicalAddress; + SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart =3D Me= moryMap[Index].CpuAddress; + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize =3D Me= moryMap[Index].RangeLength; + if (MemoryMap[Index].Type =3D=3D DualChannelDdrSmramCacheable) { + SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState =3D EF= I_SMRAM_CLOSED | EFI_CACHEABLE; + } else { + SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState =3D EF= I_SMRAM_CLOSED; + } + + DEBUG ((EFI_D_INFO, "SmramIndex: 0x%X \n", SmramIndex)); + DEBUG ((EFI_D_INFO, "PhysicalStart: 0x%X\n", (UINTN)SmramHobDescript= orBlock->Descriptor[SmramIndex].PhysicalStart)); + DEBUG ((EFI_D_INFO, "CpuStart : 0x%X\n", (UINTN)SmramHobDescript= orBlock->Descriptor[SmramIndex].CpuStart)); + DEBUG ((EFI_D_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescript= orBlock->Descriptor[SmramIndex].PhysicalSize)); + DEBUG ((EFI_D_INFO, "RegionState : 0x%X\n", (UINTN)SmramHobDescript= orBlock->Descriptor[SmramIndex].RegionState)); + if ( SmramIndex =3D=3D SmramRanges - 1) { + // + // one extra EFI_SMRAM_DESCRIPTOR for a page of SMRAM memory + // + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize =3D E= FI_PAGE_SIZE; + SmramIndex++; + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalStart =3D= MemoryMap[Index].PhysicalAddress + EFI_PAGE_SIZE; + SmramHobDescriptorBlock->Descriptor[SmramIndex].CpuStart =3D= MemoryMap[Index].CpuAddress + EFI_PAGE_SIZE; + SmramHobDescriptorBlock->Descriptor[SmramIndex].PhysicalSize =3D= MemoryMap[Index].RangeLength - EFI_PAGE_SIZE; + SmramHobDescriptorBlock->Descriptor[SmramIndex].RegionState =3D= SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState; + SmramHobDescriptorBlock->Descriptor[SmramIndex-1].RegionState |=3D= EFI_ALLOCATED; + DEBUG ((EFI_D_INFO, "SmramIndex: 0x%X \n", SmramIndex)); + DEBUG ((EFI_D_INFO, "PhysicalStart: 0x%X\n", (UINTN)SmramHobDescri= ptorBlock->Descriptor[SmramIndex].PhysicalStart)); + DEBUG ((EFI_D_INFO, "CpuStart : 0x%X\n", (UINTN)SmramHobDescri= ptorBlock->Descriptor[SmramIndex].CpuStart)); + DEBUG ((EFI_D_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescri= ptorBlock->Descriptor[SmramIndex].PhysicalSize)); + DEBUG ((EFI_D_INFO, "RegionState : 0x%X\n\n", (UINTN)SmramHobDesc= riptorBlock->Descriptor[SmramIndex].RegionState)); + + DEBUG ((EFI_D_INFO, "PhysicalSize : 0x%X\n", (UINTN)SmramHobDescri= ptorBlock->Descriptor[SmramIndex-1].PhysicalSize)); + DEBUG ((EFI_D_INFO, "RegionState : 0x%X\n", (UINTN)SmramHobDescri= ptorBlock->Descriptor[SmramIndex-1].RegionState)); + } + + SmramIndex++; + } + } + + // + // Build a HOB with the location of the reserved memory range. + // + CopyMem (&DescriptorAcpiVariable, &SmramHobDescriptorBlock->Descriptor[S= mramRanges-1], sizeof (EFI_SMRAM_DESCRIPTOR)); + DescriptorAcpiVariable.CpuStart +=3D RESERVED_CPU_S3_SAVE_OFFSET; + DEBUG ((EFI_D_INFO, "gEfiAcpiVariableGuid CpuStart: 0x%X\n", (UINTN)Desc= riptorAcpiVariable.CpuStart)); + BuildGuidDataHob ( + &gEfiAcpiVariableGuid, + &DescriptorAcpiVariable, + sizeof (EFI_SMRAM_DESCRIPTOR) + ); + + // + // Get the location and size of the S3 memory range in the reserved page= and + // install it as PEI Memory. + // + + DEBUG ((EFI_D_INFO, "TSEG Base =3D 0x%08x\n", SmramHobDescriptorBlock->D= escriptor[SmramRanges].PhysicalStart)); + DEBUG ((EFI_D_INFO, "SmramRanges =3D 0x%x\n", SmramRanges)); + S3MemoryRangeData =3D (RESERVED_ACPI_S3_RANGE *)(UINTN) + (SmramHobDescriptorBlock->Descriptor[SmramRanges].Ph= ysicalStart + RESERVED_ACPI_S3_RANGE_OFFSET); + DEBUG ((EFI_D_INFO, "S3MemoryRangeData =3D 0x%08x\n", (UINTN)S3MemoryRan= geData)); + + DEBUG ((EFI_D_INFO, "S3MemoryRangeData->AcpiReservedMemoryBase =3D 0x%X\= n", (UINTN)S3MemoryRangeData->AcpiReservedMemoryBase)); + DEBUG ((EFI_D_INFO, "S3MemoryRangeData->AcpiReservedMemorySize =3D 0x%X\= n", (UINTN)S3MemoryRangeData->AcpiReservedMemorySize)); + DEBUG ((EFI_D_INFO, "S3MemoryRangeData->SystemMemoryLength =3D 0x%X\n", = (UINTN)S3MemoryRangeData->SystemMemoryLength)); + + S3MemoryBase =3D (UINTN)(S3MemoryRangeData->AcpiReservedMemoryBase); + DEBUG ((EFI_D_INFO, "S3MemoryBase =3D 0x%08x\n", S3MemoryBase)); + S3MemorySize =3D (UINTN)(S3MemoryRangeData->AcpiReservedMemorySize); + DEBUG ((EFI_D_INFO, "S3MemorySize =3D 0x%08x\n", S3MemorySize)); + + Status =3D PeiServicesInstallPeiMemory (S3MemoryBase, S3MemorySize); + ASSERT_EFI_ERROR (Status); + + // + // Retrieve the system memory length and build memory hob for the system + // memory above 1MB. So Memory Callback can set cache for the system mem= ory + // correctly on S3 boot path, just like it does on Normal boot path. + // + ASSERT ((S3MemoryRangeData->SystemMemoryLength - 0x100000) > 0); + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + 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 + ), + 0x100000, + S3MemoryRangeData->SystemMemoryLength - 0x100000 + ); + + DEBUG ((EFI_D_INFO, "MemoryBegin: 0x%lX, MemoryLength: 0x%lX\n", 0x10000= 0, S3MemoryRangeData->SystemMemoryLength - 0x100000)); + + for (Index =3D 0; Index < NumRanges; Index++) { + if ((MemoryMap[Index].Type =3D=3D DualChannelDdrMainMemory) && + (MemoryMap[Index].PhysicalAddress + MemoryMap[Index].RangeLength <= 0x100000)) + { + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + ( + 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 + ), + MemoryMap[Index].PhysicalAddress, + MemoryMap[Index].RangeLength + ); + DEBUG ((EFI_D_INFO, "MemoryBegin: 0x%lX, MemoryLength: 0x%lX\n", Mem= oryMap[Index].PhysicalAddress, MemoryMap[Index].RangeLength)); + + DEBUG ((EFI_D_INFO, "Build resource HOB for Legacy Region on S3 patc= h :")); + DEBUG ((EFI_D_INFO, " Memory Base:0x%lX Length:0x%lX\n", MemoryMap[I= ndex].PhysicalAddress, MemoryMap[Index].RangeLength)); + } + } + + return EFI_SUCCESS; +} + +/** + + This function Get Platform Memory Size. + + @param PeiServices PEI Services table. + @param BootMode The specific boot path that is being followed + @param MemorySize Size of Memory used by Platform + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetPlatformMemorySize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode, + IN OUT UINT64 *MemorySize + ) +{ + EFI_STATUS Status; + EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable; + UINTN DataSize; + EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1]; + UINTN Index; + + DataSize =3D sizeof (MemoryData); + + if (BootMode =3D=3D BOOT_IN_RECOVERY_MODE) { + // + // // Treat recovery as if variable not found (eg 1st boot). + // + Status =3D EFI_NOT_FOUND; + } else { + Status =3D PeiServicesLocatePpi ( + &gEfiPeiReadOnlyVariable2PpiGuid, + 0, + NULL, + (VOID **)&Variable + ); + + ASSERT_EFI_ERROR (Status); + + DataSize =3D sizeof (MemoryData); + Status =3D Variable->GetVariable ( + Variable, + EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME, + &gEfiMemoryTypeInformationGuid, + NULL, + &DataSize, + &MemoryData + ); + } + + // + // Accumulate maximum amount of memory needed + // + if (EFI_ERROR (Status)) { + // + // Start with minimum memory + // + *MemorySize =3D PEI_MIN_MEMORY_SIZE; + + for (Index =3D 0; Index < sizeof (mDefaultMemoryTypeInformation) / siz= eof (EFI_MEMORY_TYPE_INFORMATION); Index++) { + *MemorySize +=3D mDefaultMemoryTypeInformation[Index].NumberOfPages = * EFI_PAGE_SIZE; + } + + // + // Build the GUID'd HOB for DXE + // + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof (mDefaultMemoryTypeInformation) + ); + } else { + // + // Start with at least PEI_MIN_MEMORY_SIZE pages of memory for the DXE= Core and the DXE Stack + // + + *MemorySize =3D PEI_MIN_MEMORY_SIZE; + for (Index =3D 0; Index < DataSize / sizeof (EFI_MEMORY_TYPE_INFORMATI= ON); Index++) { + DEBUG ((EFI_D_INFO, "Index %d, Page: %d\n", Index, MemoryData[Index]= .NumberOfPages)); + *MemorySize +=3D MemoryData[Index].NumberOfPages * EFI_PAGE_SIZE; + } + + // + // Build the GUID'd HOB for DXE + // + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + MemoryData, + DataSize + ); + } + + DEBUG ((EFI_D_INFO, "GetPlatformMemorySize, MemorySize: 0x%lX\n", *Memor= ySize)); + return EFI_SUCCESS; +} + +/** + + Callback function after Memory Info Hob Installed. + + @param PeiServices PEI Services table. + @param NotifyDescriptor Notify Descriptor. + @param Ppi Ppi + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +MemoryInfoHobPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + + // + // Get boot mode + // + Status =3D PeiServicesGetBootMode (&BootMode); + ASSERT_EFI_ERROR (Status); + + if (BootMode =3D=3D BOOT_ON_S3_RESUME) { + DEBUG ((EFI_D_INFO, "Following BOOT_ON_S3_RESUME boot path.\n")); + + Status =3D InstallS3Memory (PeiServices, BootMode); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + PeiServicesResetSystem (); + } + + return EFI_SUCCESS; + } + + Status =3D InstallEfiMemory (PeiServices, BootMode); + return Status; +} diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInst= all.h b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.h new file mode 100644 index 0000000000..a9a24677ad --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryInstall.h @@ -0,0 +1,229 @@ +/** @file + Implements MemoryInstall.h + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file +Framework PEIM to initialize memory on an DDR2 SDRAM Memory Controller. + +Copyright (c) 2013 - 2016 Intel Corporation. + +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 IMPLI= ED. + +**/ + +#ifndef _MRC_WRAPPER_H +#define _MRC_WRAPPER_H + +// +// Maximum number of memory ranges supported by the memory controller +// +#define MAX_RANGES (4 + 5) + +// +// Min. of 48MB PEI phase +// +#define PEI_MIN_MEMORY_SIZE (8 * 0x800000) +#define PEI_RECOVERY_MIN_MEMORY_SIZE (8 * 0x800000) + +// +// SMRAM Memory Range +// +#define PEI_MEMORY_RANGE_SMRAM UINT32 +#define PEI_MR_SMRAM_ALL 0xFFFFFFFF +#define PEI_MR_SMRAM_NONE 0x00000000 +#define PEI_MR_SMRAM_CACHEABLE_MASK 0x80000000 +#define PEI_MR_SMRAM_SEGTYPE_MASK 0x00FF0000 +#define PEI_MR_SMRAM_ABSEG_MASK 0x00010000 +#define PEI_MR_SMRAM_HSEG_MASK 0x00020000 +#define PEI_MR_SMRAM_TSEG_MASK 0x00040000 + +// +// SMRAM range definitions +// +#define MC_ABSEG_HSEG_PHYSICAL_START 0x000A0000 +#define MC_ABSEG_HSEG_LENGTH 0x00020000 +#define MC_ABSEG_CPU_START 0x000A0000 +#define MC_HSEG_CPU_START 0xFEDA0000 + +// +// If adding additional entries, SMRAM Size +// is a multiple of 128KB. +// +#define PEI_MR_SMRAM_SIZE_MASK 0x0000FFFF +#define PEI_MR_SMRAM_SIZE_128K_MASK 0x00000001 +#define PEI_MR_SMRAM_SIZE_256K_MASK 0x00000002 +#define PEI_MR_SMRAM_SIZE_512K_MASK 0x00000004 +#define PEI_MR_SMRAM_SIZE_1024K_MASK 0x00000008 +#define PEI_MR_SMRAM_SIZE_2048K_MASK 0x00000010 +#define PEI_MR_SMRAM_SIZE_4096K_MASK 0x00000020 +#define PEI_MR_SMRAM_SIZE_8192K_MASK 0x00000040 + +#define PEI_MR_SMRAM_ABSEG_128K_NOCACHE 0x00010001 +#define PEI_MR_SMRAM_HSEG_128K_CACHE 0x80020001 +#define PEI_MR_SMRAM_HSEG_128K_NOCACHE 0x00020001 +#define PEI_MR_SMRAM_TSEG_128K_CACHE 0x80040001 +#define PEI_MR_SMRAM_TSEG_128K_NOCACHE 0x00040001 +#define PEI_MR_SMRAM_TSEG_256K_CACHE 0x80040002 +#define PEI_MR_SMRAM_TSEG_256K_NOCACHE 0x00040002 +#define PEI_MR_SMRAM_TSEG_512K_CACHE 0x80040004 +#define PEI_MR_SMRAM_TSEG_512K_NOCACHE 0x00040004 +#define PEI_MR_SMRAM_TSEG_1024K_CACHE 0x80040008 +#define PEI_MR_SMRAM_TSEG_1024K_NOCACHE 0x00040008 +#define PEI_MR_SMRAM_TSEG_2048K_CACHE 0x80040010 +#define PEI_MR_SMRAM_TSEG_2048K_NOCACHE 0x00040010 +#define PEI_MR_SMRAM_TSEG_4096K_CACHE 0x80040020 +#define PEI_MR_SMRAM_TSEG_4096K_NOCACHE 0x00040020 +#define PEI_MR_SMRAM_TSEG_8192K_CACHE 0x80040040 +#define PEI_MR_SMRAM_TSEG_8192K_NOCACHE 0x00040040 + +// +// Pci Memory Hole +// +#define PEI_MEMORY_RANGE_PCI_MEMORY UINT32 + +typedef enum { + Ignore, + Quick, + Sparse, + Extensive +} PEI_MEMORY_TEST_OP; + +// Memory range types +// +typedef enum { + DualChannelDdrMainMemory, + DualChannelDdrSmramCacheable, + DualChannelDdrSmramNonCacheable, + DualChannelDdrGraphicsMemoryCacheable, + DualChannelDdrGraphicsMemoryNonCacheable, + DualChannelDdrReservedMemory, + DualChannelDdrMaxMemoryRangeType +} PEI_DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE; + +// +// Memory map range information +// +typedef struct { + EFI_PHYSICAL_ADDRESS PhysicalAddress; + EFI_PHYSICAL_ADDRESS CpuAddress; + EFI_PHYSICAL_ADDRESS RangeLength; + PEI_DUAL_CHANNEL_DDR_MEMORY_RANGE_TYPE Type; +} PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE; + +// +// This structure stores the base and size of the ACPI reserved memory use= d when +// resuming from S3. This region must be allocated by the platform code. +// +typedef struct { + UINT32 AcpiReservedMemoryBase; + UINT32 AcpiReservedMemorySize; + UINT32 SystemMemoryLength; +} RESERVED_ACPI_S3_RANGE; + +#define RESERVED_ACPI_S3_RANGE_OFFSET (EFI_PAGE_SIZE - sizeof (RESERVED_A= CPI_S3_RANGE)) + +// +// ------------------------ TSEG Base +// +// ------------------------ RESERVED_CPU_S3_SAVE_OFFSET +// CPU S3 data +// ------------------------ RESERVED_ACPI_S3_RANGE_OFFSET +// S3 Memory base structure +// ------------------------ TSEG + 1 page + +#define RESERVED_CPU_S3_SAVE_OFFSET (RESERVED_ACPI_S3_RANGE_OFFSET - size= of (SMM_S3_RESUME_STATE)) + +// +// Function prototypes. +// + +/** + + This function installs memory. + + @param PeiServices PEI Services table. + @param BootMode The specific boot path that is being followed + @param Mch Pointer to the DualChannelDdrMemoryInit PPI + @param RowConfArray Row configuration information for each row in th= e system. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER One of the input parameters was invalid. + @retval EFI_ABORTED An error occurred. + +**/ +EFI_STATUS +InstallEfiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ); + +/** + + Find memory that is reserved so PEI has some to use. + + @param PeiServices PEI Services table. + @param VariableSevices Variable PPI instance. + + @retval EFI_SUCCESS The function completed successfully. + Error value from LocatePpi() + +**/ +EFI_STATUS +InstallS3Memory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ); + +/** + + This function returns the memory ranges to be enabled, along with inform= ation + describing how the range should be used. + + @param PeiServices PEI Services Table. + @param MemoryMap Buffer to record details of the memory ranges tobe= enabled. + @param NumRanges On input, this contains the maximum number of memo= ry ranges that can be described + in the MemoryMap buffer. + + @retval MemoryMap The buffer will be filled in + @retval NumRanges will contain the actual number of memory ranges th= at are to be anabled. + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetMemoryMap ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap, + IN OUT UINT8 *NumRanges + ); + +/** + + This function Get Platform Memory Size. + + @param PeiServices PEI Services table. + @param BootMode The specific boot path that is being followed + @param MemorySize Size of Memory used by Platform + + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetPlatformMemorySize ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode, + IN OUT UINT64 *MemorySize + ); + +#endif diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryPeim= .c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryPeim.c new file mode 100644 index 0000000000..5f6aefa9b1 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/MemoryPeim.c @@ -0,0 +1,385 @@ +/** @file + Implements MemoryPeim.C + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file + + Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.
+ + + This program and the accompanying materials are licensed and made availa= ble under + + the terms and conditions of the BSD License that accompanies this distri= bution. + + 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 IMP= LIED. + + + + +Module Name: + + + MemoryPeim.c + +Abstract: + + Tiano PEIM to provide the platform support functionality. + This file implements the Platform Memory Range PPI + +--*/ + +#include "CommonHeader.h" + +#define MTRR_LIB_CACHE_MTRR_ENABLED 0x800 +#define SYS_CFG 0xC0010010ul + +VOID +MtrrLibInitializeMtrrMask ( + OUT UINT64 *MtrrValidBitsMask, + OUT UINT64 *MtrrValidAddressMask + ); + +/** + + This function set different memory range cache attribute. + + @param PeiServices Pointer to the PEI Service Table. + +**/ +EFI_STATUS +EFIAPI +SetPeiCacheMode ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + EFI_BOOT_MODE BootMode; + UINT64 MemoryLength; + UINT64 MemOverflow; + UINT64 MemoryLengthUc; + UINT64 MaxMemoryLength; + UINT64 LowMemoryLength; + UINT64 HighMemoryLength; + UINT8 Index; + MTRR_SETTINGS MtrrSetting; + UINT64 MsrData; + UINT64 MtrrValidBitsMask; + UINT64 MtrrValidAddressMask; + + MtrrLibInitializeMtrrMask ( + &MtrrValidBitsMask, + &MtrrValidAddressMask + ); + + // + // Variable initialization + // + LowMemoryLength =3D 0; + HighMemoryLength =3D 0; + MemoryLengthUc =3D 0; + + Status =3D (*PeiServices)->GetBootMode ( + PeiServices, + &BootMode + ); + + // + // Determine memory usage + // + GetMemorySize ( + PeiServices, + &LowMemoryLength, + &HighMemoryLength, + NULL, + NULL + ); + + MaxMemoryLength =3D LowMemoryLength; + + // + // Round up to nearest 256MB with high memory and 64MB w/o high memory + // + if (HighMemoryLength !=3D 0 ) { + MemOverflow =3D (LowMemoryLength & 0x0fffffff); + if (MemOverflow !=3D 0) { + MaxMemoryLength =3D LowMemoryLength + (0x10000000 - MemOverflow); + } + } else { + MemOverflow =3D (LowMemoryLength & 0x03ffffff); + if (MemOverflow !=3D 0) { + MaxMemoryLength =3D LowMemoryLength + (0x4000000 - MemOverflow); + } + } + + ZeroMem (&MtrrSetting, sizeof (MTRR_SETTINGS)); + for (Index =3D 0; Index < 2; Index++) { + MtrrSetting.Fixed.Mtrr[Index] =3D 0x1E1E1E1E1E1E1E1Eul; + } + + // 0xA0000-0xBFFFF used for ASEG which cache type is controlled by bit 1= 0:8 of SMMMask(MSR 0xC0010113) + for (Index =3D 3; Index < 11; Index++) { + MtrrSetting.Fixed.Mtrr[Index] =3D 0x1C1C1C1C1C1C1C1Cul; + } + + // + // Cache the flash area to improve the boot performance in PEI phase + // + Index =3D 0; + MtrrSetting.Variables.Mtrr[Index].Base =3D FixedPcdGet32 (PcdFlashAreaBa= seAddress) | CacheWriteProtected; + MtrrSetting.Variables.Mtrr[Index].Mask =3D ((~((UINT64)(FixedPcdGet32 (P= cdFlashAreaSize) - 1))) & MtrrValidBitsMask) | MTRR_LIB_CACHE_MTRR_ENABLED; + + Index++; + + MemOverflow =3D 0; + while (MaxMemoryLength > MemOverflow) { + MtrrSetting.Variables.Mtrr[Index].Base =3D (MemOverflow & MtrrValidAdd= ressMask) | CacheWriteBack; + MemoryLength =3D MaxMemoryLength - MemOverfl= ow; + MemoryLength =3D GetPowerOfTwo64 (MemoryLeng= th); + MtrrSetting.Variables.Mtrr[Index].Mask =3D ((~(MemoryLength - 1)) & Mt= rrValidBitsMask) | MTRR_LIB_CACHE_MTRR_ENABLED; + + MemOverflow +=3D MemoryLength; + Index++; + } + + MemoryLength =3D LowMemoryLength; + + while (MaxMemoryLength !=3D MemoryLength) { + MemoryLengthUc =3D GetPowerOfTwo64 (MaxMemoryLength - MemoryLength); + + MtrrSetting.Variables.Mtrr[Index].Base =3D ((MaxMemoryLength - MemoryL= engthUc) & MtrrValidAddressMask) | CacheUncacheable; + MtrrSetting.Variables.Mtrr[Index].Mask =3D ((~(MemoryLengthUc - 1)) = & MtrrValidBitsMask) | MTRR_LIB_CACHE_MTRR_ENABLED; + MaxMemoryLength -=3D MemoryLengthUc; + Index++; + } + + if (HighMemoryLength > 0) { + MsrData =3D AsmReadMsr64 (SYS_CFG); + MsrData |=3D BIT22; + AsmWriteMsr64 (SYS_CFG, MsrData); + } + + for (Index =3D 0; Index < MTRR_NUMBER_OF_VARIABLE_MTRR; Index++) { + if (MtrrSetting.Variables.Mtrr[Index].Base =3D=3D 0) { + break; + } + + DEBUG ((EFI_D_INFO, "Base=3D%lx, Mask=3D%lx\n", MtrrSetting.Variables.= Mtrr[Index].Base, MtrrSetting.Variables.Mtrr[Index].Mask)); + } + + // + // set FE/E bits for IA32_MTRR_DEF_TYPE + // + MtrrSetting.MtrrDefType |=3D 3 <<10; + + AsmWriteMsr64 (SYS_CFG, (AsmReadMsr64 (SYS_CFG) | (1 << 19))); + MtrrSetAllMtrrs (&MtrrSetting); + AsmWriteMsr64 (SYS_CFG, (AsmReadMsr64 (SYS_CFG) & (~(1 << 19)))); + // + // Dump MTRR Setting + // + MtrrDebugPrintAllMtrrs (); + (VOID)Status; + return EFI_SUCCESS; +} + +/** + + This function returns the different avaiable memory length. + + @param PeiServices Pointer to the PEI Service Table. + @param LowMemoryLength Avaiable memory length below 4G address. + @param HighMemoryLength Avaiable memory length above 4G address. + @param GraphicMemoryBase Avaiable UMA base address. + @param GraphicMemoryLength Avaiable UMA length. + + @retval LowMemoryLength Avaiable memory length below 4G address. + @retval HighMemoryLength Avaiable memory length above 4G address. + @retval GraphicMemoryBase Avaiable UMA base address. + @retval GraphicMemoryLength Avaiable UMA length. + +**/ +EFI_STATUS +GetMemorySize ( + IN CONST EFI_PEI_SERVICES **PeiServices, + OUT UINT64 *LowMemoryLength, + OUT UINT64 *HighMemoryLength, + OUT UINT64 *GraphicMemoryBase OPTIONAL, + OUT UINT64 *GraphicMemoryLength OPTIONAL + ) +{ + AMD_MEMORY_INFO_HOB *AmdMemoryInfoHob; + AMD_MEMORY_RANGE_DESCRIPTOR *Range; + UINT32 Index; + + if (HighMemoryLength !=3D NULL) { + *HighMemoryLength =3D 0; + } + + if (LowMemoryLength !=3D NULL) { + *LowMemoryLength =3D 0x100000; + } + + // Get Pointer to HOB + AmdMemoryInfoHob =3D GetFirstGuidHob (&gAmdMemoryInfoHobGuid); + ASSERT (AmdMemoryInfoHob !=3D NULL); + // Get HOB Data + AmdMemoryInfoHob =3D GET_GUID_HOB_DATA (AmdMemoryInfoHob); + if (AmdMemoryInfoHob !=3D NULL) { + for (Index =3D 0; Index < AmdMemoryInfoHob->NumberOfDescriptor; Index+= +) { + Range =3D (AMD_MEMORY_RANGE_DESCRIPTOR *)&AmdMemoryInfoHob->Ranges[I= ndex]; + if (Range->Attribute =3D=3D AMD_MEMORY_ATTRIBUTE_AVAILABLE) { + if (Range->Base < SIZE_4GB) { + if (LowMemoryLength !=3D NULL) { + *LowMemoryLength =3D Range->Size; + } + } else if (Range->Base >=3D SIZE_4GB) { + if (HighMemoryLength !=3D NULL) { + *HighMemoryLength =3D Range->Size; + } + } + } else if (Range->Attribute =3D=3D AMD_MEMORY_ATTRIBUTE_UMA) { + if (GraphicMemoryBase !=3D NULL) { + *GraphicMemoryBase =3D Range->Base; + } + + if (GraphicMemoryLength !=3D NULL) { + *GraphicMemoryLength =3D Range->Size; + } + } + } + } + + return EFI_SUCCESS; +} + +/** + + This function returns the memory ranges to be enabled, along with inform= ation + describing how the range should be used. + + @param MemoryMap Buffer to record details of the memory ranges. + @param NumRanges On input, this contains the maximum number of memo= ry ranges that can be described + in the MemoryMap buffer. + + @retval MemoryMap The buffer will be filled in + @retval NumRanges will contain the actual number of memory ranges th= at are to be anabled. + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetAvailableMemoryRanges ( + IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap, + IN OUT UINT8 *NumRanges + ) +{ + AMD_MEMORY_INFO_HOB *AmdMemoryInfoHob; + AMD_MEMORY_RANGE_DESCRIPTOR *Range; + UINT32 Index; + + DEBUG ((EFI_D_INFO, "GetAvailableMemoryRanges++\n")); + if ((*NumRanges) < MAX_RANGES) { + return EFI_BUFFER_TOO_SMALL; + } + + *NumRanges =3D 0; + + // Get Pointer to HOB + AmdMemoryInfoHob =3D GetFirstGuidHob (&gAmdMemoryInfoHobGuid); + ASSERT (AmdMemoryInfoHob !=3D NULL); + // Get HOB Data + AmdMemoryInfoHob =3D GET_GUID_HOB_DATA (AmdMemoryInfoHob); + if (AmdMemoryInfoHob !=3D NULL) { + for (Index =3D 0; Index < AmdMemoryInfoHob->NumberOfDescriptor; Index+= +) { + Range =3D (AMD_MEMORY_RANGE_DESCRIPTOR *)&AmdMemoryInfoHob->Ranges[I= ndex]; + if (Range->Attribute =3D=3D AMD_MEMORY_ATTRIBUTE_AVAILABLE) { + MemoryMap[*NumRanges].PhysicalAddress =3D Range->Base; + MemoryMap[*NumRanges].CpuAddress =3D Range->Base; + MemoryMap[*NumRanges].RangeLength =3D Range->Size; + MemoryMap[*NumRanges].Type =3D DualChannelDdrMainMemory; + (*NumRanges)++; + DEBUG ((EFI_D_INFO, " Base:0x%016lX, Size: 0x%016lX\n", Range->Bas= e, Range->Size)); + } + } + } + + return EFI_SUCCESS; +} + +/** + + This function returns the memory ranges to be reserved, along with infor= mation + describing how the range should be used. + + @param MemoryMap Buffer to record details of the memory ranges. + @param NumRanges On input, this contains the maximum number of memo= ry ranges that can be described + in the MemoryMap buffer. + + @retval MemoryMap The buffer will be filled in + @retval NumRanges will contain the actual number of memory ranges th= at are to be reserved. + @retval EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +GetReservedMemoryRanges ( + IN OUT PEI_DUAL_CHANNEL_DDR_MEMORY_MAP_RANGE *MemoryMap, + IN OUT UINT8 *NumRanges + ) +{ + AMD_MEMORY_INFO_HOB *AmdMemoryInfoHob; + AMD_MEMORY_RANGE_DESCRIPTOR *Range; + UINT32 Index; + + DEBUG ((EFI_D_INFO, "GetReservedMemoryRanges\n")); + if ((*NumRanges) < MAX_RANGES) { + return EFI_BUFFER_TOO_SMALL; + } + + *NumRanges =3D 0; + + // Get Pointer to HOB + AmdMemoryInfoHob =3D GetFirstGuidHob (&gAmdMemoryInfoHobGuid); + ASSERT (AmdMemoryInfoHob !=3D NULL); + // Get HOB Data + AmdMemoryInfoHob =3D GET_GUID_HOB_DATA (AmdMemoryInfoHob); + if (AmdMemoryInfoHob !=3D NULL) { + for (Index =3D 0; Index < AmdMemoryInfoHob->NumberOfDescriptor; Index+= +) { + Range =3D (AMD_MEMORY_RANGE_DESCRIPTOR *)&AmdMemoryInfoHob->Ranges[I= ndex]; + if (Range->Base > SIZE_4GB) { + if (Range->Attribute =3D=3D AMD_MEMORY_ATTRIBUTE_RESERVED) { + MemoryMap[*NumRanges].PhysicalAddress =3D Range->Base; + MemoryMap[*NumRanges].CpuAddress =3D Range->Base; + MemoryMap[*NumRanges].RangeLength =3D Range->Size; + MemoryMap[*NumRanges].Type =3D DualChannelDdrReserved= Memory; + (*NumRanges)++; + DEBUG ((EFI_D_INFO, " GetReservedMemoryRanges Base:0x%016lX, Siz= e: 0x%016lX\n", Range->Base, Range->Size)); + } + + if (Range->Attribute =3D=3D AMD_MEMORY_ATTRIBUTE_UMA) { + MemoryMap[*NumRanges].PhysicalAddress =3D Range->Base; + MemoryMap[*NumRanges].CpuAddress =3D Range->Base; + MemoryMap[*NumRanges].RangeLength =3D Range->Size; + MemoryMap[*NumRanges].Type =3D DualChannelDdrReserved= Memory; + (*NumRanges)++; + DEBUG ((EFI_D_INFO, " GetReservedMemoryRanges Base:0x%016lX, Siz= e: 0x%016lX\n", Range->Base, Range->Size)); + } + } + } + } + + return EFI_SUCCESS; +} diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformIn= it.c b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.c new file mode 100644 index 0000000000..4ff57dfca1 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.c @@ -0,0 +1,176 @@ +/** @file + Implements Platforminit.C + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file +This PEIM initialize platform for MRC, following action is performed, +1. Initizluize GMCH +2. Detect boot mode +3. Detect video adapter to determine whether we need pre allocated memory +4. Calls MRC to initialize memory and install a PPI notify to do post memo= ry initialization. +This file contains the main entrypoint of the PEIM. + +Copyright (c) 2013 - 2016 Intel Corporation. + +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 IMPLI= ED. + +**/ + +#include "CommonHeader.h" +#define PEI_STALL_RESOLUTION 1 + +EFI_PEI_STALL_PPI mStallPpi =3D { + PEI_STALL_RESOLUTION, + Stall +}; + +EFI_PEI_PPI_DESCRIPTOR mPpiStall[1] =3D { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiStallPpiGuid, + &mStallPpi + } +}; + +EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[1] =3D { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMasterBootModePpiGuid, + NULL + } +}; + +EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList[] =3D { + { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + &gAmdMemoryInfoHobPpiGuid, + MemoryInfoHobPpiNotifyCallback + }, + { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMI= NATE_LIST), + &gEfiPeiMemoryDiscoveredPpiGuid, + MemoryDiscoveredPpiNotifyCallback + } +}; + +/** + Clear all SMI enable bit in SmiControl0-SmiControl9 register + + @param [in] None + + @retval None +*/ +VOID +ClearAllSmiControlRegisters ( + VOID + ) +{ + UINTN SmiControlOffset; + + for (SmiControlOffset =3D FCH_SMI_REGA0; SmiControlOffset <=3D FCH_SMI_R= EGC4; SmiControlOffset +=3D 4) { + MmioWrite32 (ACPI_MMIO_BASE + SMI_BASE + SmiControlOffset, 0x00); + } +} + +/** + Clear any SMI status or wake status left over from boot. + + @param none + + @retval none +**/ +VOID +EFIAPI +ClearSmiAndWake ( + VOID + ) +{ + UINT16 Pm1Status; + UINT16 PmControl; + UINT16 AcpiBaseAddr; + + AcpiBaseAddr =3D MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG6= 0); + + // + // Read the ACPI registers + // + Pm1Status =3D IoRead16 (AcpiBaseAddr); + PmControl =3D IoRead16 ((UINT16)(AcpiBaseAddr + R_FCH_ACPI_PM_CONTROL)); + + // + // Clear any SMI or wake state from the boot + // + Pm1Status |=3D 0xFF; // clear all events + PmControl &=3D 0xFFFE; // clear Bit0(SciEn) in PmControl + + // + // Write them back + // + IoWrite16 (AcpiBaseAddr, Pm1Status); + IoWrite16 ((UINT16)(AcpiBaseAddr + R_FCH_ACPI_PM_CONTROL), PmControl); +} + +/** + This is the entrypoint of PEIM + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS if it completed successfully. +**/ +EFI_STATUS +EFIAPI +PeiInitPlatform ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + + Status =3D (**PeiServices).InstallPpi (PeiServices, &mPpiStall[0]); + ASSERT_EFI_ERROR (Status); + + // + // Dtermine boot mode and return boot mode. + // + BootMode =3D 0; + Status =3D UpdateBootMode (PeiServices, &BootMode); + ASSERT_EFI_ERROR (Status); + + // + // Install Boot mode ppi. + // + if (!EFI_ERROR (Status)) { + Status =3D (**PeiServices).InstallPpi (PeiServices, &mPpiBootMode[0]); + ASSERT_EFI_ERROR (Status); + } + + if ((BootMode !=3D BOOT_ON_S3_RESUME)) { + // + // Clear all pending SMI. On S3 clear power button enable so it wll no= t generate an SMI + // + ClearSmiAndWake (); + ClearAllSmiControlRegisters (); + } + + // + // Notify for memory discovery callback + // + Status =3D (**PeiServices).NotifyPpi (PeiServices, &mMemoryDiscoveredNot= ifyList[0]); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformIn= it.inf b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.i= nf new file mode 100644 index 0000000000..0941b09de3 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/PlatformInit.inf @@ -0,0 +1,114 @@ +## @file +# Platform Init Module +# +# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## +# This file includes code originally published under the following license. +## @file +# This is the Platform PEIM to initialize whole platform on PEI phase. +# Copyright (c) 2013 - 2016 Intel Corporation. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BS= D License +# which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D PlatformInitPei + FILE_GUID =3D CD33267E-CF9C-40D6-85F6-4A14AF36F739 + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PeiInitPlatform + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + BootMode.c + MemoryCallback.c + MemoryPeim.c + PlatformInit.c + MemoryInstall.c + Stall.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + ChachaniBoardPkg/Project.dec + VanGoghCommonPkg/AmdCommonPkg.dec + IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec + AgesaPublic/AgesaPublic.dec + +[LibraryClasses] + PrintLib + PcdLib + ReportStatusCodeLib + IoLib + HobLib + BaseMemoryLib + BaseLib + PeimEntryPoint + DebugLib + MemoryAllocationLib + MtrrLib + PciExpressLib + +[Guids] + gEfiAcpiVariableGuid # ALWAYS_CONSUMED L"AcpiGl= obalVariab" + gEfiMemoryTypeInformationGuid # ALWAYS_CONSUMED L"Memory= TypeInformation" + gEfiSmmPeiSmramMemoryReserveGuid # ALWAYS_PRODUCED Hob: GU= ID_EXTENSION + gAmdMemoryInfoHobGuid + gPlatformChargerPresentGuid + +[Ppis] + gEfiPeiStallPpiGuid + gEfiPeiMasterBootModePpiGuid + gEfiPeiMemoryDiscoveredPpiGuid + gEfiPeiBootInRecoveryModePpiGuid + gAmdMemoryInfoHobPpiGuid + gEfiPeiReadOnlyVariable2PpiGuid + gPeiSmmControlPpiGuid + gPeiPostScriptTablePpiGuid + gEfiEndOfPeiSignalPpiGuid + gEfiPeiCapsulePpiGuid + gAmdCpmTablePpiGuid + gCapsuleUpdateDetectedPpiGuid + +[FeaturePcd] + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress + gPcAtChipsetPkgTokenSpaceGuid.PcdIoApicBaseAddress + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress + gPlatformPkgTokenSpaceGuid.PcdFlashAreaBaseAddress + gPlatformPkgTokenSpaceGuid.PcdFlashAreaSize + gPlatformPkgTokenSpaceGuid.PcdMemoryFvRecoveryBase + gAmdCommonPkgTokenSpaceGuid.PcdMemoryFvMainSize + gPlatformPkgTokenSpaceGuid.PcdFlashFvRecoverySize + gPlatformPkgTokenSpaceGuid.PcdFlashFvMainBase + gPlatformPkgTokenSpaceGuid.PcdFlashFvMainSize + gPlatformPkgTokenSpaceGuid.PcdFlashFvMainUnCompressBase + gPlatformPkgTokenSpaceGuid.PcdFlashFvMainUnCompressSize + gEfiAmdAgesaPkgTokenSpaceGuid.PcdFchOemBeforePciRestoreSwSmi + gEfiAmdAgesaPkgTokenSpaceGuid.PcdFchOemAfterPciRestoreSwSmi + gAmdCpmPkgTokenSpaceGuid.AcpiRestoreSwSmi + gPlatformPkgTokenSpaceGuid.PcdBootState + gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection + +[Depex] + TRUE diff --git a/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Stall.c b/= Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Stall.c new file mode 100644 index 0000000000..3c7ef4e965 --- /dev/null +++ b/Platform/AMD/VanGoghBoard/Universal/PlatformInitPei/Stall.c @@ -0,0 +1,122 @@ +/** @file + Implements Stall.C + + Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* This file includes code originally published under the following licens= e. */ + +/** @file + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + + This program and the accompanying materials are licensed and made availa= ble under + + the terms and conditions of the BSD License that accompanies this distri= bution. + + 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 IMP= LIED. + + + + + + +Module Name: + + Stall.c + +Abstract: + + Produce Stall Ppi. + +--*/ +#include +#include +#include +#include "CommonHeader.h" + +#define B_FCH_ACPI_PM1_TMR_VAL 0xFFFFFF // The timer value= mask +#define V_FCH_ACPI_PM1_TMR_MAX_VAL 0x1000000 // The timer is 24= bit overflow + +/** + + Waits for at least the given number of microseconds. + + @param PeiServices General purpose services available to every PEIM. + @param This PPI instance structure. + @param Microseconds Desired length of time to wait. + + @retval EFI_SUCCESS If the desired amount of time was passed. + +*/ +EFI_STATUS +EFIAPI +Stall ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN CONST EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ) +{ + UINTN Ticks; + UINTN Counts; + UINT16 AcpiTimerPort; + UINT32 CurrentTick; + UINT32 OriginalTick; + UINT32 RemainingTick; + + if (Microseconds =3D=3D 0) { + return EFI_SUCCESS; + } + + AcpiTimerPort =3D MmioRead16 (ACPI_MMIO_BASE + PMIO_BASE + FCH_PMIOA_REG= 64); + + OriginalTick =3D IoRead32 (AcpiTimerPort); + OriginalTick &=3D (V_FCH_ACPI_PM1_TMR_MAX_VAL - 1); + CurrentTick =3D OriginalTick; + + // + // The timer frequency is 3.579545MHz, so 1 ms corresponds to 3.58 clocks + // + Ticks =3D Microseconds * 358 / 100 + OriginalTick + 1; + + // + // The loops needed for timer overflow + // + Counts =3D (UINTN)RShiftU64 ((UINT64)Ticks, 24); + + // + // Remaining clocks within one loop + // + RemainingTick =3D Ticks & 0xFFFFFF; + + // + // Do not intend to use TMROF_STS bit of register PM1_STS, because this = add extra + // one I/O operation, and may generate SMI + // + while (Counts !=3D 0) { + CurrentTick =3D IoRead32 (AcpiTimerPort) & B_FCH_ACPI_PM1_TMR_VAL; + if (CurrentTick <=3D OriginalTick) { + Counts--; + } + + OriginalTick =3D CurrentTick; + } + + while ((RemainingTick > CurrentTick) && (OriginalTick <=3D CurrentTick))= { + OriginalTick =3D CurrentTick; + CurrentTick =3D IoRead32 (AcpiTimerPort) & B_FCH_ACPI_PM1_TMR_VAL; + } + + return EFI_SUCCESS; +} -- 2.31.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#114075): https://edk2.groups.io/g/devel/message/114075 Mute This Topic: https://groups.io/mt/103831198/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-