Blob Blame Raw
From f0d66bb3979a2bcba84027cb2d09f5de76fec9a4 Mon Sep 17 00:00:00 2001
From: Sami Mujawar <sami.mujawar@arm.com>
Date: Fri, 21 Apr 2017 17:07:03 +0100
Subject: [PATCH] Add support for hex AML C header file generation

The iAsl compiler provides a list of options to support
'Firmware Support - C Text Output'.

One of the options, '-tc' supports generation of AML hex
tables in C. This command generates a character array that
represents the AML hex table data.
        e.g. unsigned char AmlCode[] = {
               // HEX AML data
               ...
               };

However, there is no option to change the name of the
generated character array (AmlCode) in the output hex file.
This limits the ability to reference more than one table from
the firmware code.

Also, the generated output does not have header file include
guards. This is ideally desired if the hex file is to be
included from a C source file.

A solution to this is to modify the Hex C output such that
the name of the array is derived from the input file name,
and to add header file include guards.

To address the above, without breaking existing implementations,
a new option '-th' is introduced in the list of supported
'Firmware Support - C Text Output' commands. This option
generates an AML hex table output in a C header file suitable
for including from a C source file.

The '-th' option:
1. Uses the input file name as a prefix for the generated
   C array name.
   e.g. 'unsigned char DadtAmlCode[]'

2. Adds a header file include guard.
   e.g.
        #ifndef DSDT_HEX_
        #define DSDT_HEX_
        ...

        unsigned char DadtAmlCode[] = {
                // HEX AML data
                ...
        };

        #endif // DSDT_HEX_

  Where Dadt.aml is the input file name.

  Note: The header file include guard uses '<InputFileName>_HEX_'
        format instead of '<InputFileName>_H_' to avoid possible
        collision with an existing header guard.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Signed-off-by: Evan Lloyd <evan.lloyd@arm.com>

Github-Location: https://github.com/acpica/acpica/pull/368/commits/f0d66bb3979a2bcba84027cb2d09f5de76fec9a4

---
 source/compiler/aslcompile.c |  12 +++-
 source/compiler/aslglobal.h  |   1 +
 source/compiler/aslhelp.c    |   1 +
 source/compiler/aslhex.c     | 154 +++++++++++++++++++++++++++++++++++++++++++
 source/compiler/asloptions.c |   5 ++
 source/include/acapps.h      |   6 ++
 6 files changed, 176 insertions(+), 3 deletions(-)

Index: acpica-unix2-20180209/source/compiler/aslcompile.c
===================================================================
--- acpica-unix2-20180209.orig/source/compiler/aslcompile.c
+++ acpica-unix2-20180209/source/compiler/aslcompile.c
@@ -436,7 +436,8 @@ AslCompilerSignon (
             Prefix = "; ";
         }
         else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
-                 (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
+                 (Gbl_HexOutputFlag == HEX_OUTPUT_ASL) ||
+                 (Gbl_HexOutputFlag == HEX_OUTPUT_H))
         {
             FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n");
             Prefix = " * ";
@@ -471,7 +472,11 @@ AslCompilerSignon (
     /* Compiler signon with copyright */
 
     FlPrintFile (FileId, "%s\n", Prefix);
-    FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
+    if (Gbl_HexOutputFlag == HEX_OUTPUT_H) {
+        FlPrintFile (FileId, ACPI_COMMON_HEADER_NO_COPYRIGHT (UtilityName, Prefix));
+    } else {
+        FlPrintFile (FileId, ACPI_COMMON_HEADER (UtilityName, Prefix));
+    }
 }
 
 
@@ -513,7 +518,8 @@ AslCompilerFileHeader (
             Prefix = "; ";
         }
         else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) ||
-                 (Gbl_HexOutputFlag == HEX_OUTPUT_ASL))
+                 (Gbl_HexOutputFlag == HEX_OUTPUT_ASL) ||
+                 (Gbl_HexOutputFlag == HEX_OUTPUT_H))
         {
             Prefix = " * ";
         }
Index: acpica-unix2-20180209/source/compiler/aslglobal.h
===================================================================
--- acpica-unix2-20180209.orig/source/compiler/aslglobal.h
+++ acpica-unix2-20180209/source/compiler/aslglobal.h
@@ -220,6 +220,7 @@ ASL_EXTERN BOOLEAN                  ASL_
 #define HEX_OUTPUT_C                1
 #define HEX_OUTPUT_ASM              2
 #define HEX_OUTPUT_ASL              3
+#define HEX_OUTPUT_H                4
 
 ASL_EXTERN BOOLEAN                  ASL_INIT_GLOBAL (Gbl_HexOutputFlag, HEX_OUTPUT_NONE);
 
Index: acpica-unix2-20180209/source/compiler/aslhelp.c
===================================================================
--- acpica-unix2-20180209.orig/source/compiler/aslhelp.c
+++ acpica-unix2-20180209/source/compiler/aslhelp.c
@@ -121,6 +121,7 @@ Usage (
 
     printf ("\nFirmware Support - C Text Output:\n");
     ACPI_OPTION ("-tc",             "Create hex AML table in C (*.hex)");
+    ACPI_OPTION ("-th",             "Create hex AML table in C header (*.hex)");
     ACPI_OPTION ("-sc",             "Create named hex AML arrays in C (*.c)");
     ACPI_OPTION ("-ic",             "Create include file in C for -sc symbols (*.h)");
     ACPI_OPTION ("-so",             "Create namespace AML offset table in C (*.offset.h)");
Index: acpica-unix2-20180209/source/compiler/aslhex.c
===================================================================
--- acpica-unix2-20180209.orig/source/compiler/aslhex.c
+++ acpica-unix2-20180209/source/compiler/aslhex.c
@@ -46,6 +46,10 @@
 #define _COMPONENT          ACPI_COMPILER
         ACPI_MODULE_NAME    ("ashex")
 
+#ifndef PATH_MAX
+#define PATH_MAX 256
+#endif
+
 /*
  * This module emits ASCII hex output files in either C, ASM, or ASL format
  */
@@ -64,6 +68,10 @@ static void
 HxDoHexOutputAsm (
     void);
 
+static void
+HxDoHexOutputH (
+    void);
+
 static UINT32
 HxReadAmlOutputFile (
     UINT8                   *Buffer);
@@ -104,6 +112,11 @@ HxDoHexOutput (
         HxDoHexOutputAsl ();
         break;
 
+    case HEX_OUTPUT_H:
+
+        HxDoHexOutputH ();
+        break;
+
     default:
 
         /* No other output types supported */
@@ -233,6 +246,147 @@ HxDoHexOutputC (
 }
 
 
+/*******************************************************************************
+*
+* FUNCTION:    HxDoHexOutputH
+*
+* PARAMETERS:  None
+*
+* RETURN:      None
+*
+* DESCRIPTION: Create the hex output file. This is the same data as the AML
+*              output file, but formatted into hex/ASCII bytes suitable for
+*              inclusion into a C source file.
+*
+******************************************************************************/
+
+static void
+HxDoHexOutputH (
+    void)
+{
+    UINT8                   FileData[HEX_TABLE_LINE_SIZE];
+    UINT32                  LineLength;
+    UINT32                  Offset = 0;
+    UINT32                  AmlFileSize;
+    UINT32                  i;
+    UINT32                  FileNamePrefixLength;
+    char                    *DotPosition;
+    char                    *InputFileName;
+    char                    *NamePosition;
+    char                    *FileNameEndPosition;
+    char                    FileNamePrefix[PATH_MAX];
+    char                    FileGuard[PATH_MAX];
+
+    /* Get AML size, seek back to start */
+
+    AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT);
+    FlSeekFile (ASL_FILE_AML_OUTPUT, 0);
+
+    /*
+     * Find the filename and use it as a prefix for
+     * the AML code array and the header file guard
+     */
+    InputFileName = Gbl_Files[ASL_FILE_INPUT].Filename;
+    FileNameEndPosition = InputFileName + strlen (InputFileName);
+
+    NamePosition = strrchr (InputFileName, '/');
+    if (NamePosition == NULL) {
+        /* '/' not found. This means the input file name
+         * does not contain the path and is in the current
+         * directory.
+         */
+        NamePosition = InputFileName;
+    } else {
+        /* '/' was found. So move to the next character
+         * which is the name of the input file.
+         */
+        NamePosition++;
+    }
+
+    /* Get the file name without the extension to use
+     * as a prefix.
+     */
+    DotPosition = strrchr (NamePosition, '.');
+    if (DotPosition) {
+        /* No dot or suffix */
+        FileNameEndPosition = DotPosition;
+    }
+
+    FileNamePrefixLength = FileNameEndPosition - NamePosition;
+    if (FileNamePrefixLength > (PATH_MAX - 1)) {
+        AslError (ASL_ERROR, ASL_MSG_STRING_LENGTH, NULL, ": Input file name too long.");
+        return;
+    }
+
+    strncpy (FileNamePrefix, NamePosition, FileNamePrefixLength);
+    /* NULL terminate the string */
+    FileNamePrefix[FileNamePrefixLength] = '\0';
+
+    if (strrchr (FileNamePrefix, ' ')) {
+        AslError (ASL_ERROR, ASL_MSG_SYNTAX, NULL, "Input file name has space.");
+        return;
+    }
+
+    strcpy (FileGuard, FileNamePrefix);
+    AcpiUtStrupr (FileGuard);
+
+    /* Generate the hex output. */
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C header code output\n");
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n",
+        AmlFileSize);
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, "#ifndef %s_HEX_\n", FileGuard);
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, "#define %s_HEX_\n", FileGuard);
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n");
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char %sAmlCode[] =\n{\n", FileNamePrefix);
+
+    while (Offset < AmlFileSize) {
+        /* Read enough bytes needed for one output line */
+
+        LineLength = HxReadAmlOutputFile (FileData);
+        if (!LineLength) {
+            break;
+        }
+
+        FlPrintFile (ASL_FILE_HEX_OUTPUT, "    ");
+
+        for (i = 0; i < LineLength; i++) {
+            /*
+            * Print each hex byte.
+            * Add a comma until the very last byte of the AML file
+            * (Some C compilers complain about a trailing comma)
+            */
+            FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]);
+            if ((Offset + i + 1) < AmlFileSize) {
+                FlPrintFile (ASL_FILE_HEX_OUTPUT, ",");
+            } else {
+                FlPrintFile (ASL_FILE_HEX_OUTPUT, " ");
+            }
+        }
+
+        /* Add fill spaces if needed for last line */
+
+        if (LineLength < HEX_TABLE_LINE_SIZE) {
+            FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s",
+                5 * (HEX_TABLE_LINE_SIZE - LineLength), " ");
+        }
+
+        /* Emit the offset and ASCII dump for the entire line */
+
+        FlPrintFile (ASL_FILE_HEX_OUTPUT, "  /* %8.8X", Offset);
+        LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData);
+
+        FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n",
+            HEX_TABLE_LINE_SIZE - LineLength + 1, " ");
+
+        Offset += LineLength;
+    }
+
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n");
+    FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n#endif // %s_HEX_\n", FileGuard);
+}
+
+
 /*******************************************************************************
  *
  * FUNCTION:    HxDoHexOutputAsl
Index: acpica-unix2-20180209/source/compiler/asloptions.c
===================================================================
--- acpica-unix2-20180209.orig/source/compiler/asloptions.c
+++ acpica-unix2-20180209/source/compiler/asloptions.c
@@ -734,6 +734,11 @@ AslDoOptions (
             Gbl_HexOutputFlag = HEX_OUTPUT_ASL;
             break;
 
+        case 'h':
+
+            Gbl_HexOutputFlag = HEX_OUTPUT_H;
+            break;
+
         default:
 
             printf ("Unknown option: -t%s\n", AcpiGbl_Optarg);
Index: acpica-unix2-20180209/source/include/acapps.h
===================================================================
--- acpica-unix2-20180209.orig/source/include/acapps.h
+++ acpica-unix2-20180209/source/include/acapps.h
@@ -80,6 +80,12 @@
     Prefix, ACPICA_COPYRIGHT, \
     Prefix
 
+#define ACPI_COMMON_HEADER_NO_COPYRIGHT(UtilityName, Prefix) \
+    "%s%s\n%s%s version %8.8X%s\n%s\n", \
+    Prefix, ACPICA_NAME, \
+    Prefix, UtilityName, ((UINT32) ACPI_CA_VERSION), ACPI_WIDTH, \
+    Prefix
+
 #define ACPI_COMMON_BUILD_TIME \
     "Build date/time: %s %s\n", __DATE__, __TIME__