public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "levi.yun" <yeoreum.yun@arm.com>
To: devel@edk2.groups.io
Cc: yeoreum.yun@arm.com, sami.mujawar@arm.com,
	pierre.gondois@arm.com, zhiguang.liu@intel.com,
	dandan.bi@intel.com, gaoliming@byosoft.com.cn,
	zhichao.gao@intel.com, nd@arm.com
Subject: [edk2-devel] [PATCH v1 4/4] ShellPkg/Acpiview: Add EINJ Parser
Date: Fri, 10 May 2024 13:22:57 +0100	[thread overview]
Message-ID: <20240510122257.2457623-5-yeoreum.yun@arm.com> (raw)
In-Reply-To: <20240510122257.2457623-1-yeoreum.yun@arm.com>

Add a new parser for the Error Injection Table (EINJ).

The EINJ table provides machinism through which OSPM
can inject hardware errors to the platform without requiring platform
specific OSPM software.

Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhichao Gao <zhichao.gao@intel.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Cc: Pierre Gondois <pierre.gondois@arm.com>
Signed-off-by: levi.yun <yeoreum.yun@arm.com>
---
 ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf |   1 +
 ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h                    |  21 ++
 ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Einj/EinjParser.c       | 358 ++++++++++++++++++++
 ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c   |   1 +
 4 files changed, 381 insertions(+)

diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
index e62366116cb7d90c9202c6f0fd17b3306efd7800..9c2e2b703d267fb3ed9d631469d907106e7d4278 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
@@ -33,6 +33,7 @@ [Sources.common]
   Parsers/Bgrt/BgrtParser.c
   Parsers/Dbg2/Dbg2Parser.c
   Parsers/Dsdt/DsdtParser.c
+  Parsers/Einj/EinjParser.c
   Parsers/Erst/ErstParser.c
   Parsers/Facs/FacsParser.c
   Parsers/Fadt/FadtParser.c
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
index 6468fe5d8cddf02d67f2d4705369064046c4a9a1..b41f110f6aa18f4f6806c849737f0b540a11152f 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
@@ -616,6 +616,27 @@ ParseAcpiDsdt (
   IN UINT8    AcpiTableRevision
   );
 
+/**
+  This function parses the EINJ table.
+  When trace is enabled this function parses the EINJ table and
+  traces the ACPI table fields.
+
+  This function also performs validation of the ACPI table fields.
+
+  @param [in] Trace              If TRUE, trace the ACPI fields.
+  @param [in] Ptr                Pointer to the start of the buffer.
+  @param [in] AcpiTableLength    Length of the ACPI table.
+  @param [in] AcpiTableRevision  Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiEinj (
+  IN BOOLEAN  Trace,
+  IN UINT8    *Ptr,
+  IN UINT32   AcpiTableLength,
+  IN UINT8    AcpiTableRevision
+  );
+
 /**
   This function parses the ACPI ERST table.
   When trace is enabled this function parses the ERST table and
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Einj/EinjParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Einj/EinjParser.c
new file mode 100644
index 0000000000000000000000000000000000000000..508b082f908d76dc46e6ce92d9b4aa6c15998f95
--- /dev/null
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Einj/EinjParser.c
@@ -0,0 +1,358 @@
+/** @file
+  EINJ table parser
+
+  Copyright (c) 2024, Arm Limited.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Specification Reference:
+    - ACPI 6.5, Table 18.3.2 ACPI Error Source
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiView.h"
+
+STATIC ACPI_DESCRIPTION_HEADER_INFO  mAcpiHdrInfo;
+STATIC UINT32                        *mEinjInjectionHdrSize;
+STATIC UINT32                        *mEinjInjectionEntryCnt;
+
+STATIC CONST CHAR16  *InstNameTable[] = {
+  L"READ_REGISTER",
+  L"READ_REGISTER_VALUE",
+  L"WRITE_REGISTER",
+  L"WRITE_REGISTER_VALUE",
+  L"NOOP",
+};
+
+/**
+  This function validates the flags field in the EINJ injection header.
+
+  @param [in] Ptr     Pointer to the start of the field data.
+  @param [in] Context Pointer to context specific information e.g. this
+                      could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateInjectionFlags (
+  IN UINT8  *Ptr,
+  IN VOID   *Context
+  )
+{
+  UINT8  Flags;
+
+  Flags = *(UINT8 *)Ptr;
+
+  if (Flags != 0) {
+    IncrementErrorCount ();
+    Print (L"\nERROR: Injection Flags must be zero...");
+  }
+}
+
+/**
+  An ACPI_PARSER array describing the ACPI EINJ Table.
+**/
+STATIC CONST ACPI_PARSER  EinjParser[] = {
+  PARSE_ACPI_HEADER (&mAcpiHdrInfo),
+  { L"Injection Header Size",       4,  36, L"%d",   NULL, (VOID **)&mEinjInjectionHdrSize,
+    NULL,                           NULL },
+  { L"Injection Flags",             1,  40, L"0x%x", NULL, NULL,                            ValidateInjectionFlags,NULL },
+  { L"Reserved",                    3,  41, NULL,    NULL, NULL,                            NULL,  NULL },
+  { L"Injection Entry Count",       4,  44, L"%d",   NULL, (VOID **)&mEinjInjectionEntryCnt,
+    NULL,                           NULL },
+  /// Injection Action Table.
+  /// ...
+};
+
+/**
+  This function validates the injection action field in
+  the EINJ injection instruction entry.
+
+  @param [in] Ptr     Pointer to the start of the field data.
+  @param [in] Context Pointer to context specific information e.g. this
+                      could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateInjectionAction (
+  IN UINT8  *Ptr,
+  IN VOID   *Context
+  )
+{
+  UINT8  InjectionAction;
+  UINT8  MaxInjectionAction;
+
+  InjectionAction = *(UINT8 *)Ptr;
+
+  /**
+   * EFI_ACPI_6_5_EINJ_TRIGGER_ERROR is only used Trigger Action Table
+   * not used in Injection Action Table in EINJ.
+   * Cf ACPI 6.5 Table 18.24 - Error Injection Table
+   * Cf ACPI 6.5 Table 18.36 - Trigger Error Action
+   */
+  if (*mAcpiHdrInfo.Revision < EFI_ACPI_6_5_ERROR_INJECTION_TABLE_REVISION) {
+    MaxInjectionAction = EFI_ACPI_6_5_EINJ_GET_EXECUTE_OPERATION_TIMINGS;
+  } else {
+    MaxInjectionAction = EFI_ACPI_6_5_EINJ_EINJV2_GET_ERROR_TYPE;
+  }
+
+  if ((InjectionAction < EFI_ACPI_6_5_EINJ_BEGIN_INJECTION_OPERATION) ||
+      (InjectionAction > MaxInjectionAction))
+  {
+    IncrementErrorCount ();
+    Print (L"\nERROR: Invalid Injection Action(0x%x)...", InjectionAction);
+  }
+}
+
+/**
+  This function validates the instruction field in
+  the EINJ injection instruction entry.
+
+  @param [in] Ptr     Pointer to the start of the field data.
+  @param [in] Context Pointer to context specific information e.g. this
+                      could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateInstruction (
+  IN UINT8  *Ptr,
+  IN VOID   *Context
+  )
+{
+  UINT8  Inst;
+
+  Inst = *Ptr;
+
+  if (*mAcpiHdrInfo.Revision <= EFI_ACPI_6_5_ERROR_INJECTION_TABLE_REVISION) {
+    if (Inst > EFI_ACPI_6_5_EINJ_NOOP) {
+      IncrementErrorCount ();
+      Print (L"\nERROR: Invalid Instruction(0x%x)...", Inst);
+    }
+  }
+}
+
+/**
+  This function validates the register region field in
+  the EINJ injection instruction entry.
+
+  @param [in] Ptr     Pointer to the start of the field data.
+  @param [in] Context Pointer to context specific information e.g. this
+                      could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRegisterRegion (
+  IN UINT8  *Ptr,
+  IN VOID   *Context
+  )
+{
+  EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE  *RegisterRegion;
+
+  RegisterRegion = (EFI_ACPI_6_5_GENERIC_ADDRESS_STRUCTURE *)Ptr;
+
+  if ((RegisterRegion->AddressSpaceId != EFI_ACPI_6_5_SYSTEM_MEMORY) &&
+      (RegisterRegion->AddressSpaceId != EFI_ACPI_6_5_SYSTEM_IO))
+  {
+    IncrementErrorCount ();
+    Print (L"\nERROR: Register Region Must be SYSTEM_MEMORY or SYSTEM_IO...");
+  }
+}
+
+/**
+  Dumps the injection action fields in injection instruction entry.
+
+  @param [in] Format  Optional format string for tracing the data.
+  @param [in] Ptr     Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpInjectionInstAction (
+  IN CONST CHAR16  *Format OPTIONAL,
+  IN UINT8         *Ptr
+  )
+{
+  UINT8         InjectionAction;
+  CONST CHAR16  *ActionName;
+
+  InjectionAction = *Ptr;
+
+  switch (InjectionAction) {
+    case EFI_ACPI_6_5_EINJ_BEGIN_INJECTION_OPERATION:
+      ActionName = L"BEGIN_INJECTION_OPERATION";
+      break;
+    case EFI_ACPI_6_5_EINJ_GET_TRIGGER_ERROR_ACTION_TABLE:
+      ActionName = L"GET_TRIGGER_ERROR_ACTION_TABLE";
+      break;
+    case EFI_ACPI_6_5_EINJ_SET_ERROR_TYPE:
+      ActionName = L"SET_ERROR_TYPE";
+      break;
+    case EFI_ACPI_6_5_EINJ_GET_ERROR_TYPE:
+      ActionName = L"GET_ERROR_TYPE";
+      break;
+    case EFI_ACPI_6_5_EINJ_END_OPERATION:
+      ActionName = L"END_OPERATION";
+      break;
+    case EFI_ACPI_6_5_EINJ_EXECUTE_OPERATION:
+      ActionName = L"EXECUTE_OPERATION";
+      break;
+    case EFI_ACPI_6_5_EINJ_CHECK_BUSY_STATUS:
+      ActionName = L"CHECK_BUSY_STATUS";
+      break;
+    case EFI_ACPI_6_5_EINJ_GET_COMMAND_STATUS:
+      ActionName = L"GET_COMMAND_STATUS";
+      break;
+    case EFI_ACPI_6_5_EINJ_SET_ERROR_TYPE_WITH_ADDRESS:
+      ActionName = L"SET_ERROR_TYPE_WITH_ADDRESS";
+      break;
+    case EFI_ACPI_6_5_EINJ_GET_EXECUTE_OPERATION_TIMINGS:
+      ActionName = L"GET_EXECUTE_OPERATION_TIMINGS";
+      break;
+    case EFI_ACPI_6_5_EINJ_EINJV2_SET_ERROR_TYPE:
+      ActionName = L"EINJV2_SET_ERROR_TYPE";
+      break;
+    case EFI_ACPI_6_5_EINJ_EINJV2_GET_ERROR_TYPE:
+      ActionName = L"EINJV2_GET_ERROR_TYPE";
+      break;
+    case EFI_ACPI_6_5_EINJ_TRIGGER_ERROR:
+      ActionName = L"TRIGGER_ERROR";
+      break;
+    default:
+      IncrementErrorCount ();
+      ActionName = L"UNKNOWN";
+  }
+
+  Print (L"%s(0x%x)", ActionName, InjectionAction);
+}
+
+/**
+  Dumps the instruction fields in injection instruction entry.
+
+  @param [in] Format  Optional format string for tracing the data.
+  @param [in] Ptr     Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpInstruction (
+  IN CONST CHAR16  *Format OPTIONAL,
+  IN UINT8         *Ptr
+  )
+{
+  UINT8         Inst;
+  CONST CHAR16  *InstName;
+
+  Inst = *Ptr;
+
+  if (Inst < ARRAY_SIZE (InstNameTable)) {
+    InstName = InstNameTable[Inst];
+  } else {
+    IncrementErrorCount ();
+    InstName = L"UNKNOWN";
+  }
+
+  Print (L"%s(0x%x)", InstName, Inst);
+}
+
+/**
+  An ACPI_PARSER array describing the EINJ Injection instruction entry.
+**/
+STATIC CONST ACPI_PARSER  EinjInjectionInstEntryParser[] = {
+  { L"Injection Action", 1,  0,  NULL,    DumpInjectionInstAction, NULL,
+    ValidateInjectionAction, NULL },
+  { L"Instruction",      1,  1,  NULL,    DumpInstruction,         NULL,
+    ValidateInstruction, NULL },
+  { L"Flags",            1,  2,  L"0x%x", NULL,                    NULL,NULL,  NULL },
+  { L"Reserved",         1,  3,  NULL,    NULL,                    NULL,NULL,  NULL },
+  { L"Register Region",  12, 4,  NULL,    DumpGas,                 NULL,
+    ValidateRegisterRegion, NULL },
+  { L"Value",            8,  16, L"0x%x", NULL,                    NULL,NULL,  NULL },
+  { L"Mask",             8,  24, L"0x%x", NULL,                    NULL,NULL,  NULL },
+};
+
+/**
+  This function parses the EINJ table.
+  When trace is enabled this function parses the EINJ table and
+  traces the ACPI table fields.
+
+  This function also performs validation of the ACPI table fields.
+
+  @param [in] Trace              If TRUE, trace the ACPI fields.
+  @param [in] Ptr                Pointer to the start of the buffer.
+  @param [in] AcpiTableLength    Length of the ACPI table.
+  @param [in] AcpiTableRevision  Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiEinj (
+  IN BOOLEAN  Trace,
+  IN UINT8    *Ptr,
+  IN UINT32   AcpiTableLength,
+  IN UINT8    AcpiTableRevision
+  )
+{
+  UINT32  Offset;
+  UINT8   *InjInstEntryPtr;
+  UINT32  InjInstEntrySize;
+
+  if (!Trace) {
+    return;
+  }
+
+  Offset = ParseAcpi (
+             TRUE,
+             0,
+             "EINJ",
+             Ptr,
+             AcpiTableLength,
+             PARSER_PARAMS (EinjParser)
+             );
+
+  // Validate Error Source Descriptors Count.
+  if ((mEinjInjectionHdrSize == NULL) || (*mEinjInjectionHdrSize != Offset)) {
+    IncrementErrorCount ();
+    Print (L"ERROR: Invalid Injection Header...\n");
+    return;
+  }
+
+  if ((mEinjInjectionEntryCnt == NULL) || (*mEinjInjectionEntryCnt == 0)) {
+    IncrementErrorCount ();
+    Print (L"ERROR: Injection Instruction Entry should be presented...\n");
+    return;
+  }
+
+  InjInstEntrySize = sizeof (EFI_ACPI_6_5_EINJ_INJECTION_INSTRUCTION_ENTRY);
+
+  if ((*mEinjInjectionEntryCnt * InjInstEntrySize) != (AcpiTableLength - Offset)) {
+    IncrementErrorCount ();
+    Print (
+      L"ERROR: Incorrect count for Injection Instruction Entry.\n" \
+      L"       Injection Entry Count= %d.\n" \
+      L"       Present Count= %d.\n",
+      *mEinjInjectionEntryCnt,
+      (AcpiTableLength - Offset) / InjInstEntrySize
+      );
+  }
+
+  while (Offset < AcpiTableLength) {
+    InjInstEntryPtr = Ptr + Offset;
+
+    // Get Injection Instruction Entry.
+    ParseAcpi (
+      TRUE,
+      2,
+      "Injection Instruction Entry",
+      InjInstEntryPtr,
+      AcpiTableLength - Offset,
+      PARSER_PARAMS (EinjInjectionInstEntryParser)
+      );
+
+    Offset += InjInstEntrySize;
+  } // while
+}
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
index 0bdf068fe07614727e690897d9c76a5686be18b5..4a90372d81ff1eb2caeb3a477d058d08ffc1bdbf 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
@@ -54,6 +54,7 @@ ACPI_TABLE_PARSER  ParserList[] = {
   { EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE,                                                           ParseAcpiDbg2 },
   { EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
     ParseAcpiDsdt },
+  { EFI_ACPI_6_5_ERROR_INJECTION_TABLE_SIGNATURE,                                                        ParseAcpiEinj },
   { EFI_ACPI_6_4_ERROR_RECORD_SERIALIZATION_TABLE_SIGNATURE,                                             ParseAcpiErst },
   { EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,                                              ParseAcpiFacs },
   { EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,                                                 ParseAcpiFadt },
--
Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#118818): https://edk2.groups.io/g/devel/message/118818
Mute This Topic: https://groups.io/mt/106019474/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  parent reply	other threads:[~2024-05-10 12:23 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-10 12:22 [edk2-devel] [PATCH v1 0/4] Add EINJ table parser levi.yun
2024-05-10 12:22 ` [edk2-devel] [PATCH v1 1/4] MdePkg/Include/IndustryStandard: Update SET_ERROR_TYPE_WITH_ADDRESS Error Injection Actions levi.yun
2024-05-10 12:22 ` [edk2-devel] [PATCH v1 2/4] MdePkg/Include/IndustryStandard: Update GET_EXECUTE_OPERATION_TIMINGS " levi.yun
2024-05-10 12:22 ` [edk2-devel] [PATCH v1 3/4] MdePkg/Include/IndustryStandard: Update EINJ information according to ACPI 6.5 levi.yun
2024-05-10 12:22 ` levi.yun [this message]
2024-05-13  7:41 ` [edk2-devel] [PATCH v1 0/4] Add EINJ table parser PierreGondois
2024-05-23  8:52 ` levi.yun
2024-06-03  6:36 ` levi.yun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240510122257.2457623-5-yeoreum.yun@arm.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox