[edk2-devel] [PATCH v1 4/5] ShellPkg: add dot file generator functions

Joey Gouly joey.gouly at arm.com
Fri May 7 10:38:03 UTC 2021


From: Marc Moisson-Franckhauser <marc.moisson-franckhauser at arm.com>

Bugzilla: 3378 (https://bugzilla.tianocore.org/show_bug.cgi?id=3378)

These can be used to generate dot files, that can be used to visualise
graphs in tables, such as PPTT.

Signed-off-by: Marc Moisson-Franckhauser <marc.moisson-franckhauser at arm.com>
Signed-off-by: Joey Gouly <joey.gouly at arm.com>
---
 ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf |   4 +-
 ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.h                  |  97 +++++++
 ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.c                  | 276 ++++++++++++++++++++
 3 files changed, 376 insertions(+), 1 deletion(-)

diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
index 63fc5a1281a894841dac704484c3d4f9481edb46..ffe4979b3ac5d0120bcf678cf7823afac6674e4f 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
@@ -1,7 +1,7 @@
 ##  @file
 # Provides Shell 'acpiview' command functions
 #
-# Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.<BR>
+# Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -27,6 +27,8 @@ [Sources.common]
   AcpiView.h
   AcpiViewConfig.c
   AcpiViewConfig.h
+  DotGenerator.c
+  DotGenerator.h
   Parsers/Aest/AestParser.c
   Parsers/Bgrt/BgrtParser.c
   Parsers/Dbg2/Dbg2Parser.c
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.h b/ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a8e2fdc2d2024ae54fdce963d751ab53a8a5758
--- /dev/null
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.h
@@ -0,0 +1,97 @@
+/** @file
+  Header file for Dot File Generation
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef DOT_GENERATOR_H_
+#define DOT_GENERATOR_H_
+
+#include <Protocol/Shell.h>
+
+#define DOT_COLOR_MASK            0b111
+// Flags for color of arrow or node.
+#define DOT_COLOR_BLACK           0b000 // default
+#define DOT_COLOR_GRAY            0b001
+#define DOT_COLOR_BLUE            0b010
+#define DOT_COLOR_YELLOW          0b011
+#define DOT_COLOR_RED             0b100
+
+#define DOT_ARROW_TYPE_MASK       0b1000
+// Flags for style of arrow.
+#define DOT_ARROW_FULL            0b0000 // default
+#define DOT_ARROW_DOTTED          0b1000
+
+// Flag for reversing how the nodes will be ranked and displayed.
+#define DOT_ARROW_RANK_REVERSE    0b10000
+
+#define DOT_BOX_TYPE_MASK         0b1100000
+// Flag for shape of box
+#define DOT_BOX_SQUARE            0b0000000 // default
+#define DOT_BOX_DIAMOND           0b0100000
+
+// Flag for adding the node's ID to the end of the label.
+#define DOT_BOX_ADD_ID_TO_LABEL   0b10000000
+
+// Valid flags for DotAddNode.
+#define DOT_BOX_FLAGS_MASK        (DOT_COLOR_MASK |\
+                                   DOT_BOX_TYPE_MASK |\
+                                   DOT_BOX_ADD_ID_TO_LABEL)
+// Valid flags for DotAddLink.
+#define DOT_ARROW_FLAGS_MASK      (DOT_COLOR_MASK |\
+                                   DOT_ARROW_TYPE_MASK |\
+                                   DOT_ARROW_RANK_REVERSE)
+
+
+/**
+  Opens a new dot file and writes a dot directional graph.
+
+  @param [in] FileName    Null terminated unicode string.
+**/
+SHELL_FILE_HANDLE
+DotOpenNewFile (
+  IN CHAR16* FileName
+  );
+
+/**
+  Writes a dot graph footer and closes the dot file.
+**/
+VOID
+DotCloseFile (
+  SHELL_FILE_HANDLE DotFile
+  );
+
+/**
+  Writes a line in the previously opened dot file describing a
+  new node.
+
+  @param [in] Id        A unique identifier for the node.
+  @param [in] Flags     Flags describing the node's characteristics.
+  @param [in] Label     Label to be shown on the graph node.
+**/
+VOID
+DotAddNode (
+  SHELL_FILE_HANDLE DotFile,
+  IN UINT32         Id,
+  IN UINT16         Flags,
+  IN CONST CHAR16*  Label
+  );
+
+/**
+  Writes a line in the previously opened dot file describing a
+  new link between two nodes.
+
+  @param [in] IdSource    An identifier for the source node of the link.
+  @param [in] IdTarget    An identifier for the target node of the link.
+  @param [in] Flags       Flags describing the node's characteristics.
+**/
+VOID
+DotAddLink (
+  SHELL_FILE_HANDLE DotFile,
+  IN UINT32 IdSource,
+  IN UINT32 IdTarget,
+  IN UINT16 Flags
+  );
+
+#endif // DOT_GENERATOR_H_
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c644d96af30ca4b1160bc892fe391ae1ff5211b
--- /dev/null
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/DotGenerator.c
@@ -0,0 +1,276 @@
+/** @file
+  Dot File Generator
+
+  Copyright (c) 2021, Arm Limited. All rights reserved.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include "DotGenerator.h"
+#include "AcpiView.h"
+
+#define MAX_DOT_BUFFER_SIZE   128
+
+/**
+  Writes a Null terminated ASCII string to the dot file handle.
+
+  @param [in] String      Null terminated ascii string.
+**/
+STATIC
+VOID
+DotWriteFile (
+  SHELL_FILE_HANDLE DotFileHandle,
+  IN CHAR8* String
+  )
+{
+  UINTN TransferBytes;
+  EFI_STATUS Status;
+
+  if (DotFileHandle == NULL) {
+    Print ("ERROR: Failed to write to dot file\n");
+    ASSERT (0);
+    return;
+  }
+
+  TransferBytes = AsciiStrLen (String);
+  Status = ShellWriteFile (
+    DotFileHandle,
+    &TransferBytes,
+    String
+    );
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (AsciiStrLen (String) == TransferBytes);
+}
+
+/**
+  Writes a new parameter to a previously started parameter list.
+
+  @param [in] Name      Null terminated string of the parameter's name.
+  @param [in] Value     Null terminated string of the parameter's value.
+  @param [in] Quoted    True if value needs to be quoted.
+**/
+STATIC
+VOID
+DotAddParameter (
+  SHELL_FILE_HANDLE DotFileHandle,
+  IN CHAR16*  Name,
+  IN CHAR16*  Value,
+  IN BOOLEAN  Quoted
+  )
+{
+  CHAR8 StringBuffer[MAX_DOT_BUFFER_SIZE];
+
+  ASSERT(DotFileHandle != NULL);
+
+  if (Quoted) {
+    AsciiSPrint (
+      StringBuffer,
+      sizeof (StringBuffer),
+      "[%s=\"%s\"]",
+      Name,
+      Value
+      );
+  } else {
+    AsciiSPrint (
+      StringBuffer,
+      sizeof (StringBuffer),
+      "[%s=%s]",
+      Name,
+      Value
+      );
+  }
+
+  DotWriteFile (DotFileHandle, StringBuffer);
+}
+
+/**
+  Writes the color argument of nodes or links according to flags.
+
+  @param [in] Flags     Flags describing the color (one of DOT_COLOR_...)
+**/
+STATIC
+VOID
+WriteColor (
+  SHELL_FILE_HANDLE DotFileHandle,
+  IN UINT16 Flags
+  )
+{
+  ASSERT(DotFileHandle != NULL);
+
+  switch (Flags & DOT_COLOR_MASK) {
+    case DOT_COLOR_GRAY:
+      DotAddParameter (DotFileHandle, L"color", L"gray", FALSE);
+      break;
+    case DOT_COLOR_YELLOW:
+      DotAddParameter (DotFileHandle, L"color", L"yellow", FALSE);
+      break;
+    case DOT_COLOR_BLUE:
+      DotAddParameter (DotFileHandle, L"color", L"blue", FALSE);
+      break;
+    case DOT_COLOR_RED:
+      DotAddParameter (DotFileHandle, L"color", L"red", FALSE);
+      break;
+    case DOT_COLOR_BLACK:
+    default:
+      DotAddParameter (DotFileHandle, L"color", L"black", FALSE);
+      break;
+  }
+}
+
+/**
+  Opens a new dot file and writes a dot directional graph.
+
+  @param [in] FileName    Null terminated unicode string.
+**/
+SHELL_FILE_HANDLE
+DotOpenNewFile (
+  IN CHAR16* FileName
+  )
+{
+  SHELL_FILE_HANDLE DotFileHandle;
+  EFI_STATUS Status;
+
+  Status = ShellOpenFileByName (
+             FileName,
+             &DotFileHandle,
+             EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+             0
+             );
+  if (EFI_ERROR (Status)) {
+    Print (L"ERROR: Couldn't open dot file");
+    return NULL;//Status;
+  }
+  Print (L"Creating DOT Graph in : %s... ", FileName);
+  DotWriteFile (DotFileHandle, "digraph {\n\trankdir=BT\n");
+  return DotFileHandle;
+}
+
+/**
+  Writes a dot graph footer and closes the dot file.
+**/
+VOID
+DotCloseFile (
+  SHELL_FILE_HANDLE DotFileHandle
+  )
+{
+  ASSERT(DotFileHandle != NULL);
+
+  DotWriteFile (DotFileHandle, "}\n");
+  ShellCloseFile (&DotFileHandle);
+  Print (L"Done.\n");
+}
+
+/**
+  Writes a line in the previously opened dot file describing a
+  new node.
+
+  @param [in] Id        A unique identifier for the node.
+  @param [in] Flags     Flags describing the node's characteristics.
+  @param [in] Label     Label to be shown on the graph node.
+**/
+VOID
+DotAddNode (
+  SHELL_FILE_HANDLE DotFileHandle,
+  IN UINT32         Id,
+  IN UINT16         Flags,
+  IN CONST CHAR16*  Label
+  )
+{
+  CHAR8  LineBuffer[64];
+  CHAR16 LabelBuffer[MAX_DOT_BUFFER_SIZE];
+
+  ASSERT ((Flags & ~DOT_BOX_FLAGS_MASK) == 0);
+  ASSERT(DotFileHandle != NULL);
+
+  AsciiSPrint (
+    LineBuffer,
+    sizeof (LineBuffer),
+    "\tx%x",
+    Id
+    );
+  DotWriteFile (DotFileHandle, LineBuffer);
+
+  switch (Flags & DOT_BOX_TYPE_MASK) {
+    case DOT_BOX_DIAMOND:
+      DotAddParameter (DotFileHandle, L"shape", L"diamond", FALSE);
+      break;
+    case DOT_BOX_SQUARE:
+    default:
+      DotAddParameter (DotFileHandle, L"shape", L"box", FALSE);
+      break;
+  }
+
+  if (Label != NULL) {
+    if ((Flags & DOT_BOX_ADD_ID_TO_LABEL) != 0) {
+      UnicodeSPrint (
+        LabelBuffer,
+        sizeof (LabelBuffer),
+        L"%s\\n0x%x",
+        Label,
+        Id
+        );
+    } else {
+      UnicodeSPrint (
+        LabelBuffer,
+        sizeof (LabelBuffer),
+        L"%s",
+        Label
+        );
+    }
+    DotAddParameter (DotFileHandle, L"label", LabelBuffer, TRUE);
+  }
+
+  WriteColor (DotFileHandle, Flags);
+  DotWriteFile (DotFileHandle, "\n");
+}
+
+/**
+  Writes a line in the previously opened dot file describing a
+  new link between two nodes.
+
+  @param [in] IdSource    An identifier for the source node of the link.
+  @param [in] IdTarget    An identifier for the target node of the link.
+  @param [in] Flags       Flags describing the node's characteristics.
+**/
+VOID
+DotAddLink (
+  SHELL_FILE_HANDLE DotFileHandle,
+  IN UINT32 IdSource,
+  IN UINT32 IdTarget,
+  IN UINT16 Flags
+  )
+{
+  CHAR8 LineBuffer[64];
+
+  ASSERT(DotFileHandle != NULL);
+  ASSERT ((Flags & ~DOT_ARROW_FLAGS_MASK) == 0);
+
+  AsciiSPrint (
+    LineBuffer,
+    sizeof (LineBuffer),
+    "\tx%x -> x%x",
+    IdSource,
+    IdTarget
+    );
+  DotWriteFile (DotFileHandle, LineBuffer);
+
+  if ((Flags & DOT_ARROW_RANK_REVERSE) != 0) {
+    DotAddParameter (DotFileHandle, L"dir", L"back", FALSE);
+  }
+
+  switch (Flags & DOT_ARROW_TYPE_MASK) {
+    case DOT_ARROW_DOTTED:
+      DotAddParameter (DotFileHandle, L"style", L"dotted", FALSE);
+      break;
+    case DOT_ARROW_FULL:
+    default:
+      DotAddParameter (DotFileHandle, L"style", L"solid", FALSE);
+      break;
+  }
+
+  WriteColor (DotFileHandle, Flags);
+  DotWriteFile (DotFileHandle, "\n");
+}
-- 
Guid("CE165669-3EF3-493F-B85D-6190EE5B9759")



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#74809): https://edk2.groups.io/g/devel/message/74809
Mute This Topic: https://groups.io/mt/82651822/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