From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.107.94.93]) by mx.groups.io with SMTP id smtpd.web12.4046.1607505855319270284 for ; Wed, 09 Dec 2020 01:24:15 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@os.amperecomputing.com header.s=selector2 header.b=rg0v1ymR; spf=pass (domain: os.amperecomputing.com, ip: 40.107.94.93, mailfrom: nhi@os.amperecomputing.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=QjeEda4CpqvwHGSCcLWnqfbKMAeDd/R9sSJYAcdyw4QxOOdISbSezEP46YTsj70NI+2fnRI4ImFFl99b78KfOMO888UmndRUL/vKhH7mVpQDzHdTzjTyVmsrAwnOe4KhtsjyfUTyW1/8bLGITUuYiORrJiXS5R9LIbvELUSpfJizeC0TTZoe10omMyBpmQeaxHnLgBf9xgqkset1zydt+cWoGam/7vWg7qPR2pKoTWZo3Mj7VdbvZHH4DQQgSR1OjhO7nb9PTrzNB5ulcgYcHO366WOlPV1wR9j1pe9dRQsyxZqph8PwNn8uxK4J090PQm/qVrisc0+k44JFfnES9g== 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-SenderADCheck; bh=klyHBpFsvDCA4I8XxpnoAtgi2eZU1sBaOVO/9jtzpmM=; b=fPKTn37cxa86Gz5F9x5L08ASRqKEsx/IlH01kbuhfLi7nf6rU9BUu7Nk6qcOp82O3uiThZf/hLRSUtwA6bDvW8r6H/+xG0rRs13wQFE7i91YEmHWZkN3tokRYfOF6AP6Wvqf9rtBj8hyR0NEfDzsitQOZXQ69Rt0BgjrzU4pRj+csDrM0fuowPE6kO5yVL6GVljoeEVCOI+IdpBhNI6nO8B0nJncAh5NYbN2MXFEBRGvBlS+jdN1T/59Y0IpqJG8ORSL93WD5wjzb1xODN78xuM+46xRHmhrbx4LYe09+TYcfUHzdakXMl1U44i2qLZQ/kiEO84yaHayu3OKw4f5jg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=os.amperecomputing.com; dmarc=pass action=none header.from=os.amperecomputing.com; dkim=pass header.d=os.amperecomputing.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=os.amperecomputing.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=klyHBpFsvDCA4I8XxpnoAtgi2eZU1sBaOVO/9jtzpmM=; b=rg0v1ymRkok8TDI69ntwnq38h8F94qaLMur8AYIkKJ6hB4kDvhMbIVMo9VD+QT75idOeX6VHa2xRB/L7k6pTim2uG31eaB30rTvm0pTl4uWpi0V7eyvFhFVQqJ8sN9FLDtZyZcsdnlawite9AT8x6z/SUOlaaKx5nnbpaOMZfgg= Authentication-Results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=os.amperecomputing.com; Received: from DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) by DM6PR01MB5609.prod.exchangelabs.com (2603:10b6:5:157::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3632.21; Wed, 9 Dec 2020 09:24:13 +0000 Received: from DM6PR01MB5849.prod.exchangelabs.com ([fe80::c814:9a08:5c2e:4076]) by DM6PR01MB5849.prod.exchangelabs.com ([fe80::c814:9a08:5c2e:4076%5]) with mapi id 15.20.3632.023; Wed, 9 Dec 2020 09:24:13 +0000 From: "Nhi Pham" To: devel@edk2.groups.io Cc: Nhi Pham Subject: [edk2-platforms][PATCH 02/34] Platform/Ampere: Implement FailSafe library Date: Wed, 9 Dec 2020 16:24:59 +0700 Message-Id: <20201209092531.30867-3-nhi@os.amperecomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201209092531.30867-1-nhi@os.amperecomputing.com> References: <20201209092531.30867-1-nhi@os.amperecomputing.com> X-Originating-IP: [118.69.219.201] X-ClientProxiedBy: HK0PR01CA0054.apcprd01.prod.exchangelabs.com (2603:1096:203:a6::18) To DM6PR01MB5849.prod.exchangelabs.com (2603:10b6:5:205::20) Return-Path: nhi@os.amperecomputing.com MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from sw004.amperecomputing.com (118.69.219.201) by HK0PR01CA0054.apcprd01.prod.exchangelabs.com (2603:1096:203:a6::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3654.12 via Frontend Transport; Wed, 9 Dec 2020 09:24:11 +0000 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: ac385836-548c-4b34-93b3-08d89c243156 X-MS-TrafficTypeDiagnostic: DM6PR01MB5609: X-MS-Exchange-Transport-Forked: True X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:3968; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: esqeWu7gaGcEZHuhD4Og89Jgwn4kXVJZ1vp2douTLthMIFBCI8nC6+cP98E/Sa0RrNH7GWmFSb00i5BGyZS4ZZJskjMLqjW2ffKYHNBaodzNmdoDdu/3r/CtYli56eb8Csshguj81WZ8pq1WQBhn1eL/ieE0bLQUxoJQkMV7/Pzr5EPa+EJ9zz+3yTkBSBGYuEZWZApVWf1DkFQzRpRDB5LDZX4ojTE5nMb27KcI8rYoIosM8ngMoHOGw+m5f9twNvBf3d2fBJ8VBXjc4DKxHimUKEWRpDcw8fOsRbdnk0W1qAcZ3tIvs1sRcGB7S+xmnK67LmcPj+6wYDCkPOZyQeITgpF0RiI6HJe3H0IQWwAnFw1uzNDqTDjmaB+Zh4M9 X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR01MB5849.prod.exchangelabs.com;PTR:;CAT:NONE;SFS:(4636009)(376002)(136003)(346002)(366004)(5660300002)(956004)(508600001)(52116002)(30864003)(66946007)(6916009)(2616005)(1076003)(19627235002)(86362001)(6512007)(66476007)(26005)(8936002)(16526019)(107886003)(6666004)(186003)(6486002)(8676002)(6506007)(83380400001)(2906002)(34490700003)(66556008)(4326008);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData: =?us-ascii?Q?ZZ6NhPe+iIF3IZ691FehyhPzPJl5aRfDZD79O4vGIX8HoQlqL3vZwWCmyImT?= =?us-ascii?Q?wAniZfmS0nn9280p8wzVuzYy0+sKsi9F3pHJZCMH7FkA9Qk5B29ZvnLo/A2z?= =?us-ascii?Q?2/lXoYPAZeu+gnXNb7SXeklCn9LtApes/6toSZho68GeDljV4YoAyF22GyTf?= =?us-ascii?Q?ZQQt8rNxCo34QeSNQl9McdKhY5SO0ymm2gFYQVaqJXNn0q5Zmn0Doq70SnpI?= =?us-ascii?Q?/mZBQBaAMZmTCyrAum2TJhP2ymKIOreIUPmKarv/zl3dg00DtrEsqaTV9BS/?= =?us-ascii?Q?ZQd8cgWnzb834tQo4Xt23qhK2IVXpNHRnWCkO6tZ4+bROw3FlMt+UBpVmMOP?= =?us-ascii?Q?YsvZZ1Sl/lDJLT6RZr1WQtPcL9Yj1AA+voD1c4FEYZcyxQctyuP+YBJ1gtXm?= =?us-ascii?Q?DHmX6LeuGwd9bP7txc4qa4l2/hC6HHSjejwUcTIjo+S94iJNNDcDsqtmXROH?= =?us-ascii?Q?wty7HZF/mGIb8XvcQUNhElBUuxzRtDI5NfvWegm3PutiDQdFEmhQ6DRTDpDB?= =?us-ascii?Q?Fv/HAYGBjC3ds9rZh2zHeXvZfQqBzSA5TfVX+oYcvQyjNJzmqd/8XKFE5CGx?= =?us-ascii?Q?bDBOIms39MtdMA08eRNdCITo9gJnl8K9V5KytLPA+qhJmMlKFcPhu2W09DZS?= =?us-ascii?Q?zVxMZHAyKbB5fSGVuuMps/q6NvtfBIluGWyCntLygrYDEFnO5ChTF6L56AuQ?= =?us-ascii?Q?CVHf3FPkflU/T/ZJRrZWkoMbD+gWm8FOh4fVz7DJaMcwxfWh0sX3Ww+mV2uP?= =?us-ascii?Q?UANChKmz6e1oVBvo8TalvV3GbP0zT5vKxuB1Hs/qOcODueUd06W6VUwRRagu?= =?us-ascii?Q?c2NobgQXaKoR4ZGihUKwQpUMwVg+hmvp2Lt5eH6q5yxVyEHeYsf+Wc/R2BT8?= =?us-ascii?Q?ZoNjwElpH0GlGAjsJzBjySXHyOgS/Y2CIdm7+joyHsmpfmME+feMBcrKXEnM?= =?us-ascii?Q?YSDVzhKOBegtOJP2Zxhkk+pOz2a3bugqYgAq/C+wysM4Urs/7NP8dxLzz9f8?= =?us-ascii?Q?+1hi?= X-OriginatorOrg: os.amperecomputing.com X-MS-Exchange-CrossTenant-AuthSource: DM6PR01MB5849.prod.exchangelabs.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Dec 2020 09:24:13.1919 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3bc2b170-fd94-476d-b0ce-4229bdc904a7 X-MS-Exchange-CrossTenant-Network-Message-Id: ac385836-548c-4b34-93b3-08d89c243156 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: K2gYKGxlxcCs8G2BYH3ROWHcquY9J1qaqkSIfjB4CnSLDg1yWBbQVr1Cs0l8hll3lt4g37X6hVReSO5qsoEfeKg2po9ltTCQQbpYuhLzqG4= X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR01MB5609 Content-Type: text/plain The FailSafeLib support API calls to Secure World to: * Get the FailSafe region information. * Get the current FailSafe status. * Inform to FailSafe monitor that the system boots successfully. * Simulate UEFI boot failure due to config wrong NVPARAM for testing failsafe feature. This library is consumed by FailSafe DXE driver. Signed-off-by: Nhi Pham --- Platform/Ampere/AmperePkg.dec | 3 + Platform/Ampere/Library/FailSafeLib/FailSafeLib.inf | 41 +++ Platform/Ampere/Include/Library/FailSafeLib.h | 64 +++++ Platform/Ampere/Library/FailSafeLib/FailSafeLib.c | 267 ++++++++++++++++++++ 4 files changed, 375 insertions(+) diff --git a/Platform/Ampere/AmperePkg.dec b/Platform/Ampere/AmperePkg.dec index e6a73b25286c..472b44550fee 100755 --- a/Platform/Ampere/AmperePkg.dec +++ b/Platform/Ampere/AmperePkg.dec @@ -22,7 +22,10 @@ [Defines] # ################################################################################ [Includes] + Include # Root include for the package [LibraryClasses] + ## @libraryclass Provides functions to support FailSafe operations. + FailSafeLib|Platform/Ampere/Include/Library/FailSafeLib.h [Guids] diff --git a/Platform/Ampere/Library/FailSafeLib/FailSafeLib.inf b/Platform/Ampere/Library/FailSafeLib/FailSafeLib.inf new file mode 100755 index 000000000000..3ce0c2209cf1 --- /dev/null +++ b/Platform/Ampere/Library/FailSafeLib/FailSafeLib.inf @@ -0,0 +1,41 @@ +## @file +# +# Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = FailSafeLib + FILE_GUID = 3403D080-6D76-11E7-907B-A6006AD3DBA0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FailSafeLib + +[Sources] + FailSafeLib.c + +[Protocols] + gEfiMmCommunicationProtocolGuid ## CONSUMES + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + MdePkg/MdePkg.dec + Silicon/Ampere/AmperePkg.dec + Silicon/Ampere/AmpereAltraPkg/Ac01Pkg.dec + Platform/Ampere/AmperePkg.dec + +[LibraryClasses] + IoLib + DebugLib + BaseLib + BaseMemoryLib + ArmSmcLib + HobLib + NVParamLib + +[Guids] + gSpiNorMmGuid diff --git a/Platform/Ampere/Include/Library/FailSafeLib.h b/Platform/Ampere/Include/Library/FailSafeLib.h new file mode 100755 index 000000000000..6319284e5ecd --- /dev/null +++ b/Platform/Ampere/Include/Library/FailSafeLib.h @@ -0,0 +1,64 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _FAILSAFE_LIB_H_ +#define _FAILSAFE_LIB_H_ + +enum { + MM_SPINOR_FUNC_GET_INFO, + MM_SPINOR_FUNC_READ, + MM_SPINOR_FUNC_WRITE, + MM_SPINOR_FUNC_ERASE, + MM_SPINOR_FUNC_GET_NVRAM_INFO, + MM_SPINOR_FUNC_GET_NVRAM2_INFO, + MM_SPINOR_FUNC_GET_FAILSAFE_INFO +}; + +#define MM_SPINOR_RES_SUCCESS 0xAABBCC00 +#define MM_SPINOR_RES_FAIL 0xAABBCCFF + +enum { + FAILSAFE_BOOT_NORMAL = 0, + FAILSAFE_BOOT_LAST_KNOWN_SETTINGS, + FAILSAFE_BOOT_DEFAULT_SETTINGS, + FAILSAFE_BOOT_SUCCESSFUL +}; + +/** + Get the FailSafe region information. +**/ +EFI_STATUS +EFIAPI +FailSafeGetRegionInfo ( + UINT64 *Offset, + UINT64 *Size + ); + +/** + Get the current FailSafe status. +**/ +UINT64 +EFIAPI +FailSafeGetStatus (VOID); + +/** + Inform to FailSafe monitor that the system boots successfully. +**/ +EFI_STATUS +EFIAPI +FailSafeBootSuccessfully (VOID); + +/** + Simulate UEFI boot failure due to config wrong NVPARAM for + testing failsafe feature +**/ +EFI_STATUS +EFIAPI +FailSafeTestBootFailure (VOID); + +#endif /* _FAILSAFE_LIB_H_ */ diff --git a/Platform/Ampere/Library/FailSafeLib/FailSafeLib.c b/Platform/Ampere/Library/FailSafeLib/FailSafeLib.c new file mode 100755 index 000000000000..244c0b49d085 --- /dev/null +++ b/Platform/Ampere/Library/FailSafeLib/FailSafeLib.c @@ -0,0 +1,267 @@ +/** @file + + Copyright (c) 2020, Ampere Computing LLC. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFI_MM_MAX_PAYLOAD_U64_E 10 +#define EFI_MM_MAX_PAYLOAD_SIZE (EFI_MM_MAX_PAYLOAD_U64_E * sizeof (UINT64)) + +EFI_MM_COMMUNICATION_PROTOCOL *mFlashLibMmCommProtocol = NULL; + +typedef struct { + /* Allows for disambiguation of the message format */ + EFI_GUID HeaderGuid; + /* + * Describes the size of Data (in bytes) and does not include the size + * of the header + */ + UINTN MsgLength; +} EFI_MM_COMM_HEADER_NOPAYLOAD; + +typedef struct { + UINT64 Data[EFI_MM_MAX_PAYLOAD_U64_E]; +} EFI_MM_COMM_SPINOR_PAYLOAD; + +typedef struct { + EFI_MM_COMM_HEADER_NOPAYLOAD EfiMmHdr; + EFI_MM_COMM_SPINOR_PAYLOAD PayLoad; +} EFI_MM_COMM_REQUEST; + +typedef struct { + UINT64 Status; +} EFI_MM_COMMUNICATE_SPINOR_RES; + +typedef struct { + UINT64 Status; + UINT64 FailSafeBase; + UINT64 FailSafeSize; +} EFI_MM_COMMUNICATE_SPINOR_FAILSAFE_INFO_RES; + +EFI_MM_COMM_REQUEST mEfiMmSpiNorReq; + +typedef struct { + UINT32 NumRetry1; + UINT32 NumRetry2; + UINT32 MaxRetry; + UINT8 Status; + /* + * Byte[3]: Reserved + * Byte[2]: Slave MCU Failure Mask + * Byte[1]: Reserved + * Byte[0]: Master MCU Failure Mask + */ + UINT32 MCUFailsMask; + UINT16 CRC16; +} __attribute__((packed, aligned(4))) FailsafeCtx_t; + +STATIC +EFI_STATUS +UefiMmCreateSpiNorReq ( + VOID *Data, + UINT64 Size + ) +{ + CopyGuid (&mEfiMmSpiNorReq.EfiMmHdr.HeaderGuid, &gSpiNorMmGuid); + mEfiMmSpiNorReq.EfiMmHdr.MsgLength = Size; + + if (Size != 0) { + ASSERT (Data); + ASSERT (Size <= EFI_MM_MAX_PAYLOAD_SIZE); + + CopyMem (mEfiMmSpiNorReq.PayLoad.Data, Data, Size); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FailSafeGetRegionInfo ( + UINT64 *Offset, + UINT64 *Size + ) +{ + EFI_MM_COMMUNICATE_SPINOR_FAILSAFE_INFO_RES *MmSpiNorFailSafeInfoRes; + UINT64 MmData[5]; + UINTN DataSize; + EFI_STATUS Status; + + if (mFlashLibMmCommProtocol == NULL) { + Status = gBS->LocateProtocol ( + &gEfiMmCommunicationProtocolGuid, + NULL, + (VOID **) &mFlashLibMmCommProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Can't locate gEfiMmCommunicationProtocolGuid\n", __FUNCTION__)); + return Status; + } + } + + MmData[0] = MM_SPINOR_FUNC_GET_FAILSAFE_INFO; + UefiMmCreateSpiNorReq ((VOID *) &MmData, sizeof (MmData)); + + DataSize = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); + Status = mFlashLibMmCommProtocol->Communicate ( + mFlashLibMmCommProtocol, + (VOID *) &mEfiMmSpiNorReq, + &DataSize + ); + ASSERT_EFI_ERROR (Status); + + MmSpiNorFailSafeInfoRes = (EFI_MM_COMMUNICATE_SPINOR_FAILSAFE_INFO_RES *) &mEfiMmSpiNorReq.PayLoad; + if (MmSpiNorFailSafeInfoRes->Status != MM_SPINOR_RES_SUCCESS) { + DEBUG ((DEBUG_ERROR, "%a: Get flash information failed: %d\n", + __FUNCTION__, + MmSpiNorFailSafeInfoRes->Status)); + return EFI_DEVICE_ERROR; + } + + *Offset = MmSpiNorFailSafeInfoRes->FailSafeBase; + *Size = MmSpiNorFailSafeInfoRes->FailSafeSize; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FailSafeBootSuccessfully (VOID) +{ + EFI_MM_COMMUNICATE_SPINOR_RES *MmSpiNorRes; + UINT64 MmData[5]; + UINTN Size; + EFI_STATUS Status; + UINT64 FailSafeStartOffset; + UINT64 FailSafeSize; + + Status = FailSafeGetRegionInfo (&FailSafeStartOffset, &FailSafeSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get context region information\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + ASSERT (mFlashLibMmCommProtocol != NULL); + + MmData[0] = MM_SPINOR_FUNC_ERASE; + MmData[1] = FailSafeStartOffset; + MmData[2] = FailSafeSize; + UefiMmCreateSpiNorReq ((VOID *) &MmData, sizeof (MmData)); + + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); + Status = mFlashLibMmCommProtocol->Communicate ( + mFlashLibMmCommProtocol, + (VOID *) &mEfiMmSpiNorReq, + &Size + ); + ASSERT_EFI_ERROR (Status); + + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *) &mEfiMmSpiNorReq.PayLoad; + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { + DEBUG ((DEBUG_ERROR, "%a: erase context failed: %d\n", + __FUNCTION__, + MmSpiNorRes->Status)); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +UINT8 +FailSafeValidStatus ( + IN UINT8 Status + ) +{ + if ((Status == FAILSAFE_BOOT_NORMAL) || + (Status == FAILSAFE_BOOT_LAST_KNOWN_SETTINGS) || + (Status == FAILSAFE_BOOT_DEFAULT_SETTINGS) || + (Status == FAILSAFE_BOOT_SUCCESSFUL)) { + return 1; + } + + return 0; +} + +UINT64 +EFIAPI +FailSafeGetStatus (VOID) +{ + EFI_MM_COMMUNICATE_SPINOR_RES *MmSpiNorRes; + UINT64 MmData[5]; + UINTN Size; + EFI_STATUS Status; + UINT64 FailSafeStartOffset; + UINT64 FailSafeSize; + FailsafeCtx_t FailsafeBuf; + + Status = FailSafeGetRegionInfo (&FailSafeStartOffset, &FailSafeSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to get region information\n", __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + ASSERT (mFlashLibMmCommProtocol != NULL); + + MmData[0] = MM_SPINOR_FUNC_READ; + MmData[1] = FailSafeStartOffset; + MmData[2] = (UINT64) sizeof (FailsafeCtx_t); + MmData[3] = (UINT64) &FailsafeBuf; + UefiMmCreateSpiNorReq ((VOID *)&MmData, sizeof(MmData)); + + Size = sizeof (EFI_MM_COMM_HEADER_NOPAYLOAD) + sizeof (MmData); + Status = mFlashLibMmCommProtocol->Communicate ( + mFlashLibMmCommProtocol, + (VOID *) &mEfiMmSpiNorReq, + &Size + ); + ASSERT_EFI_ERROR (Status); + + MmSpiNorRes = (EFI_MM_COMMUNICATE_SPINOR_RES *) &mEfiMmSpiNorReq.PayLoad; + if (MmSpiNorRes->Status != MM_SPINOR_RES_SUCCESS) { + DEBUG ((DEBUG_ERROR, "%a: read context failed: %d\n", + __FUNCTION__, + MmSpiNorRes->Status)); + return EFI_DEVICE_ERROR; + } + + if (FailSafeValidStatus (FailsafeBuf.Status) == 0) { + FailsafeBuf.Status = FAILSAFE_BOOT_NORMAL; + } + + return FailsafeBuf.Status; +} + +EFI_STATUS +EFIAPI +FailSafeTestBootFailure (VOID) +{ + EFI_STATUS Status; + UINT32 Value = 0; + + /* + * Simulate UEFI boot failure due to config wrong NVPARAM for + * testing failsafe feature + */ + Status = NVParamGet (NV_UEFI_FAILURE_FAILSAFE_OFFSET, NV_PERM_ALL, &Value); + if (!EFI_ERROR (Status) && (Value == 1)) { + while (1); + } + + return EFI_SUCCESS; +} -- 2.17.1