[edk2-devel] [edk2-platforms][PATCH 02/34] Platform/Ampere: Implement FailSafe library

Nhi Pham via groups.io nhi=os.amperecomputing.com at groups.io
Wed Dec 9 09:24:59 UTC 2020


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 <nhi at os.amperecomputing.com>
---
 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.<BR>
+#
+# 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.<BR>
+
+  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.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiRuntimeLib.h>
+#include <PiPei.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Library/FailSafeLib.h>
+#include <Library/NVParamLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/MmCommunication.h>
+#include <Platform/Ac01.h>
+
+#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



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#68500): https://edk2.groups.io/g/devel/message/68500
Mute This Topic: https://groups.io/mt/78825481/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list