public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH] BaseTools/GenBiosId: Add a new tool GenBiosId
@ 2019-05-28  1:32 Zhang, Shenglei
  2019-05-28 16:48 ` [edk2-devel] " Michael D Kinney
  0 siblings, 1 reply; 4+ messages in thread
From: Zhang, Shenglei @ 2019-05-28  1:32 UTC (permalink / raw)
  To: devel

GenBiosId is a tool to generate the BIOS ID binary file which uses
the data from the configuration file.
https://bugzilla.tianocore.org/show_bug.cgi?id=1846

Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
---
 BaseTools/Source/C/GenBiosId/GenBiosId.c | 627 +++++++++++++++++++++++
 BaseTools/Source/C/GNUmakefile           |   3 +-
 BaseTools/Source/C/GenBiosId/BiosId.env  |  27 +
 BaseTools/Source/C/GenBiosId/GNUmakefile |  14 +
 BaseTools/Source/C/GenBiosId/GenBiosId.h | 105 ++++
 BaseTools/Source/C/GenBiosId/Makefile    |  14 +
 BaseTools/Source/C/Makefile              |   3 +-
 7 files changed, 791 insertions(+), 2 deletions(-)
 create mode 100644 BaseTools/Source/C/GenBiosId/GenBiosId.c
 create mode 100644 BaseTools/Source/C/GenBiosId/BiosId.env
 create mode 100644 BaseTools/Source/C/GenBiosId/GNUmakefile
 create mode 100644 BaseTools/Source/C/GenBiosId/GenBiosId.h
 create mode 100644 BaseTools/Source/C/GenBiosId/Makefile

diff --git a/BaseTools/Source/C/GenBiosId/GenBiosId.c b/BaseTools/Source/C/GenBiosId/GenBiosId.c
new file mode 100644
index 000000000000..21d71d4ebd51
--- /dev/null
+++ b/BaseTools/Source/C/GenBiosId/GenBiosId.c
@@ -0,0 +1,627 @@
+/** @file
+This tool generates the BIOS ID binary file using the data from the configuration file.
+
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "GenBiosId.h"
+
+CHAR8          InputFileName[FILE_NAME_SIZE];
+CHAR8          OutputFileName[FILE_NAME_SIZE];
+CHAR8          OutputBatchFileName[FILE_NAME_SIZE];
+
+FILE          *InputFile;
+FILE          *OutputFile;
+FILE          *OutputBatchFile;
+
+BIOS_ID_IMAGE BiosIdImage = {
+  { '$', 'I', 'B', 'I', 'O', 'S', 'I', '$' },
+  {
+    { ATOU (' '), ATOU (' '), ATOU (' '), ATOU (' '), ATOU (' '), ATOU (' '), ATOU (' ') },
+    ATOU (' '),
+    ATOU ('.'),
+    { ATOU (' '), ATOU (' '), ATOU (' ') },
+    ATOU ('.'),
+    { ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0') },
+    ATOU ('.'),
+    ATOU (' '),
+    { ATOU ('0'), ATOU ('0') },
+    ATOU ('.'),
+    { ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0'),
+      ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0') },
+    ATOU ('\0')
+  }
+};
+
+VOID
+PrintBanner (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+  printf ("\n");
+  printf ("GenBiosId utility, version: v1.0 05/27/2018   \n");
+  printf ("Copyright (c) 2019, Intel Corporation. All rights reserved.   \n");
+  printf ("\n");
+}
+
+VOID
+PrintUsage (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Returns:
+
+--*/
+{
+  printf ("Usage:\n");
+  printf ("GenBiosId -i ConfigFile -o OutputFile [-ob OutputBatchFile] \n");
+  printf ("\n");
+}
+
+CHAR8 *
+StripLeadingWhiteSpace (
+  IN CHAR8 *StrInput
+  )
+/*++
+
+Routine Description:
+
+  Strip the leading whitespoace off the given ASCII string.
+
+Arguments:
+
+  StrInput  - the ASCII string that should be processed.
+
+Returns:
+
+  A pointer to the first non-whitespace character in the given string,
+  or NULL if the string was all whitespace.
+
+--*/
+{
+  if (StrInput == NULL) {
+    return NULL;
+  }
+
+  while (*StrInput != 0) {
+    if ((*StrInput == ' ') || (*StrInput == '\t') || (*StrInput == '\n')) {
+      ++StrInput;
+    } else {
+      return StrInput;
+    }
+  }
+
+  return NULL;
+}
+
+VOID
+ConvertToUnicode (
+  IN  CHAR8  *StrAscii,
+  OUT CHAR16 *StrUnicode
+  )
+/*++
+
+Routine Description:
+
+  Convert the given ASCII string to Unicode without appending terminating 0x0000.
+
+Arguments:
+
+  StrAscii    - the source ASCII string, null-terminated.
+
+  StrUnicode  - the resulted Unicode string will be put here, without the terminating 0x0000.
+
+Returns:
+
+--*/
+{
+  if ((StrAscii == NULL) || (StrUnicode == NULL)) {
+    return;
+  }
+
+  while (*StrAscii != 0) {
+    *StrUnicode = ATOU (*StrAscii);
+    ++StrAscii;
+    ++StrUnicode;
+  }
+}
+
+VOID
+FillTimeStamp (
+  OUT CHAR16  *StrTimeStampUnicode
+  )
+/*++
+
+Routine Description:
+  The function generates the current timestamp in "YYMMDDHHMM" format
+  and puts it into the Unicode string supplied, without the null-terminator.
+
+Arguments:
+
+  StrTimeStampUnicode - The Unicode string which is filled on return with the current timestamp.
+
+Returns:
+
+--*/
+{
+  struct tm *Time;
+  time_t    CurTime;
+  CHAR8     StrTime[11];
+
+  //
+  // Fetch the current time based on UTC timezone
+  //
+  time (&CurTime);
+  Time = gmtime (&CurTime);
+
+  if (NULL == Time) {
+    return;
+  }
+
+  sprintf (
+    StrTime,
+    "%02d%02d%02d%02d%02d",
+    (Time->tm_year + 1900) % 100, // Year is 1900-based, need only 2 digits.
+    Time->tm_mon + 1,             // Month is zero based.
+    Time->tm_mday,
+    Time->tm_hour,
+    Time->tm_min
+    );
+
+  ConvertToUnicode (StrTime, StrTimeStampUnicode);
+}
+
+VOID
+ConvertToAscii (
+  IN  CHAR16 *StrUnicode,
+  OUT CHAR8  *StrAscii
+  )
+/*++
+
+Routine Description:
+
+  Convert the given Unicode string to ASCII with appending terminating 0x00.
+
+Arguments:
+
+  StrUnicode  - the source Unicode string, null-terminated.
+
+  StrAscii    - the resulted ASCII string will be put here, with the terminating 0x00.
+
+Returns:
+
+--*/
+{
+  if ((StrUnicode == NULL) || (StrAscii == NULL)) {
+    return;
+  }
+
+  while (*StrUnicode != 0) {
+    *StrAscii = UTOA (*StrUnicode);
+    ++StrUnicode;
+    ++StrAscii;
+  }
+  *StrAscii = 0;
+}
+
+VOID
+PrintUnicodeString (
+  IN CHAR16 *StrUnicode
+  )
+/*++
+
+Routine Description:
+
+  Print the given Unicode string.
+
+Arguments:
+
+  StrUnicode  - the null-terminated Unicode string to print.
+
+Returns:
+
+--*/
+{
+  if (StrUnicode == NULL) {
+    return;
+  }
+
+  while (*StrUnicode != 0) {
+    putchar ((CHAR8)(*StrUnicode));
+    ++StrUnicode;
+  }
+}
+
+EFI_STATUS
+ParseInputFile (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Parse the BIOS ID definition file and fill the BIOS ID structure, including timestamp.
+
+Arguments:
+
+Returns:
+
+  EFI_SUCCESS           - The input file was parsed successfully.
+
+  EFI_INVALID_PARAMETER - The input file has incorrect format.
+
+--*/
+{
+  CHAR8   StrLine[MAX_LINE_SIZE];
+  CHAR8   StrFieldName[MAX_LINE_SIZE];
+  CHAR8   StrFieldValue[MAX_LINE_SIZE];
+  CHAR8   *Str;
+  UINT16  FieldsSet;
+  CHAR8   FormatString[MAX_FORMAT_STRING_SIZE];
+
+  FieldsSet = 0;
+  Str       = NULL;
+
+  //
+  // Generate the format string for sscanf() function.
+  //
+  sprintf (FormatString, "%%%us = %%%us", (unsigned int) sizeof (StrFieldName) - 1, (unsigned int) sizeof (StrFieldValue) - 1);
+
+  while (fgets (StrLine, sizeof (StrLine) - 1, InputFile) != NULL) {
+    Str = StripLeadingWhiteSpace (StrLine);
+
+    //
+    // Check for whitespace string.
+    //
+    if (Str == NULL) {
+      continue;
+    }
+
+    //
+    // Check for comment string.
+    //
+    if (*Str == '#') {
+      continue;
+    }
+
+    if (sscanf (Str, FormatString, StrFieldName, StrFieldValue) != 2) {
+      continue;
+    }
+
+    if (strcmp (StrFieldName, NAME_BOARD_ID) == 0) {
+      if (strlen (StrFieldValue) == CHARS_BOARD_ID) {
+        ConvertToUnicode (StrFieldValue, BiosIdImage.BiosIdString.BoardId);
+        FieldsSet |= FIELD_BOARD_ID;
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_BOARD_ID, CHARS_BOARD_ID);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    if (strcmp (StrFieldName, NAME_BOARD_REV) == 0) {
+      if (strlen (StrFieldValue) == CHARS_BOARD_REV) {
+        ConvertToUnicode (StrFieldValue, &(BiosIdImage.BiosIdString.BoardRev));
+        FieldsSet |= FIELD_BOARD_REV;
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_BOARD_REV, CHARS_BOARD_REV);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    if (strcmp (StrFieldName, NAME_BOARD_EXT) == 0) {
+      if (strlen (StrFieldValue) == CHARS_BOARD_EXT) {
+        ConvertToUnicode (StrFieldValue, BiosIdImage.BiosIdString.BoardExt);
+        FieldsSet |= FIELD_BOARD_EXT;
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_BOARD_EXT, CHARS_BOARD_EXT);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    if (strcmp (StrFieldName, NAME_BUILD_TYPE) == 0) {
+      if (strlen (StrFieldValue) == CHARS_BUILD_TYPE) {
+        if ((strcmp (StrFieldValue, "D") == 0) ||
+            (strcmp (StrFieldValue, "A") == 0) ||
+            (strcmp (StrFieldValue, "B") == 0) ||
+            (strcmp (StrFieldValue, "P") == 0)) {
+          ConvertToUnicode (StrFieldValue, &(BiosIdImage.BiosIdString.BuildType));
+          FieldsSet |= FIELD_BUILD_TYPE;
+        } else {
+          printf ("Error: value of %s should be one of %s, %s, %s or %s\n", NAME_BUILD_TYPE, "D", "A", "B", "P");
+          return EFI_INVALID_PARAMETER;
+        }
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_BUILD_TYPE, CHARS_BUILD_TYPE);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    if (strcmp (StrFieldName, NAME_VERSION_MAJOR) == 0) {
+      if (strlen (StrFieldValue) == CHARS_VERSION_MAJOR) {
+        ConvertToUnicode (StrFieldValue, BiosIdImage.BiosIdString.VersionMajor);
+        FieldsSet |= FIELD_VERSION_MAJOR;
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_VERSION_MAJOR, CHARS_VERSION_MAJOR);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    if (strcmp (StrFieldName, NAME_VERSION_MINOR) == 0) {
+      if (strlen (StrFieldValue) == CHARS_VERSION_MINOR) {
+        ConvertToUnicode (StrFieldValue, BiosIdImage.BiosIdString.VersionMinor);
+        FieldsSet |= FIELD_VERSION_MINOR;
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_VERSION_MINOR, CHARS_VERSION_MINOR);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    if (strcmp (StrFieldName, NAME_DATE) == 0) {
+      if (strlen (StrFieldValue) == CHARS_DATE) {
+        ConvertToUnicode (StrFieldValue, BiosIdImage.BiosIdString.TimeStamp);
+        FieldsSet |= FIELD_DATE;
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_DATE, CHARS_DATE);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+    if (strcmp (StrFieldName, NAME_TIME) == 0) {
+      if (strlen (StrFieldValue) == CHARS_TIME) {
+        ConvertToUnicode (StrFieldValue, &(BiosIdImage.BiosIdString.TimeStamp[CHARS_DATE]));
+        FieldsSet |= FIELD_TIME;
+      } else {
+        printf ("Error: value of %s should have exactly %d chars\n", NAME_TIME, CHARS_TIME);
+        return EFI_INVALID_PARAMETER;
+      }
+    }
+
+  }
+
+  if ((FieldsSet & (FIELD_DATE | FIELD_TIME)) != (FIELD_DATE | FIELD_TIME)) {
+    //
+    // Fill the timestamp.
+    //
+    FillTimeStamp (BiosIdImage.BiosIdString.TimeStamp);
+    FieldsSet |= (FIELD_DATE | FIELD_TIME);
+  }
+
+  //
+  // Exit if not all fields were supplied.
+  //
+  if ((FieldsSet & FIELD_ALL) != FIELD_ALL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteOutputFile (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Write the BIOS ID structure to the output file.
+
+Arguments:
+
+Returns:
+
+  EFI_SUCCESS       - The output file was created successfully.
+
+  EFI_DEVICE_ERROR  - There was a file write error.
+
+--*/
+{
+  if (fwrite (&BiosIdImage, sizeof (BIOS_ID_IMAGE), 1, OutputFile) != 1) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteOutputBatchFile (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Write "SET BIOS_ID=" and BIOS ID string to the batch file.
+
+Arguments:
+
+Returns:
+
+  EFI_SUCCESS       - The output batch file was created successfully.
+
+  EFI_DEVICE_ERROR  - There was a file write error.
+
+--*/
+{
+#ifndef __GNUC__
+  CHAR8 BatchFileContent[MAX_LINE_SIZE] = "SET BIOS_ID=";
+#else
+  CHAR8 BatchFileContent[MAX_LINE_SIZE] = "export BIOS_ID=";
+#endif
+
+  CHAR8 BiosIdString[sizeof (BIOS_ID_STRING)];
+
+  ConvertToAscii ((CHAR16 *) (&(BiosIdImage.BiosIdString)), BiosIdString);
+  strcat (BatchFileContent, BiosIdString);
+
+  if (fwrite (BatchFileContent, strlen (BatchFileContent), 1, OutputBatchFile) != 1) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
+
+int
+main (
+  IN  int   argc,
+  IN  CHAR8 *argv[]
+  )
+/*++
+
+Routine Description:
+
+Arguments:
+
+  argc  - Number of command-line arguments.
+
+  argv  - Array of command-line arguments.
+
+Returns:
+
+  0   - The operation completed successfully.
+
+  -1  - An error occurred.
+
+--*/
+{
+  int Status;
+
+  Status = 0;
+
+  PrintBanner ();
+
+  if ((argc != 5) && (argc != 7)) {
+    PrintUsage ();
+    Status = -1;
+    goto Done;
+  }
+
+  if (strcmp (argv[1], "-i") == 0) {
+    if (strlen (argv[2])> sizeof (InputFileName) - 1) {
+      printf ("The InputFileName %s is too long \n", argv[2]);
+      Status = -1;
+      goto Done;
+    }
+    strncpy (InputFileName, argv[2], sizeof (InputFileName) - 1);
+    InputFileName[sizeof (InputFileName) - 1] = 0;
+  } else {
+    PrintUsage ();
+    Status = -1;
+    goto Done;
+  }
+
+  if (strcmp (argv[3], "-o") == 0) {
+    if (strlen (argv[4])> sizeof (OutputFileName) - 1) {
+      printf ("OutputFileName %s is too long \n", argv[4]);
+      Status = -1;
+      goto Done;
+    }
+    strncpy (OutputFileName, argv[4], sizeof (OutputFileName) - 1);
+    OutputFileName[sizeof (OutputFileName) - 1] = 0;
+  } else {
+    PrintUsage ();
+    Status = -1;
+    goto Done;
+  }
+
+  if (argc == 7) {
+    if (strcmp (argv[5], "-ob") == 0) {
+      if (strlen (argv[6])> sizeof (OutputBatchFileName) - 1) {
+        printf ("The OutputBatchFileName %s is too long \n", argv[6]);
+        Status = -1;
+        goto Done;
+      }
+      strncpy (OutputBatchFileName, argv[6], sizeof (OutputBatchFileName) - 1);
+      OutputBatchFileName[sizeof (OutputBatchFileName) - 1] = 0;
+    } else {
+      PrintUsage ();
+      Status = -1;
+      goto Done;
+    }
+  }
+
+  InputFile   = NULL;
+  OutputFile  = NULL;
+  OutputBatchFile = NULL;
+
+  InputFile   = fopen (InputFileName, "r");
+  if (InputFile == NULL) {
+    printf ("Error opening input file: %s\n", InputFileName);
+    Status = -1;
+    goto Done;
+  }
+
+  OutputFile  = fopen (OutputFileName, "wb");
+  if (OutputFile == NULL) {
+    printf ("Error creating output file: %s\n", OutputFileName);
+    Status = -1;
+    goto Done;
+  }
+
+  if (argc == 7) {
+    OutputBatchFile = fopen (OutputBatchFileName, "wb");
+    if (OutputBatchFile == NULL) {
+      printf ("Error creating output batch file: %s\n", OutputBatchFileName);
+      Status = -1;
+      goto Done;
+    }
+  }
+
+  if (ParseInputFile () != EFI_SUCCESS) {
+    printf ("Invalid config file format: %s\n", InputFileName);
+    Status = -1;
+    goto Done;
+  }
+
+  if (WriteOutputFile () != EFI_SUCCESS) {
+    printf ("Can't write output file: %s\n", OutputFileName);
+    Status = -1;
+    goto Done;
+  }
+
+  if (argc == 7) {
+    if (WriteOutputBatchFile () != EFI_SUCCESS) {
+      printf ("Can't write output batch file: %s\n", OutputBatchFileName);
+      Status = -1;
+      goto Done;
+    }
+  }
+
+  printf ("BIOS ID created: ");
+  PrintUnicodeString ((CHAR16 *)(&(BiosIdImage.BiosIdString)));
+  printf ("\n");
+  printf ("BIOS ID binary file created: %s\n", OutputFileName);
+
+Done:
+
+  if (InputFile != NULL) {
+    fclose (InputFile);
+  }
+
+  if (OutputFile != NULL) {
+    fclose (OutputFile);
+  }
+
+  if (OutputBatchFile != NULL) {
+    fclose (OutputBatchFile);
+  }
+
+  return Status;
+}
+
diff --git a/BaseTools/Source/C/GNUmakefile b/BaseTools/Source/C/GNUmakefile
index 37bcce519c7e..9dbf1a4b06db 100644
--- a/BaseTools/Source/C/GNUmakefile
+++ b/BaseTools/Source/C/GNUmakefile
@@ -1,7 +1,7 @@
 ## @file
 #  GNU/Linux makefile for C tools build.
 #
-#  Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -47,6 +47,7 @@ VFRAUTOGEN = VfrCompile/VfrLexer.h
 APPLICATIONS = \
   BrotliCompress \
   VfrCompile \
+  GenBiosId \
   EfiRom \
   GenFfs \
   GenFv \
diff --git a/BaseTools/Source/C/GenBiosId/BiosId.env b/BaseTools/Source/C/GenBiosId/BiosId.env
new file mode 100644
index 000000000000..de54273107bd
--- /dev/null
+++ b/BaseTools/Source/C/GenBiosId/BiosId.env
@@ -0,0 +1,27 @@
+## @file
+#  This file is used to define the BIOS ID parameters of the build.
+#  This file is processed by GenBiosId.
+#  Here, it is just a template and can be customized by user.
+#
+#  BIOS ID string format:
+#    $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$(BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM
+#  All fields must have a fixed length. YYMMDDHHMM is UTC time.
+#    Example: "OVMF.000.0008.D03.1501301017"
+#
+#  If DATE is specified for YYMMDD and TIME is specified for HHMM like below,
+#  GenBiosId will use the value of DATE and TIME to fill YYMMDDHHMM,
+#  otherwise GenBiosId will fill YYMMDDHHMM with current UTC time of the build machine.
+#    DATE          = 150130
+#    TIME          = 1017
+#
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+BOARD_ID      = OVMF
+BOARD_REV     = 1
+BOARD_EXT     = 000
+BUILD_TYPE    = D
+VERSION_MAJOR = 0008
+VERSION_MINOR = 03
diff --git a/BaseTools/Source/C/GenBiosId/GNUmakefile b/BaseTools/Source/C/GenBiosId/GNUmakefile
new file mode 100644
index 000000000000..90a918c13f96
--- /dev/null
+++ b/BaseTools/Source/C/GenBiosId/GNUmakefile
@@ -0,0 +1,14 @@
+## @file
+#  makefile for building the GenBiosId utility.
+#
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+MAKEROOT ?= ..
+
+APPNAME = GenBiosId
+
+OBJECTS = GenBiosId.o
+
+include $(MAKEROOT)/Makefiles/app.makefile
diff --git a/BaseTools/Source/C/GenBiosId/GenBiosId.h b/BaseTools/Source/C/GenBiosId/GenBiosId.h
new file mode 100644
index 000000000000..660fba77e90b
--- /dev/null
+++ b/BaseTools/Source/C/GenBiosId/GenBiosId.h
@@ -0,0 +1,105 @@
+/** @file
+Definitions for the GenBiosId tool.
+
+Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GEN_BIOS_ID_
+#define _GEN_BIOS_ID_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <Common/UefiBaseTypes.h>
+
+#define FILE_NAME_SIZE  256
+#define MAX_LINE_SIZE   256
+#define MAX_FORMAT_STRING_SIZE  64
+
+#define ATOU(a)         (CHAR16) ((UINT8) (a))
+#define UTOA(a)         (CHAR8) ((UINT16) (a))
+
+//
+// BIOS ID field names.
+//
+#define NAME_BOARD_ID       "BOARD_ID"
+#define NAME_BOARD_REV      "BOARD_REV"
+#define NAME_BOARD_EXT      "BOARD_EXT"
+#define NAME_BUILD_TYPE     "BUILD_TYPE"
+#define NAME_VERSION_MAJOR  "VERSION_MAJOR"
+#define NAME_VERSION_MINOR  "VERSION_MINOR"
+#define NAME_DATE           "DATE"
+#define NAME_TIME           "TIME"
+
+//
+// Number of ASCII characters in each field
+//
+#define CHARS_BOARD_ID      7
+#define CHARS_BOARD_REV     1
+#define CHARS_BOARD_EXT     3
+#define CHARS_BUILD_TYPE    1
+#define CHARS_VERSION_MAJOR 4
+#define CHARS_VERSION_MINOR 2
+#define CHARS_DATE          6
+#define CHARS_TIME          4
+
+#define FIELD_BOARD_ID      0x0001
+#define FIELD_BOARD_REV     0x0002
+#define FIELD_BOARD_EXT     0x0004
+#define FIELD_BUILD_TYPE    0x0008
+#define FIELD_VERSION_MAJOR 0x0010
+#define FIELD_VERSION_MINOR 0x0020
+#define FIELD_DATE          0x0040
+#define FIELD_TIME          0x0080
+
+#define FIELD_ALL (     \
+  FIELD_BOARD_ID      | \
+  FIELD_BOARD_REV     | \
+  FIELD_BOARD_EXT     | \
+  FIELD_BUILD_TYPE    | \
+  FIELD_VERSION_MAJOR | \
+  FIELD_VERSION_MINOR | \
+  FIELD_DATE          | \
+  FIELD_TIME)
+
+//
+// BIOS ID string format:
+//
+// $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$(BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM
+//
+// Example: "TRFTCRB1.000.0008.D03.1501301017"
+//
+// The format should be same as platform BIOS ID definition
+//
+#pragma pack(1)
+
+typedef struct {
+  CHAR16    BoardId[7];             // "TRFTCRB"
+  CHAR16    BoardRev;               // "1"
+  CHAR16    Dot1;                   // "."
+  CHAR16    BoardExt[3];            // "000"
+  CHAR16    Dot2;                   // "."
+  CHAR16    VersionMajor[4];        // "0008"
+  CHAR16    Dot3;                   // "."
+  CHAR16    BuildType;              // "D"
+  CHAR16    VersionMinor[2];        // "03"
+  CHAR16    Dot4;                   // "."
+  CHAR16    TimeStamp[10];          // "YYMMDDHHMM"
+  CHAR16    NullTerminator;         // 0x0000
+} BIOS_ID_STRING;
+
+//
+// A signature precedes the BIOS ID string in the FV to enable search by external tools.
+//
+typedef struct {
+  UINT8             Signature[8];   // "$IBIOSI$"
+  BIOS_ID_STRING    BiosIdString;   // "TRFTCRB1.000.0008.D03.1501301017"
+} BIOS_ID_IMAGE;
+
+#pragma pack()
+
+
+#endif // _GEN_BIOS_ID_
diff --git a/BaseTools/Source/C/GenBiosId/Makefile b/BaseTools/Source/C/GenBiosId/Makefile
new file mode 100644
index 000000000000..967a1809b635
--- /dev/null
+++ b/BaseTools/Source/C/GenBiosId/Makefile
@@ -0,0 +1,14 @@
+## @file
+#  makefile for building the GenBiosId utility.
+#
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+!INCLUDE ..\Makefiles\ms.common
+
+APPNAME = GenBiosId
+
+OBJECTS = GenBiosId.obj
+
+!INCLUDE ..\Makefiles\ms.app
+
diff --git a/BaseTools/Source/C/Makefile b/BaseTools/Source/C/Makefile
index 217fc2b91d7b..748565bba9ff 100644
--- a/BaseTools/Source/C/Makefile
+++ b/BaseTools/Source/C/Makefile
@@ -1,7 +1,7 @@
 ## @file
 # Windows makefile for C tools build.
 #
-# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 HOST_ARCH = IA32
@@ -12,6 +12,7 @@ LIBRARIES = Common
 APPLICATIONS = \
   VfrCompile \
   BrotliCompress \
+  GenBiosId \
   EfiRom \
   GenCrc32 \
   GenFfs \
-- 
2.18.0.windows.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH] BaseTools/GenBiosId: Add a new tool GenBiosId
  2019-05-28  1:32 [PATCH] BaseTools/GenBiosId: Add a new tool GenBiosId Zhang, Shenglei
@ 2019-05-28 16:48 ` Michael D Kinney
  2019-05-31  6:36   ` Zhang, Shenglei
  0 siblings, 1 reply; 4+ messages in thread
From: Michael D Kinney @ 2019-05-28 16:48 UTC (permalink / raw)
  To: devel@edk2.groups.io, Zhang, Shenglei, Kinney, Michael D

Could this tools be ported to Python using the python
struct module to access C structures?

The implementation may be much simpler if python was
used for command line parsing.  And this capability 
could also be provided as a python module to support
direct access from pre/post build steps implemented in
python.

Thanks,

Mike

> -----Original Message-----
> From: devel@edk2.groups.io
> [mailto:devel@edk2.groups.io] On Behalf Of Zhang,
> Shenglei
> Sent: Monday, May 27, 2019 6:32 PM
> To: devel@edk2.groups.io
> Subject: [edk2-devel] [PATCH] BaseTools/GenBiosId: Add
> a new tool GenBiosId
> 
> GenBiosId is a tool to generate the BIOS ID binary file
> which uses
> the data from the configuration file.
> https://bugzilla.tianocore.org/show_bug.cgi?id=1846
> 
> Signed-off-by: Shenglei Zhang
> <shenglei.zhang@intel.com>
> ---
>  BaseTools/Source/C/GenBiosId/GenBiosId.c | 627
> +++++++++++++++++++++++
>  BaseTools/Source/C/GNUmakefile           |   3 +-
>  BaseTools/Source/C/GenBiosId/BiosId.env  |  27 +
>  BaseTools/Source/C/GenBiosId/GNUmakefile |  14 +
>  BaseTools/Source/C/GenBiosId/GenBiosId.h | 105 ++++
>  BaseTools/Source/C/GenBiosId/Makefile    |  14 +
>  BaseTools/Source/C/Makefile              |   3 +-
>  7 files changed, 791 insertions(+), 2 deletions(-)
>  create mode 100644
> BaseTools/Source/C/GenBiosId/GenBiosId.c
>  create mode 100644
> BaseTools/Source/C/GenBiosId/BiosId.env
>  create mode 100644
> BaseTools/Source/C/GenBiosId/GNUmakefile
>  create mode 100644
> BaseTools/Source/C/GenBiosId/GenBiosId.h
>  create mode 100644
> BaseTools/Source/C/GenBiosId/Makefile
> 
> diff --git a/BaseTools/Source/C/GenBiosId/GenBiosId.c
> b/BaseTools/Source/C/GenBiosId/GenBiosId.c
> new file mode 100644
> index 000000000000..21d71d4ebd51
> --- /dev/null
> +++ b/BaseTools/Source/C/GenBiosId/GenBiosId.c
> @@ -0,0 +1,627 @@
> +/** @file
> +This tool generates the BIOS ID binary file using the
> data from the configuration file.
> +
> +Copyright (c) 2015 - 2019, Intel Corporation. All
> rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include "GenBiosId.h"
> +
> +CHAR8          InputFileName[FILE_NAME_SIZE];
> +CHAR8          OutputFileName[FILE_NAME_SIZE];
> +CHAR8          OutputBatchFileName[FILE_NAME_SIZE];
> +
> +FILE          *InputFile;
> +FILE          *OutputFile;
> +FILE          *OutputBatchFile;
> +
> +BIOS_ID_IMAGE BiosIdImage = {
> +  { '$', 'I', 'B', 'I', 'O', 'S', 'I', '$' },
> +  {
> +    { ATOU (' '), ATOU (' '), ATOU (' '), ATOU (' '),
> ATOU (' '), ATOU (' '), ATOU (' ') },
> +    ATOU (' '),
> +    ATOU ('.'),
> +    { ATOU (' '), ATOU (' '), ATOU (' ') },
> +    ATOU ('.'),
> +    { ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0')
> },
> +    ATOU ('.'),
> +    ATOU (' '),
> +    { ATOU ('0'), ATOU ('0') },
> +    ATOU ('.'),
> +    { ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0'),
> ATOU ('0'),
> +      ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0'),
> ATOU ('0') },
> +    ATOU ('\0')
> +  }
> +};
> +
> +VOID
> +PrintBanner (
> +  VOID
> +  )
> +/*++
> +
> +Routine Description:
> +
> +Arguments:
> +
> +Returns:
> +
> +--*/
> +{
> +  printf ("\n");
> +  printf ("GenBiosId utility, version: v1.0 05/27/2018
> \n");
> +  printf ("Copyright (c) 2019, Intel Corporation. All
> rights reserved.   \n");
> +  printf ("\n");
> +}
> +
> +VOID
> +PrintUsage (
> +  VOID
> +  )
> +/*++
> +
> +Routine Description:
> +
> +Arguments:
> +
> +Returns:
> +
> +--*/
> +{
> +  printf ("Usage:\n");
> +  printf ("GenBiosId -i ConfigFile -o OutputFile [-ob
> OutputBatchFile] \n");
> +  printf ("\n");
> +}
> +
> +CHAR8 *
> +StripLeadingWhiteSpace (
> +  IN CHAR8 *StrInput
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Strip the leading whitespoace off the given ASCII
> string.
> +
> +Arguments:
> +
> +  StrInput  - the ASCII string that should be
> processed.
> +
> +Returns:
> +
> +  A pointer to the first non-whitespace character in
> the given string,
> +  or NULL if the string was all whitespace.
> +
> +--*/
> +{
> +  if (StrInput == NULL) {
> +    return NULL;
> +  }
> +
> +  while (*StrInput != 0) {
> +    if ((*StrInput == ' ') || (*StrInput == '\t') ||
> (*StrInput == '\n')) {
> +      ++StrInput;
> +    } else {
> +      return StrInput;
> +    }
> +  }
> +
> +  return NULL;
> +}
> +
> +VOID
> +ConvertToUnicode (
> +  IN  CHAR8  *StrAscii,
> +  OUT CHAR16 *StrUnicode
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Convert the given ASCII string to Unicode without
> appending terminating 0x0000.
> +
> +Arguments:
> +
> +  StrAscii    - the source ASCII string, null-
> terminated.
> +
> +  StrUnicode  - the resulted Unicode string will be
> put here, without the terminating 0x0000.
> +
> +Returns:
> +
> +--*/
> +{
> +  if ((StrAscii == NULL) || (StrUnicode == NULL)) {
> +    return;
> +  }
> +
> +  while (*StrAscii != 0) {
> +    *StrUnicode = ATOU (*StrAscii);
> +    ++StrAscii;
> +    ++StrUnicode;
> +  }
> +}
> +
> +VOID
> +FillTimeStamp (
> +  OUT CHAR16  *StrTimeStampUnicode
> +  )
> +/*++
> +
> +Routine Description:
> +  The function generates the current timestamp in
> "YYMMDDHHMM" format
> +  and puts it into the Unicode string supplied,
> without the null-terminator.
> +
> +Arguments:
> +
> +  StrTimeStampUnicode - The Unicode string which is
> filled on return with the current timestamp.
> +
> +Returns:
> +
> +--*/
> +{
> +  struct tm *Time;
> +  time_t    CurTime;
> +  CHAR8     StrTime[11];
> +
> +  //
> +  // Fetch the current time based on UTC timezone
> +  //
> +  time (&CurTime);
> +  Time = gmtime (&CurTime);
> +
> +  if (NULL == Time) {
> +    return;
> +  }
> +
> +  sprintf (
> +    StrTime,
> +    "%02d%02d%02d%02d%02d",
> +    (Time->tm_year + 1900) % 100, // Year is 1900-
> based, need only 2 digits.
> +    Time->tm_mon + 1,             // Month is zero
> based.
> +    Time->tm_mday,
> +    Time->tm_hour,
> +    Time->tm_min
> +    );
> +
> +  ConvertToUnicode (StrTime, StrTimeStampUnicode);
> +}
> +
> +VOID
> +ConvertToAscii (
> +  IN  CHAR16 *StrUnicode,
> +  OUT CHAR8  *StrAscii
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Convert the given Unicode string to ASCII with
> appending terminating 0x00.
> +
> +Arguments:
> +
> +  StrUnicode  - the source Unicode string, null-
> terminated.
> +
> +  StrAscii    - the resulted ASCII string will be put
> here, with the terminating 0x00.
> +
> +Returns:
> +
> +--*/
> +{
> +  if ((StrUnicode == NULL) || (StrAscii == NULL)) {
> +    return;
> +  }
> +
> +  while (*StrUnicode != 0) {
> +    *StrAscii = UTOA (*StrUnicode);
> +    ++StrUnicode;
> +    ++StrAscii;
> +  }
> +  *StrAscii = 0;
> +}
> +
> +VOID
> +PrintUnicodeString (
> +  IN CHAR16 *StrUnicode
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Print the given Unicode string.
> +
> +Arguments:
> +
> +  StrUnicode  - the null-terminated Unicode string to
> print.
> +
> +Returns:
> +
> +--*/
> +{
> +  if (StrUnicode == NULL) {
> +    return;
> +  }
> +
> +  while (*StrUnicode != 0) {
> +    putchar ((CHAR8)(*StrUnicode));
> +    ++StrUnicode;
> +  }
> +}
> +
> +EFI_STATUS
> +ParseInputFile (
> +  VOID
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Parse the BIOS ID definition file and fill the BIOS
> ID structure, including timestamp.
> +
> +Arguments:
> +
> +Returns:
> +
> +  EFI_SUCCESS           - The input file was parsed
> successfully.
> +
> +  EFI_INVALID_PARAMETER - The input file has incorrect
> format.
> +
> +--*/
> +{
> +  CHAR8   StrLine[MAX_LINE_SIZE];
> +  CHAR8   StrFieldName[MAX_LINE_SIZE];
> +  CHAR8   StrFieldValue[MAX_LINE_SIZE];
> +  CHAR8   *Str;
> +  UINT16  FieldsSet;
> +  CHAR8   FormatString[MAX_FORMAT_STRING_SIZE];
> +
> +  FieldsSet = 0;
> +  Str       = NULL;
> +
> +  //
> +  // Generate the format string for sscanf() function.
> +  //
> +  sprintf (FormatString, "%%%us = %%%us", (unsigned
> int) sizeof (StrFieldName) - 1, (unsigned int) sizeof
> (StrFieldValue) - 1);
> +
> +  while (fgets (StrLine, sizeof (StrLine) - 1,
> InputFile) != NULL) {
> +    Str = StripLeadingWhiteSpace (StrLine);
> +
> +    //
> +    // Check for whitespace string.
> +    //
> +    if (Str == NULL) {
> +      continue;
> +    }
> +
> +    //
> +    // Check for comment string.
> +    //
> +    if (*Str == '#') {
> +      continue;
> +    }
> +
> +    if (sscanf (Str, FormatString, StrFieldName,
> StrFieldValue) != 2) {
> +      continue;
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_BOARD_ID) == 0) {
> +      if (strlen (StrFieldValue) == CHARS_BOARD_ID) {
> +        ConvertToUnicode (StrFieldValue,
> BiosIdImage.BiosIdString.BoardId);
> +        FieldsSet |= FIELD_BOARD_ID;
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_BOARD_ID, CHARS_BOARD_ID);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_BOARD_REV) == 0) {
> +      if (strlen (StrFieldValue) == CHARS_BOARD_REV) {
> +        ConvertToUnicode (StrFieldValue,
> &(BiosIdImage.BiosIdString.BoardRev));
> +        FieldsSet |= FIELD_BOARD_REV;
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_BOARD_REV, CHARS_BOARD_REV);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_BOARD_EXT) == 0) {
> +      if (strlen (StrFieldValue) == CHARS_BOARD_EXT) {
> +        ConvertToUnicode (StrFieldValue,
> BiosIdImage.BiosIdString.BoardExt);
> +        FieldsSet |= FIELD_BOARD_EXT;
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_BOARD_EXT, CHARS_BOARD_EXT);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_BUILD_TYPE) == 0) {
> +      if (strlen (StrFieldValue) == CHARS_BUILD_TYPE)
> {
> +        if ((strcmp (StrFieldValue, "D") == 0) ||
> +            (strcmp (StrFieldValue, "A") == 0) ||
> +            (strcmp (StrFieldValue, "B") == 0) ||
> +            (strcmp (StrFieldValue, "P") == 0)) {
> +          ConvertToUnicode (StrFieldValue,
> &(BiosIdImage.BiosIdString.BuildType));
> +          FieldsSet |= FIELD_BUILD_TYPE;
> +        } else {
> +          printf ("Error: value of %s should be one of
> %s, %s, %s or %s\n", NAME_BUILD_TYPE, "D", "A", "B",
> "P");
> +          return EFI_INVALID_PARAMETER;
> +        }
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_BUILD_TYPE,
> CHARS_BUILD_TYPE);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_VERSION_MAJOR) ==
> 0) {
> +      if (strlen (StrFieldValue) ==
> CHARS_VERSION_MAJOR) {
> +        ConvertToUnicode (StrFieldValue,
> BiosIdImage.BiosIdString.VersionMajor);
> +        FieldsSet |= FIELD_VERSION_MAJOR;
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_VERSION_MAJOR,
> CHARS_VERSION_MAJOR);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_VERSION_MINOR) ==
> 0) {
> +      if (strlen (StrFieldValue) ==
> CHARS_VERSION_MINOR) {
> +        ConvertToUnicode (StrFieldValue,
> BiosIdImage.BiosIdString.VersionMinor);
> +        FieldsSet |= FIELD_VERSION_MINOR;
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_VERSION_MINOR,
> CHARS_VERSION_MINOR);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_DATE) == 0) {
> +      if (strlen (StrFieldValue) == CHARS_DATE) {
> +        ConvertToUnicode (StrFieldValue,
> BiosIdImage.BiosIdString.TimeStamp);
> +        FieldsSet |= FIELD_DATE;
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_DATE, CHARS_DATE);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +    if (strcmp (StrFieldName, NAME_TIME) == 0) {
> +      if (strlen (StrFieldValue) == CHARS_TIME) {
> +        ConvertToUnicode (StrFieldValue,
> &(BiosIdImage.BiosIdString.TimeStamp[CHARS_DATE]));
> +        FieldsSet |= FIELD_TIME;
> +      } else {
> +        printf ("Error: value of %s should have
> exactly %d chars\n", NAME_TIME, CHARS_TIME);
> +        return EFI_INVALID_PARAMETER;
> +      }
> +    }
> +
> +  }
> +
> +  if ((FieldsSet & (FIELD_DATE | FIELD_TIME)) !=
> (FIELD_DATE | FIELD_TIME)) {
> +    //
> +    // Fill the timestamp.
> +    //
> +    FillTimeStamp
> (BiosIdImage.BiosIdString.TimeStamp);
> +    FieldsSet |= (FIELD_DATE | FIELD_TIME);
> +  }
> +
> +  //
> +  // Exit if not all fields were supplied.
> +  //
> +  if ((FieldsSet & FIELD_ALL) != FIELD_ALL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +WriteOutputFile (
> +  VOID
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Write the BIOS ID structure to the output file.
> +
> +Arguments:
> +
> +Returns:
> +
> +  EFI_SUCCESS       - The output file was created
> successfully.
> +
> +  EFI_DEVICE_ERROR  - There was a file write error.
> +
> +--*/
> +{
> +  if (fwrite (&BiosIdImage, sizeof (BIOS_ID_IMAGE), 1,
> OutputFile) != 1) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +EFI_STATUS
> +WriteOutputBatchFile (
> +  VOID
> +  )
> +/*++
> +
> +Routine Description:
> +
> +  Write "SET BIOS_ID=" and BIOS ID string to the batch
> file.
> +
> +Arguments:
> +
> +Returns:
> +
> +  EFI_SUCCESS       - The output batch file was
> created successfully.
> +
> +  EFI_DEVICE_ERROR  - There was a file write error.
> +
> +--*/
> +{
> +#ifndef __GNUC__
> +  CHAR8 BatchFileContent[MAX_LINE_SIZE] = "SET
> BIOS_ID=";
> +#else
> +  CHAR8 BatchFileContent[MAX_LINE_SIZE] = "export
> BIOS_ID=";
> +#endif
> +
> +  CHAR8 BiosIdString[sizeof (BIOS_ID_STRING)];
> +
> +  ConvertToAscii ((CHAR16 *)
> (&(BiosIdImage.BiosIdString)), BiosIdString);
> +  strcat (BatchFileContent, BiosIdString);
> +
> +  if (fwrite (BatchFileContent, strlen
> (BatchFileContent), 1, OutputBatchFile) != 1) {
> +    return EFI_DEVICE_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +int
> +main (
> +  IN  int   argc,
> +  IN  CHAR8 *argv[]
> +  )
> +/*++
> +
> +Routine Description:
> +
> +Arguments:
> +
> +  argc  - Number of command-line arguments.
> +
> +  argv  - Array of command-line arguments.
> +
> +Returns:
> +
> +  0   - The operation completed successfully.
> +
> +  -1  - An error occurred.
> +
> +--*/
> +{
> +  int Status;
> +
> +  Status = 0;
> +
> +  PrintBanner ();
> +
> +  if ((argc != 5) && (argc != 7)) {
> +    PrintUsage ();
> +    Status = -1;
> +    goto Done;
> +  }
> +
> +  if (strcmp (argv[1], "-i") == 0) {
> +    if (strlen (argv[2])> sizeof (InputFileName) - 1)
> {
> +      printf ("The InputFileName %s is too long \n",
> argv[2]);
> +      Status = -1;
> +      goto Done;
> +    }
> +    strncpy (InputFileName, argv[2], sizeof
> (InputFileName) - 1);
> +    InputFileName[sizeof (InputFileName) - 1] = 0;
> +  } else {
> +    PrintUsage ();
> +    Status = -1;
> +    goto Done;
> +  }
> +
> +  if (strcmp (argv[3], "-o") == 0) {
> +    if (strlen (argv[4])> sizeof (OutputFileName) - 1)
> {
> +      printf ("OutputFileName %s is too long \n",
> argv[4]);
> +      Status = -1;
> +      goto Done;
> +    }
> +    strncpy (OutputFileName, argv[4], sizeof
> (OutputFileName) - 1);
> +    OutputFileName[sizeof (OutputFileName) - 1] = 0;
> +  } else {
> +    PrintUsage ();
> +    Status = -1;
> +    goto Done;
> +  }
> +
> +  if (argc == 7) {
> +    if (strcmp (argv[5], "-ob") == 0) {
> +      if (strlen (argv[6])> sizeof
> (OutputBatchFileName) - 1) {
> +        printf ("The OutputBatchFileName %s is too
> long \n", argv[6]);
> +        Status = -1;
> +        goto Done;
> +      }
> +      strncpy (OutputBatchFileName, argv[6], sizeof
> (OutputBatchFileName) - 1);
> +      OutputBatchFileName[sizeof (OutputBatchFileName)
> - 1] = 0;
> +    } else {
> +      PrintUsage ();
> +      Status = -1;
> +      goto Done;
> +    }
> +  }
> +
> +  InputFile   = NULL;
> +  OutputFile  = NULL;
> +  OutputBatchFile = NULL;
> +
> +  InputFile   = fopen (InputFileName, "r");
> +  if (InputFile == NULL) {
> +    printf ("Error opening input file: %s\n",
> InputFileName);
> +    Status = -1;
> +    goto Done;
> +  }
> +
> +  OutputFile  = fopen (OutputFileName, "wb");
> +  if (OutputFile == NULL) {
> +    printf ("Error creating output file: %s\n",
> OutputFileName);
> +    Status = -1;
> +    goto Done;
> +  }
> +
> +  if (argc == 7) {
> +    OutputBatchFile = fopen (OutputBatchFileName,
> "wb");
> +    if (OutputBatchFile == NULL) {
> +      printf ("Error creating output batch file:
> %s\n", OutputBatchFileName);
> +      Status = -1;
> +      goto Done;
> +    }
> +  }
> +
> +  if (ParseInputFile () != EFI_SUCCESS) {
> +    printf ("Invalid config file format: %s\n",
> InputFileName);
> +    Status = -1;
> +    goto Done;
> +  }
> +
> +  if (WriteOutputFile () != EFI_SUCCESS) {
> +    printf ("Can't write output file: %s\n",
> OutputFileName);
> +    Status = -1;
> +    goto Done;
> +  }
> +
> +  if (argc == 7) {
> +    if (WriteOutputBatchFile () != EFI_SUCCESS) {
> +      printf ("Can't write output batch file: %s\n",
> OutputBatchFileName);
> +      Status = -1;
> +      goto Done;
> +    }
> +  }
> +
> +  printf ("BIOS ID created: ");
> +  PrintUnicodeString ((CHAR16
> *)(&(BiosIdImage.BiosIdString)));
> +  printf ("\n");
> +  printf ("BIOS ID binary file created: %s\n",
> OutputFileName);
> +
> +Done:
> +
> +  if (InputFile != NULL) {
> +    fclose (InputFile);
> +  }
> +
> +  if (OutputFile != NULL) {
> +    fclose (OutputFile);
> +  }
> +
> +  if (OutputBatchFile != NULL) {
> +    fclose (OutputBatchFile);
> +  }
> +
> +  return Status;
> +}
> +
> diff --git a/BaseTools/Source/C/GNUmakefile
> b/BaseTools/Source/C/GNUmakefile
> index 37bcce519c7e..9dbf1a4b06db 100644
> --- a/BaseTools/Source/C/GNUmakefile
> +++ b/BaseTools/Source/C/GNUmakefile
> @@ -1,7 +1,7 @@
>  ## @file
>  #  GNU/Linux makefile for C tools build.
>  #
> -#  Copyright (c) 2007 - 2017, Intel Corporation. All
> rights reserved.<BR>
> +#  Copyright (c) 2007 - 2019, Intel Corporation. All
> rights reserved.<BR>
>  #
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -47,6 +47,7 @@ VFRAUTOGEN = VfrCompile/VfrLexer.h
>  APPLICATIONS = \
>    BrotliCompress \
>    VfrCompile \
> +  GenBiosId \
>    EfiRom \
>    GenFfs \
>    GenFv \
> diff --git a/BaseTools/Source/C/GenBiosId/BiosId.env
> b/BaseTools/Source/C/GenBiosId/BiosId.env
> new file mode 100644
> index 000000000000..de54273107bd
> --- /dev/null
> +++ b/BaseTools/Source/C/GenBiosId/BiosId.env
> @@ -0,0 +1,27 @@
> +## @file
> +#  This file is used to define the BIOS ID parameters
> of the build.
> +#  This file is processed by GenBiosId.
> +#  Here, it is just a template and can be customized
> by user.
> +#
> +#  BIOS ID string format:
> +#
> $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$
> (BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM
> +#  All fields must have a fixed length. YYMMDDHHMM is
> UTC time.
> +#    Example: "OVMF.000.0008.D03.1501301017"
> +#
> +#  If DATE is specified for YYMMDD and TIME is
> specified for HHMM like below,
> +#  GenBiosId will use the value of DATE and TIME to
> fill YYMMDDHHMM,
> +#  otherwise GenBiosId will fill YYMMDDHHMM with
> current UTC time of the build machine.
> +#    DATE          = 150130
> +#    TIME          = 1017
> +#
> +# Copyright (c) 2015 - 2019, Intel Corporation. All
> rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +BOARD_ID      = OVMF
> +BOARD_REV     = 1
> +BOARD_EXT     = 000
> +BUILD_TYPE    = D
> +VERSION_MAJOR = 0008
> +VERSION_MINOR = 03
> diff --git a/BaseTools/Source/C/GenBiosId/GNUmakefile
> b/BaseTools/Source/C/GenBiosId/GNUmakefile
> new file mode 100644
> index 000000000000..90a918c13f96
> --- /dev/null
> +++ b/BaseTools/Source/C/GenBiosId/GNUmakefile
> @@ -0,0 +1,14 @@
> +## @file
> +#  makefile for building the GenBiosId utility.
> +#
> +# Copyright (c) 2015 - 2019, Intel Corporation. All
> rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +MAKEROOT ?= ..
> +
> +APPNAME = GenBiosId
> +
> +OBJECTS = GenBiosId.o
> +
> +include $(MAKEROOT)/Makefiles/app.makefile
> diff --git a/BaseTools/Source/C/GenBiosId/GenBiosId.h
> b/BaseTools/Source/C/GenBiosId/GenBiosId.h
> new file mode 100644
> index 000000000000..660fba77e90b
> --- /dev/null
> +++ b/BaseTools/Source/C/GenBiosId/GenBiosId.h
> @@ -0,0 +1,105 @@
> +/** @file
> +Definitions for the GenBiosId tool.
> +
> +Copyright (c) 2015 - 2019, Intel Corporation. All
> rights reserved.<BR>
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef _GEN_BIOS_ID_
> +#define _GEN_BIOS_ID_
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <time.h>
> +#include <Common/UefiBaseTypes.h>
> +
> +#define FILE_NAME_SIZE  256
> +#define MAX_LINE_SIZE   256
> +#define MAX_FORMAT_STRING_SIZE  64
> +
> +#define ATOU(a)         (CHAR16) ((UINT8) (a))
> +#define UTOA(a)         (CHAR8) ((UINT16) (a))
> +
> +//
> +// BIOS ID field names.
> +//
> +#define NAME_BOARD_ID       "BOARD_ID"
> +#define NAME_BOARD_REV      "BOARD_REV"
> +#define NAME_BOARD_EXT      "BOARD_EXT"
> +#define NAME_BUILD_TYPE     "BUILD_TYPE"
> +#define NAME_VERSION_MAJOR  "VERSION_MAJOR"
> +#define NAME_VERSION_MINOR  "VERSION_MINOR"
> +#define NAME_DATE           "DATE"
> +#define NAME_TIME           "TIME"
> +
> +//
> +// Number of ASCII characters in each field
> +//
> +#define CHARS_BOARD_ID      7
> +#define CHARS_BOARD_REV     1
> +#define CHARS_BOARD_EXT     3
> +#define CHARS_BUILD_TYPE    1
> +#define CHARS_VERSION_MAJOR 4
> +#define CHARS_VERSION_MINOR 2
> +#define CHARS_DATE          6
> +#define CHARS_TIME          4
> +
> +#define FIELD_BOARD_ID      0x0001
> +#define FIELD_BOARD_REV     0x0002
> +#define FIELD_BOARD_EXT     0x0004
> +#define FIELD_BUILD_TYPE    0x0008
> +#define FIELD_VERSION_MAJOR 0x0010
> +#define FIELD_VERSION_MINOR 0x0020
> +#define FIELD_DATE          0x0040
> +#define FIELD_TIME          0x0080
> +
> +#define FIELD_ALL (     \
> +  FIELD_BOARD_ID      | \
> +  FIELD_BOARD_REV     | \
> +  FIELD_BOARD_EXT     | \
> +  FIELD_BUILD_TYPE    | \
> +  FIELD_VERSION_MAJOR | \
> +  FIELD_VERSION_MINOR | \
> +  FIELD_DATE          | \
> +  FIELD_TIME)
> +
> +//
> +// BIOS ID string format:
> +//
> +//
> $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$
> (BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM
> +//
> +// Example: "TRFTCRB1.000.0008.D03.1501301017"
> +//
> +// The format should be same as platform BIOS ID
> definition
> +//
> +#pragma pack(1)
> +
> +typedef struct {
> +  CHAR16    BoardId[7];             // "TRFTCRB"
> +  CHAR16    BoardRev;               // "1"
> +  CHAR16    Dot1;                   // "."
> +  CHAR16    BoardExt[3];            // "000"
> +  CHAR16    Dot2;                   // "."
> +  CHAR16    VersionMajor[4];        // "0008"
> +  CHAR16    Dot3;                   // "."
> +  CHAR16    BuildType;              // "D"
> +  CHAR16    VersionMinor[2];        // "03"
> +  CHAR16    Dot4;                   // "."
> +  CHAR16    TimeStamp[10];          // "YYMMDDHHMM"
> +  CHAR16    NullTerminator;         // 0x0000
> +} BIOS_ID_STRING;
> +
> +//
> +// A signature precedes the BIOS ID string in the FV
> to enable search by external tools.
> +//
> +typedef struct {
> +  UINT8             Signature[8];   // "$IBIOSI$"
> +  BIOS_ID_STRING    BiosIdString;   //
> "TRFTCRB1.000.0008.D03.1501301017"
> +} BIOS_ID_IMAGE;
> +
> +#pragma pack()
> +
> +
> +#endif // _GEN_BIOS_ID_
> diff --git a/BaseTools/Source/C/GenBiosId/Makefile
> b/BaseTools/Source/C/GenBiosId/Makefile
> new file mode 100644
> index 000000000000..967a1809b635
> --- /dev/null
> +++ b/BaseTools/Source/C/GenBiosId/Makefile
> @@ -0,0 +1,14 @@
> +## @file
> +#  makefile for building the GenBiosId utility.
> +#
> +# Copyright (c) 2015 - 2019, Intel Corporation. All
> rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +!INCLUDE ..\Makefiles\ms.common
> +
> +APPNAME = GenBiosId
> +
> +OBJECTS = GenBiosId.obj
> +
> +!INCLUDE ..\Makefiles\ms.app
> +
> diff --git a/BaseTools/Source/C/Makefile
> b/BaseTools/Source/C/Makefile
> index 217fc2b91d7b..748565bba9ff 100644
> --- a/BaseTools/Source/C/Makefile
> +++ b/BaseTools/Source/C/Makefile
> @@ -1,7 +1,7 @@
>  ## @file
>  # Windows makefile for C tools build.
>  #
> -# Copyright (c) 2009 - 2018, Intel Corporation. All
> rights reserved.<BR>
> +# Copyright (c) 2009 - 2019, Intel Corporation. All
> rights reserved.<BR>
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
>  HOST_ARCH = IA32
> @@ -12,6 +12,7 @@ LIBRARIES = Common
>  APPLICATIONS = \
>    VfrCompile \
>    BrotliCompress \
> +  GenBiosId \
>    EfiRom \
>    GenCrc32 \
>    GenFfs \
> --
> 2.18.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH] BaseTools/GenBiosId: Add a new tool GenBiosId
  2019-05-28 16:48 ` [edk2-devel] " Michael D Kinney
@ 2019-05-31  6:36   ` Zhang, Shenglei
  0 siblings, 0 replies; 4+ messages in thread
From: Zhang, Shenglei @ 2019-05-31  6:36 UTC (permalink / raw)
  To: Kinney, Michael D, devel@edk2.groups.io



> -----Original Message-----
> From: Kinney, Michael D
> Sent: Wednesday, May 29, 2019 12:49 AM
> To: devel@edk2.groups.io; Zhang, Shenglei <shenglei.zhang@intel.com>;
> Kinney, Michael D <michael.d.kinney@intel.com>
> Subject: RE: [edk2-devel] [PATCH] BaseTools/GenBiosId: Add a new tool
> GenBiosId
> 
> Could this tools be ported to Python using the python
> struct module to access C structures?
> 
> The implementation may be much simpler if python was
> used for command line parsing.  And this capability
> could also be provided as a python module to support
> direct access from pre/post build steps implemented in
> python.
> 

I think it's feasible to using the python structure to substitute C structure.
I'll investigate on it.

Best Regards,
Shenglei

> Thanks,
> 
> Mike
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io
> > [mailto:devel@edk2.groups.io] On Behalf Of Zhang,
> > Shenglei
> > Sent: Monday, May 27, 2019 6:32 PM
> > To: devel@edk2.groups.io
> > Subject: [edk2-devel] [PATCH] BaseTools/GenBiosId: Add
> > a new tool GenBiosId
> >
> > GenBiosId is a tool to generate the BIOS ID binary file
> > which uses
> > the data from the configuration file.
> > https://bugzilla.tianocore.org/show_bug.cgi?id=1846
> >
> > Signed-off-by: Shenglei Zhang
> > <shenglei.zhang@intel.com>
> > ---
> >  BaseTools/Source/C/GenBiosId/GenBiosId.c | 627
> > +++++++++++++++++++++++
> >  BaseTools/Source/C/GNUmakefile           |   3 +-
> >  BaseTools/Source/C/GenBiosId/BiosId.env  |  27 +
> >  BaseTools/Source/C/GenBiosId/GNUmakefile |  14 +
> >  BaseTools/Source/C/GenBiosId/GenBiosId.h | 105 ++++
> >  BaseTools/Source/C/GenBiosId/Makefile    |  14 +
> >  BaseTools/Source/C/Makefile              |   3 +-
> >  7 files changed, 791 insertions(+), 2 deletions(-)
> >  create mode 100644
> > BaseTools/Source/C/GenBiosId/GenBiosId.c
> >  create mode 100644
> > BaseTools/Source/C/GenBiosId/BiosId.env
> >  create mode 100644
> > BaseTools/Source/C/GenBiosId/GNUmakefile
> >  create mode 100644
> > BaseTools/Source/C/GenBiosId/GenBiosId.h
> >  create mode 100644
> > BaseTools/Source/C/GenBiosId/Makefile
> >
> > diff --git a/BaseTools/Source/C/GenBiosId/GenBiosId.c
> > b/BaseTools/Source/C/GenBiosId/GenBiosId.c
> > new file mode 100644
> > index 000000000000..21d71d4ebd51
> > --- /dev/null
> > +++ b/BaseTools/Source/C/GenBiosId/GenBiosId.c
> > @@ -0,0 +1,627 @@
> > +/** @file
> > +This tool generates the BIOS ID binary file using the
> > data from the configuration file.
> > +
> > +Copyright (c) 2015 - 2019, Intel Corporation. All
> > rights reserved.<BR>
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include "GenBiosId.h"
> > +
> > +CHAR8          InputFileName[FILE_NAME_SIZE];
> > +CHAR8          OutputFileName[FILE_NAME_SIZE];
> > +CHAR8          OutputBatchFileName[FILE_NAME_SIZE];
> > +
> > +FILE          *InputFile;
> > +FILE          *OutputFile;
> > +FILE          *OutputBatchFile;
> > +
> > +BIOS_ID_IMAGE BiosIdImage = {
> > +  { '$', 'I', 'B', 'I', 'O', 'S', 'I', '$' },
> > +  {
> > +    { ATOU (' '), ATOU (' '), ATOU (' '), ATOU (' '),
> > ATOU (' '), ATOU (' '), ATOU (' ') },
> > +    ATOU (' '),
> > +    ATOU ('.'),
> > +    { ATOU (' '), ATOU (' '), ATOU (' ') },
> > +    ATOU ('.'),
> > +    { ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0')
> > },
> > +    ATOU ('.'),
> > +    ATOU (' '),
> > +    { ATOU ('0'), ATOU ('0') },
> > +    ATOU ('.'),
> > +    { ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0'),
> > ATOU ('0'),
> > +      ATOU ('0'), ATOU ('0'), ATOU ('0'), ATOU ('0'),
> > ATOU ('0') },
> > +    ATOU ('\0')
> > +  }
> > +};
> > +
> > +VOID
> > +PrintBanner (
> > +  VOID
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +Arguments:
> > +
> > +Returns:
> > +
> > +--*/
> > +{
> > +  printf ("\n");
> > +  printf ("GenBiosId utility, version: v1.0 05/27/2018
> > \n");
> > +  printf ("Copyright (c) 2019, Intel Corporation. All
> > rights reserved.   \n");
> > +  printf ("\n");
> > +}
> > +
> > +VOID
> > +PrintUsage (
> > +  VOID
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +Arguments:
> > +
> > +Returns:
> > +
> > +--*/
> > +{
> > +  printf ("Usage:\n");
> > +  printf ("GenBiosId -i ConfigFile -o OutputFile [-ob
> > OutputBatchFile] \n");
> > +  printf ("\n");
> > +}
> > +
> > +CHAR8 *
> > +StripLeadingWhiteSpace (
> > +  IN CHAR8 *StrInput
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +  Strip the leading whitespoace off the given ASCII
> > string.
> > +
> > +Arguments:
> > +
> > +  StrInput  - the ASCII string that should be
> > processed.
> > +
> > +Returns:
> > +
> > +  A pointer to the first non-whitespace character in
> > the given string,
> > +  or NULL if the string was all whitespace.
> > +
> > +--*/
> > +{
> > +  if (StrInput == NULL) {
> > +    return NULL;
> > +  }
> > +
> > +  while (*StrInput != 0) {
> > +    if ((*StrInput == ' ') || (*StrInput == '\t') ||
> > (*StrInput == '\n')) {
> > +      ++StrInput;
> > +    } else {
> > +      return StrInput;
> > +    }
> > +  }
> > +
> > +  return NULL;
> > +}
> > +
> > +VOID
> > +ConvertToUnicode (
> > +  IN  CHAR8  *StrAscii,
> > +  OUT CHAR16 *StrUnicode
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +  Convert the given ASCII string to Unicode without
> > appending terminating 0x0000.
> > +
> > +Arguments:
> > +
> > +  StrAscii    - the source ASCII string, null-
> > terminated.
> > +
> > +  StrUnicode  - the resulted Unicode string will be
> > put here, without the terminating 0x0000.
> > +
> > +Returns:
> > +
> > +--*/
> > +{
> > +  if ((StrAscii == NULL) || (StrUnicode == NULL)) {
> > +    return;
> > +  }
> > +
> > +  while (*StrAscii != 0) {
> > +    *StrUnicode = ATOU (*StrAscii);
> > +    ++StrAscii;
> > +    ++StrUnicode;
> > +  }
> > +}
> > +
> > +VOID
> > +FillTimeStamp (
> > +  OUT CHAR16  *StrTimeStampUnicode
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +  The function generates the current timestamp in
> > "YYMMDDHHMM" format
> > +  and puts it into the Unicode string supplied,
> > without the null-terminator.
> > +
> > +Arguments:
> > +
> > +  StrTimeStampUnicode - The Unicode string which is
> > filled on return with the current timestamp.
> > +
> > +Returns:
> > +
> > +--*/
> > +{
> > +  struct tm *Time;
> > +  time_t    CurTime;
> > +  CHAR8     StrTime[11];
> > +
> > +  //
> > +  // Fetch the current time based on UTC timezone
> > +  //
> > +  time (&CurTime);
> > +  Time = gmtime (&CurTime);
> > +
> > +  if (NULL == Time) {
> > +    return;
> > +  }
> > +
> > +  sprintf (
> > +    StrTime,
> > +    "%02d%02d%02d%02d%02d",
> > +    (Time->tm_year + 1900) % 100, // Year is 1900-
> > based, need only 2 digits.
> > +    Time->tm_mon + 1,             // Month is zero
> > based.
> > +    Time->tm_mday,
> > +    Time->tm_hour,
> > +    Time->tm_min
> > +    );
> > +
> > +  ConvertToUnicode (StrTime, StrTimeStampUnicode);
> > +}
> > +
> > +VOID
> > +ConvertToAscii (
> > +  IN  CHAR16 *StrUnicode,
> > +  OUT CHAR8  *StrAscii
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +  Convert the given Unicode string to ASCII with
> > appending terminating 0x00.
> > +
> > +Arguments:
> > +
> > +  StrUnicode  - the source Unicode string, null-
> > terminated.
> > +
> > +  StrAscii    - the resulted ASCII string will be put
> > here, with the terminating 0x00.
> > +
> > +Returns:
> > +
> > +--*/
> > +{
> > +  if ((StrUnicode == NULL) || (StrAscii == NULL)) {
> > +    return;
> > +  }
> > +
> > +  while (*StrUnicode != 0) {
> > +    *StrAscii = UTOA (*StrUnicode);
> > +    ++StrUnicode;
> > +    ++StrAscii;
> > +  }
> > +  *StrAscii = 0;
> > +}
> > +
> > +VOID
> > +PrintUnicodeString (
> > +  IN CHAR16 *StrUnicode
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +  Print the given Unicode string.
> > +
> > +Arguments:
> > +
> > +  StrUnicode  - the null-terminated Unicode string to
> > print.
> > +
> > +Returns:
> > +
> > +--*/
> > +{
> > +  if (StrUnicode == NULL) {
> > +    return;
> > +  }
> > +
> > +  while (*StrUnicode != 0) {
> > +    putchar ((CHAR8)(*StrUnicode));
> > +    ++StrUnicode;
> > +  }
> > +}
> > +
> > +EFI_STATUS
> > +ParseInputFile (
> > +  VOID
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +  Parse the BIOS ID definition file and fill the BIOS
> > ID structure, including timestamp.
> > +
> > +Arguments:
> > +
> > +Returns:
> > +
> > +  EFI_SUCCESS           - The input file was parsed
> > successfully.
> > +
> > +  EFI_INVALID_PARAMETER - The input file has incorrect
> > format.
> > +
> > +--*/
> > +{
> > +  CHAR8   StrLine[MAX_LINE_SIZE];
> > +  CHAR8   StrFieldName[MAX_LINE_SIZE];
> > +  CHAR8   StrFieldValue[MAX_LINE_SIZE];
> > +  CHAR8   *Str;
> > +  UINT16  FieldsSet;
> > +  CHAR8   FormatString[MAX_FORMAT_STRING_SIZE];
> > +
> > +  FieldsSet = 0;
> > +  Str       = NULL;
> > +
> > +  //
> > +  // Generate the format string for sscanf() function.
> > +  //
> > +  sprintf (FormatString, "%%%us = %%%us", (unsigned
> > int) sizeof (StrFieldName) - 1, (unsigned int) sizeof
> > (StrFieldValue) - 1);
> > +
> > +  while (fgets (StrLine, sizeof (StrLine) - 1,
> > InputFile) != NULL) {
> > +    Str = StripLeadingWhiteSpace (StrLine);
> > +
> > +    //
> > +    // Check for whitespace string.
> > +    //
> > +    if (Str == NULL) {
> > +      continue;
> > +    }
> > +
> > +    //
> > +    // Check for comment string.
> > +    //
> > +    if (*Str == '#') {
> > +      continue;
> > +    }
> > +
> > +    if (sscanf (Str, FormatString, StrFieldName,
> > StrFieldValue) != 2) {
> > +      continue;
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_BOARD_ID) == 0) {
> > +      if (strlen (StrFieldValue) == CHARS_BOARD_ID) {
> > +        ConvertToUnicode (StrFieldValue,
> > BiosIdImage.BiosIdString.BoardId);
> > +        FieldsSet |= FIELD_BOARD_ID;
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_BOARD_ID, CHARS_BOARD_ID);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_BOARD_REV) == 0) {
> > +      if (strlen (StrFieldValue) == CHARS_BOARD_REV) {
> > +        ConvertToUnicode (StrFieldValue,
> > &(BiosIdImage.BiosIdString.BoardRev));
> > +        FieldsSet |= FIELD_BOARD_REV;
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_BOARD_REV, CHARS_BOARD_REV);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_BOARD_EXT) == 0) {
> > +      if (strlen (StrFieldValue) == CHARS_BOARD_EXT) {
> > +        ConvertToUnicode (StrFieldValue,
> > BiosIdImage.BiosIdString.BoardExt);
> > +        FieldsSet |= FIELD_BOARD_EXT;
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_BOARD_EXT, CHARS_BOARD_EXT);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_BUILD_TYPE) == 0) {
> > +      if (strlen (StrFieldValue) == CHARS_BUILD_TYPE)
> > {
> > +        if ((strcmp (StrFieldValue, "D") == 0) ||
> > +            (strcmp (StrFieldValue, "A") == 0) ||
> > +            (strcmp (StrFieldValue, "B") == 0) ||
> > +            (strcmp (StrFieldValue, "P") == 0)) {
> > +          ConvertToUnicode (StrFieldValue,
> > &(BiosIdImage.BiosIdString.BuildType));
> > +          FieldsSet |= FIELD_BUILD_TYPE;
> > +        } else {
> > +          printf ("Error: value of %s should be one of
> > %s, %s, %s or %s\n", NAME_BUILD_TYPE, "D", "A", "B",
> > "P");
> > +          return EFI_INVALID_PARAMETER;
> > +        }
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_BUILD_TYPE,
> > CHARS_BUILD_TYPE);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_VERSION_MAJOR) ==
> > 0) {
> > +      if (strlen (StrFieldValue) ==
> > CHARS_VERSION_MAJOR) {
> > +        ConvertToUnicode (StrFieldValue,
> > BiosIdImage.BiosIdString.VersionMajor);
> > +        FieldsSet |= FIELD_VERSION_MAJOR;
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_VERSION_MAJOR,
> > CHARS_VERSION_MAJOR);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_VERSION_MINOR) ==
> > 0) {
> > +      if (strlen (StrFieldValue) ==
> > CHARS_VERSION_MINOR) {
> > +        ConvertToUnicode (StrFieldValue,
> > BiosIdImage.BiosIdString.VersionMinor);
> > +        FieldsSet |= FIELD_VERSION_MINOR;
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_VERSION_MINOR,
> > CHARS_VERSION_MINOR);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_DATE) == 0) {
> > +      if (strlen (StrFieldValue) == CHARS_DATE) {
> > +        ConvertToUnicode (StrFieldValue,
> > BiosIdImage.BiosIdString.TimeStamp);
> > +        FieldsSet |= FIELD_DATE;
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_DATE, CHARS_DATE);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +    if (strcmp (StrFieldName, NAME_TIME) == 0) {
> > +      if (strlen (StrFieldValue) == CHARS_TIME) {
> > +        ConvertToUnicode (StrFieldValue,
> > &(BiosIdImage.BiosIdString.TimeStamp[CHARS_DATE]));
> > +        FieldsSet |= FIELD_TIME;
> > +      } else {
> > +        printf ("Error: value of %s should have
> > exactly %d chars\n", NAME_TIME, CHARS_TIME);
> > +        return EFI_INVALID_PARAMETER;
> > +      }
> > +    }
> > +
> > +  }
> > +
> > +  if ((FieldsSet & (FIELD_DATE | FIELD_TIME)) !=
> > (FIELD_DATE | FIELD_TIME)) {
> > +    //
> > +    // Fill the timestamp.
> > +    //
> > +    FillTimeStamp
> > (BiosIdImage.BiosIdString.TimeStamp);
> > +    FieldsSet |= (FIELD_DATE | FIELD_TIME);
> > +  }
> > +
> > +  //
> > +  // Exit if not all fields were supplied.
> > +  //
> > +  if ((FieldsSet & FIELD_ALL) != FIELD_ALL) {
> > +    return EFI_INVALID_PARAMETER;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +EFI_STATUS
> > +WriteOutputFile (
> > +  VOID
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +  Write the BIOS ID structure to the output file.
> > +
> > +Arguments:
> > +
> > +Returns:
> > +
> > +  EFI_SUCCESS       - The output file was created
> > successfully.
> > +
> > +  EFI_DEVICE_ERROR  - There was a file write error.
> > +
> > +--*/
> > +{
> > +  if (fwrite (&BiosIdImage, sizeof (BIOS_ID_IMAGE), 1,
> > OutputFile) != 1) {
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +EFI_STATUS
> > +WriteOutputBatchFile (
> > +  VOID
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +  Write "SET BIOS_ID=" and BIOS ID string to the batch
> > file.
> > +
> > +Arguments:
> > +
> > +Returns:
> > +
> > +  EFI_SUCCESS       - The output batch file was
> > created successfully.
> > +
> > +  EFI_DEVICE_ERROR  - There was a file write error.
> > +
> > +--*/
> > +{
> > +#ifndef __GNUC__
> > +  CHAR8 BatchFileContent[MAX_LINE_SIZE] = "SET
> > BIOS_ID=";
> > +#else
> > +  CHAR8 BatchFileContent[MAX_LINE_SIZE] = "export
> > BIOS_ID=";
> > +#endif
> > +
> > +  CHAR8 BiosIdString[sizeof (BIOS_ID_STRING)];
> > +
> > +  ConvertToAscii ((CHAR16 *)
> > (&(BiosIdImage.BiosIdString)), BiosIdString);
> > +  strcat (BatchFileContent, BiosIdString);
> > +
> > +  if (fwrite (BatchFileContent, strlen
> > (BatchFileContent), 1, OutputBatchFile) != 1) {
> > +    return EFI_DEVICE_ERROR;
> > +  }
> > +
> > +  return EFI_SUCCESS;
> > +}
> > +
> > +int
> > +main (
> > +  IN  int   argc,
> > +  IN  CHAR8 *argv[]
> > +  )
> > +/*++
> > +
> > +Routine Description:
> > +
> > +Arguments:
> > +
> > +  argc  - Number of command-line arguments.
> > +
> > +  argv  - Array of command-line arguments.
> > +
> > +Returns:
> > +
> > +  0   - The operation completed successfully.
> > +
> > +  -1  - An error occurred.
> > +
> > +--*/
> > +{
> > +  int Status;
> > +
> > +  Status = 0;
> > +
> > +  PrintBanner ();
> > +
> > +  if ((argc != 5) && (argc != 7)) {
> > +    PrintUsage ();
> > +    Status = -1;
> > +    goto Done;
> > +  }
> > +
> > +  if (strcmp (argv[1], "-i") == 0) {
> > +    if (strlen (argv[2])> sizeof (InputFileName) - 1)
> > {
> > +      printf ("The InputFileName %s is too long \n",
> > argv[2]);
> > +      Status = -1;
> > +      goto Done;
> > +    }
> > +    strncpy (InputFileName, argv[2], sizeof
> > (InputFileName) - 1);
> > +    InputFileName[sizeof (InputFileName) - 1] = 0;
> > +  } else {
> > +    PrintUsage ();
> > +    Status = -1;
> > +    goto Done;
> > +  }
> > +
> > +  if (strcmp (argv[3], "-o") == 0) {
> > +    if (strlen (argv[4])> sizeof (OutputFileName) - 1)
> > {
> > +      printf ("OutputFileName %s is too long \n",
> > argv[4]);
> > +      Status = -1;
> > +      goto Done;
> > +    }
> > +    strncpy (OutputFileName, argv[4], sizeof
> > (OutputFileName) - 1);
> > +    OutputFileName[sizeof (OutputFileName) - 1] = 0;
> > +  } else {
> > +    PrintUsage ();
> > +    Status = -1;
> > +    goto Done;
> > +  }
> > +
> > +  if (argc == 7) {
> > +    if (strcmp (argv[5], "-ob") == 0) {
> > +      if (strlen (argv[6])> sizeof
> > (OutputBatchFileName) - 1) {
> > +        printf ("The OutputBatchFileName %s is too
> > long \n", argv[6]);
> > +        Status = -1;
> > +        goto Done;
> > +      }
> > +      strncpy (OutputBatchFileName, argv[6], sizeof
> > (OutputBatchFileName) - 1);
> > +      OutputBatchFileName[sizeof (OutputBatchFileName)
> > - 1] = 0;
> > +    } else {
> > +      PrintUsage ();
> > +      Status = -1;
> > +      goto Done;
> > +    }
> > +  }
> > +
> > +  InputFile   = NULL;
> > +  OutputFile  = NULL;
> > +  OutputBatchFile = NULL;
> > +
> > +  InputFile   = fopen (InputFileName, "r");
> > +  if (InputFile == NULL) {
> > +    printf ("Error opening input file: %s\n",
> > InputFileName);
> > +    Status = -1;
> > +    goto Done;
> > +  }
> > +
> > +  OutputFile  = fopen (OutputFileName, "wb");
> > +  if (OutputFile == NULL) {
> > +    printf ("Error creating output file: %s\n",
> > OutputFileName);
> > +    Status = -1;
> > +    goto Done;
> > +  }
> > +
> > +  if (argc == 7) {
> > +    OutputBatchFile = fopen (OutputBatchFileName,
> > "wb");
> > +    if (OutputBatchFile == NULL) {
> > +      printf ("Error creating output batch file:
> > %s\n", OutputBatchFileName);
> > +      Status = -1;
> > +      goto Done;
> > +    }
> > +  }
> > +
> > +  if (ParseInputFile () != EFI_SUCCESS) {
> > +    printf ("Invalid config file format: %s\n",
> > InputFileName);
> > +    Status = -1;
> > +    goto Done;
> > +  }
> > +
> > +  if (WriteOutputFile () != EFI_SUCCESS) {
> > +    printf ("Can't write output file: %s\n",
> > OutputFileName);
> > +    Status = -1;
> > +    goto Done;
> > +  }
> > +
> > +  if (argc == 7) {
> > +    if (WriteOutputBatchFile () != EFI_SUCCESS) {
> > +      printf ("Can't write output batch file: %s\n",
> > OutputBatchFileName);
> > +      Status = -1;
> > +      goto Done;
> > +    }
> > +  }
> > +
> > +  printf ("BIOS ID created: ");
> > +  PrintUnicodeString ((CHAR16
> > *)(&(BiosIdImage.BiosIdString)));
> > +  printf ("\n");
> > +  printf ("BIOS ID binary file created: %s\n",
> > OutputFileName);
> > +
> > +Done:
> > +
> > +  if (InputFile != NULL) {
> > +    fclose (InputFile);
> > +  }
> > +
> > +  if (OutputFile != NULL) {
> > +    fclose (OutputFile);
> > +  }
> > +
> > +  if (OutputBatchFile != NULL) {
> > +    fclose (OutputBatchFile);
> > +  }
> > +
> > +  return Status;
> > +}
> > +
> > diff --git a/BaseTools/Source/C/GNUmakefile
> > b/BaseTools/Source/C/GNUmakefile
> > index 37bcce519c7e..9dbf1a4b06db 100644
> > --- a/BaseTools/Source/C/GNUmakefile
> > +++ b/BaseTools/Source/C/GNUmakefile
> > @@ -1,7 +1,7 @@
> >  ## @file
> >  #  GNU/Linux makefile for C tools build.
> >  #
> > -#  Copyright (c) 2007 - 2017, Intel Corporation. All
> > rights reserved.<BR>
> > +#  Copyright (c) 2007 - 2019, Intel Corporation. All
> > rights reserved.<BR>
> >  #
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >  #
> > @@ -47,6 +47,7 @@ VFRAUTOGEN = VfrCompile/VfrLexer.h
> >  APPLICATIONS = \
> >    BrotliCompress \
> >    VfrCompile \
> > +  GenBiosId \
> >    EfiRom \
> >    GenFfs \
> >    GenFv \
> > diff --git a/BaseTools/Source/C/GenBiosId/BiosId.env
> > b/BaseTools/Source/C/GenBiosId/BiosId.env
> > new file mode 100644
> > index 000000000000..de54273107bd
> > --- /dev/null
> > +++ b/BaseTools/Source/C/GenBiosId/BiosId.env
> > @@ -0,0 +1,27 @@
> > +## @file
> > +#  This file is used to define the BIOS ID parameters
> > of the build.
> > +#  This file is processed by GenBiosId.
> > +#  Here, it is just a template and can be customized
> > by user.
> > +#
> > +#  BIOS ID string format:
> > +#
> > $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$
> > (BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM
> > +#  All fields must have a fixed length. YYMMDDHHMM is
> > UTC time.
> > +#    Example: "OVMF.000.0008.D03.1501301017"
> > +#
> > +#  If DATE is specified for YYMMDD and TIME is
> > specified for HHMM like below,
> > +#  GenBiosId will use the value of DATE and TIME to
> > fill YYMMDDHHMM,
> > +#  otherwise GenBiosId will fill YYMMDDHHMM with
> > current UTC time of the build machine.
> > +#    DATE          = 150130
> > +#    TIME          = 1017
> > +#
> > +# Copyright (c) 2015 - 2019, Intel Corporation. All
> > rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +BOARD_ID      = OVMF
> > +BOARD_REV     = 1
> > +BOARD_EXT     = 000
> > +BUILD_TYPE    = D
> > +VERSION_MAJOR = 0008
> > +VERSION_MINOR = 03
> > diff --git a/BaseTools/Source/C/GenBiosId/GNUmakefile
> > b/BaseTools/Source/C/GenBiosId/GNUmakefile
> > new file mode 100644
> > index 000000000000..90a918c13f96
> > --- /dev/null
> > +++ b/BaseTools/Source/C/GenBiosId/GNUmakefile
> > @@ -0,0 +1,14 @@
> > +## @file
> > +#  makefile for building the GenBiosId utility.
> > +#
> > +# Copyright (c) 2015 - 2019, Intel Corporation. All
> > rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +MAKEROOT ?= ..
> > +
> > +APPNAME = GenBiosId
> > +
> > +OBJECTS = GenBiosId.o
> > +
> > +include $(MAKEROOT)/Makefiles/app.makefile
> > diff --git a/BaseTools/Source/C/GenBiosId/GenBiosId.h
> > b/BaseTools/Source/C/GenBiosId/GenBiosId.h
> > new file mode 100644
> > index 000000000000..660fba77e90b
> > --- /dev/null
> > +++ b/BaseTools/Source/C/GenBiosId/GenBiosId.h
> > @@ -0,0 +1,105 @@
> > +/** @file
> > +Definitions for the GenBiosId tool.
> > +
> > +Copyright (c) 2015 - 2019, Intel Corporation. All
> > rights reserved.<BR>
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef _GEN_BIOS_ID_
> > +#define _GEN_BIOS_ID_
> > +
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <time.h>
> > +#include <Common/UefiBaseTypes.h>
> > +
> > +#define FILE_NAME_SIZE  256
> > +#define MAX_LINE_SIZE   256
> > +#define MAX_FORMAT_STRING_SIZE  64
> > +
> > +#define ATOU(a)         (CHAR16) ((UINT8) (a))
> > +#define UTOA(a)         (CHAR8) ((UINT16) (a))
> > +
> > +//
> > +// BIOS ID field names.
> > +//
> > +#define NAME_BOARD_ID       "BOARD_ID"
> > +#define NAME_BOARD_REV      "BOARD_REV"
> > +#define NAME_BOARD_EXT      "BOARD_EXT"
> > +#define NAME_BUILD_TYPE     "BUILD_TYPE"
> > +#define NAME_VERSION_MAJOR  "VERSION_MAJOR"
> > +#define NAME_VERSION_MINOR  "VERSION_MINOR"
> > +#define NAME_DATE           "DATE"
> > +#define NAME_TIME           "TIME"
> > +
> > +//
> > +// Number of ASCII characters in each field
> > +//
> > +#define CHARS_BOARD_ID      7
> > +#define CHARS_BOARD_REV     1
> > +#define CHARS_BOARD_EXT     3
> > +#define CHARS_BUILD_TYPE    1
> > +#define CHARS_VERSION_MAJOR 4
> > +#define CHARS_VERSION_MINOR 2
> > +#define CHARS_DATE          6
> > +#define CHARS_TIME          4
> > +
> > +#define FIELD_BOARD_ID      0x0001
> > +#define FIELD_BOARD_REV     0x0002
> > +#define FIELD_BOARD_EXT     0x0004
> > +#define FIELD_BUILD_TYPE    0x0008
> > +#define FIELD_VERSION_MAJOR 0x0010
> > +#define FIELD_VERSION_MINOR 0x0020
> > +#define FIELD_DATE          0x0040
> > +#define FIELD_TIME          0x0080
> > +
> > +#define FIELD_ALL (     \
> > +  FIELD_BOARD_ID      | \
> > +  FIELD_BOARD_REV     | \
> > +  FIELD_BOARD_EXT     | \
> > +  FIELD_BUILD_TYPE    | \
> > +  FIELD_VERSION_MAJOR | \
> > +  FIELD_VERSION_MINOR | \
> > +  FIELD_DATE          | \
> > +  FIELD_TIME)
> > +
> > +//
> > +// BIOS ID string format:
> > +//
> > +//
> > $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$
> > (BUILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM
> > +//
> > +// Example: "TRFTCRB1.000.0008.D03.1501301017"
> > +//
> > +// The format should be same as platform BIOS ID
> > definition
> > +//
> > +#pragma pack(1)
> > +
> > +typedef struct {
> > +  CHAR16    BoardId[7];             // "TRFTCRB"
> > +  CHAR16    BoardRev;               // "1"
> > +  CHAR16    Dot1;                   // "."
> > +  CHAR16    BoardExt[3];            // "000"
> > +  CHAR16    Dot2;                   // "."
> > +  CHAR16    VersionMajor[4];        // "0008"
> > +  CHAR16    Dot3;                   // "."
> > +  CHAR16    BuildType;              // "D"
> > +  CHAR16    VersionMinor[2];        // "03"
> > +  CHAR16    Dot4;                   // "."
> > +  CHAR16    TimeStamp[10];          // "YYMMDDHHMM"
> > +  CHAR16    NullTerminator;         // 0x0000
> > +} BIOS_ID_STRING;
> > +
> > +//
> > +// A signature precedes the BIOS ID string in the FV
> > to enable search by external tools.
> > +//
> > +typedef struct {
> > +  UINT8             Signature[8];   // "$IBIOSI$"
> > +  BIOS_ID_STRING    BiosIdString;   //
> > "TRFTCRB1.000.0008.D03.1501301017"
> > +} BIOS_ID_IMAGE;
> > +
> > +#pragma pack()
> > +
> > +
> > +#endif // _GEN_BIOS_ID_
> > diff --git a/BaseTools/Source/C/GenBiosId/Makefile
> > b/BaseTools/Source/C/GenBiosId/Makefile
> > new file mode 100644
> > index 000000000000..967a1809b635
> > --- /dev/null
> > +++ b/BaseTools/Source/C/GenBiosId/Makefile
> > @@ -0,0 +1,14 @@
> > +## @file
> > +#  makefile for building the GenBiosId utility.
> > +#
> > +# Copyright (c) 2015 - 2019, Intel Corporation. All
> > rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +!INCLUDE ..\Makefiles\ms.common
> > +
> > +APPNAME = GenBiosId
> > +
> > +OBJECTS = GenBiosId.obj
> > +
> > +!INCLUDE ..\Makefiles\ms.app
> > +
> > diff --git a/BaseTools/Source/C/Makefile
> > b/BaseTools/Source/C/Makefile
> > index 217fc2b91d7b..748565bba9ff 100644
> > --- a/BaseTools/Source/C/Makefile
> > +++ b/BaseTools/Source/C/Makefile
> > @@ -1,7 +1,7 @@
> >  ## @file
> >  # Windows makefile for C tools build.
> >  #
> > -# Copyright (c) 2009 - 2018, Intel Corporation. All
> > rights reserved.<BR>
> > +# Copyright (c) 2009 - 2019, Intel Corporation. All
> > rights reserved.<BR>
> >  # SPDX-License-Identifier: BSD-2-Clause-Patent
> >  #
> >  HOST_ARCH = IA32
> > @@ -12,6 +12,7 @@ LIBRARIES = Common
> >  APPLICATIONS = \
> >    VfrCompile \
> >    BrotliCompress \
> > +  GenBiosId \
> >    EfiRom \
> >    GenCrc32 \
> >    GenFfs \
> > --
> > 2.18.0.windows.1
> >
> >
> > 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH] BaseTools/GenBiosId: Add a new tool GenBiosId
  2019-06-14  7:38 Zhang, Shenglei
@ 2019-06-14 15:06 ` Michael D Kinney
  0 siblings, 0 replies; 4+ messages in thread
From: Michael D Kinney @ 2019-06-14 15:06 UTC (permalink / raw)
  To: devel@edk2.groups.io, Zhang, Shenglei, Kinney, Michael D
  Cc: Fan, ZhijuX, Feng, Bob C, Gao, Liming

Thank you for converting to Python.

Please use python argparse module to parse arguments and make
sure the tool supports the standard EDK II tool command line
arguments.  BinToPcd is a good example:

https://github.com/tianocore/edk2/blob/master/BaseTools/Scripts/BinToPcd.py

Mike

> -----Original Message-----
> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io]
> On Behalf Of Zhang, Shenglei
> Sent: Friday, June 14, 2019 12:39 AM
> To: devel@edk2.groups.io
> Cc: Fan, ZhijuX <zhijux.fan@intel.com>; Feng, Bob C
> <bob.c.feng@intel.com>; Gao, Liming
> <liming.gao@intel.com>
> Subject: [edk2-devel] [PATCH] BaseTools/GenBiosId: Add a
> new tool GenBiosId
> 
> From: "Fan, Zhiju" <zhijux.fan@intel.com>
> 
> GenBiosId is a tool to generate the BIOS ID binary file
> which uses the data from the configuration file.
> https://bugzilla.tianocore.org/show_bug.cgi?id=1846
> 
> v2:v1 is a tool of C type and v2 is python type.
> 
> Cc: Bob Feng <bob.c.feng@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com>
> ---
>  BaseTools/BinWrappers/PosixLike/GenBiosId     |  14 +++
>  .../BinWrappers/WindowsLike/GenBiosId.bat     |   3 +
>  BaseTools/Source/Python/GenBiosId/BiosId.env  |  27
> +++++
>  .../Source/Python/GenBiosId/GenBiosId.py      | 108
> ++++++++++++++++++
>  4 files changed, 152 insertions(+)
>  create mode 100644
> BaseTools/BinWrappers/PosixLike/GenBiosId
>  create mode 100644
> BaseTools/BinWrappers/WindowsLike/GenBiosId.bat
>  create mode 100644
> BaseTools/Source/Python/GenBiosId/BiosId.env
>  create mode 100644
> BaseTools/Source/Python/GenBiosId/GenBiosId.py
> 
> diff --git a/BaseTools/BinWrappers/PosixLike/GenBiosId
> b/BaseTools/BinWrappers/PosixLike/GenBiosId
> new file mode 100644
> index 000000000000..9fb68299e4c6
> --- /dev/null
> +++ b/BaseTools/BinWrappers/PosixLike/GenBiosId
> @@ -0,0 +1,14 @@
> +#!/usr/bin/env bash
> +#python `dirname $0`/RunToolFromSource.py `basename $0`
> $*
> +
> +# If a ${PYTHON_COMMAND} command is available, use it in
> preference to
> +python if command -v ${PYTHON_COMMAND} >/dev/null 2>&1;
> then
> +    python_exe=${PYTHON_COMMAND}
> +fi
> +
> +full_cmd=${BASH_SOURCE:-$0} # see
> +http://mywiki.wooledge.org/BashFAQ/028 for a discussion
> of why $0 is
> +not a good choice here dir=$(dirname "$full_cmd")
> exe=$(basename
> +"$full_cmd")
> +
> +export
> PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYTH
> ONPATH"}"
> +exec "${python_exe:-python}"
> "$dir/../../Source/Python/$exe/$exe.py" "$@"
> diff --git
> a/BaseTools/BinWrappers/WindowsLike/GenBiosId.bat
> b/BaseTools/BinWrappers/WindowsLike/GenBiosId.bat
> new file mode 100644
> index 000000000000..9616cd893bec
> --- /dev/null
> +++ b/BaseTools/BinWrappers/WindowsLike/GenBiosId.bat
> @@ -0,0 +1,3 @@
> +@setlocal
> +@set ToolName=%~n0%
> +@%PYTHON_COMMAND%
> +%BASE_TOOLS_PATH%\Source\Python\%ToolName%\%ToolName%.py
> %*
> diff --git a/BaseTools/Source/Python/GenBiosId/BiosId.env
> b/BaseTools/Source/Python/GenBiosId/BiosId.env
> new file mode 100644
> index 000000000000..92805e3cb78c
> --- /dev/null
> +++ b/BaseTools/Source/Python/GenBiosId/BiosId.env
> @@ -0,0 +1,27 @@
> +## @file
> +#  This file is used to define the BIOS ID parameters of
> the build.
> +#  This file is processed by GenBiosId.
> +#  Here, it is just a template and can be customized by
> user.
> +#
> +#  BIOS ID string format:
> +#
> $(BOARD_ID)$(BOARD_REV).$(BOARD_EXT).$(VERSION_MAJOR).$(B
> UILD_TYPE)$(VERSION_MINOR).YYMMDDHHMM
> +#  All fields must have a fixed length. YYMMDDHHMM is
> UTC time.
> +#    Example: "EMLATOR1.000.0001.D01.1906141517"
> +#
> +#  If DATE is specified for YYMMDD and TIME is specified
> for HHMM like
> +below, #  GenBiosId will use the value of DATE and TIME
> to fill
> +YYMMDDHHMM, #  otherwise GenBiosId will fill YYMMDDHHMM
> with current UTC time of the build machine.
> +#    DATE          = 190614
> +#    TIME          = 1517
> +#
> +#  Copyright (c) 2019, Intel Corporation. All rights
> reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent # ##
> [config]
> +BOARD_ID      = EMLATOR
> +BOARD_REV     = 1
> +BOARD_EXT     = 000
> +BUILD_TYPE    = D
> +VERSION_MAJOR = 0001
> +VERSION_MINOR = 01
> diff --git
> a/BaseTools/Source/Python/GenBiosId/GenBiosId.py
> b/BaseTools/Source/Python/GenBiosId/GenBiosId.py
> new file mode 100644
> index 000000000000..1be99f4a5931
> --- /dev/null
> +++ b/BaseTools/Source/Python/GenBiosId/GenBiosId.py
> @@ -0,0 +1,108 @@
> +## @file
> +# Trim files preprocessed by compiler
> +#
> +# Copyright (c) 2019, Intel Corporation. All rights
> reserved.<BR> #
> +SPDX-License-Identifier: BSD-2-Clause-Patent #
> +
> +##
> +# Import Modules
> +#
> +import Common.LongFilePathOs as os
> +import sys
> +import struct
> +import time
> +import datetime
> +try:
> +    from configparser import ConfigParser
> +except:
> +    from ConfigParser import ConfigParser from
> Common.BuildToolError
> +import * from Common.Misc import * from Common.DataType
> import * from
> +Common.BuildVersion import gBUILD_VERSION import
> Common.EdkLogger as
> +EdkLogger from Common.LongFilePathSupport import
> OpenLongFilePath as
> +open
> +
> +_BIOS_Signature = "$IBIOSI$"
> +_SectionKeyName = '__name__'
> +_SectionName = 'config'
> +
> +_ConfigItem = {
> +    "BOARD_ID"   : {'Value' : '', 'Length' : 7},
> +    "BOARD_REV"  : {'Value' : '', 'Length' : 1},
> +    "BOARD_EXT"  : { 'Value' : '', 'Length' : 3},
> +    "BUILD_TYPE" : {'Value' : '', 'Length' :1},
> +    "VERSION_MAJOR" : {'Value' : '0000', 'Length' : 4},
> +    "VERSION_MINOR" : {'Value' : '00', 'Length' : 2},
> +
> +}
> +
> +
> +_Usage = "Usage: GenBiosId -i Configfile -o OutputFile
> [-ob OutputBatchFile]"
> +_ConfigSectionNotDefine = "Not support the config file
> format, need config section"
> +_ConfigLenInvalid = "Config item %s length is invalid"
> +_ConfigItemInvalid = "Item %s is invalid"
> +
> +def Main():
> +    try:
> +        EdkLogger.Initialize()
> +        if len(sys.argv) !=5 and len(sys.argv) != 7:
> +            EdkLogger.error("GenBiosId", OPTION_MISSING,
> ExtraData=_Usage)
> +    except FatalError as X:
> +        return 1
> +    InputFile = ''
> +    OutputFile = ''
> +    OutputBatchFile = ''
> +    for Index, Item in enumerate(sys.argv):
> +        if '-i' == Item:
> +            InputFile = sys.argv[Index + 1]
> +        if '-o' == Item:
> +            OutputFile = sys.argv[Index + 1]
> +        if '-ob' == Item:
> +            OutputBatchFile = sys.argv[Index + 1]
> +    if not os.path.exists(InputFile):
> +        EdkLogger.error("GenBiosId", FILE_NOT_FOUND,
> ExtraData="Input file not found")
> +    cf = ConfigParser()
> +    cf.optionxform = str
> +    cf.read(InputFile)
> +    if _SectionName not in cf._sections:
> +        EdkLogger.error("GenBiosId",
> FORMAT_NOT_SUPPORTED, ExtraData=_ConfigSectionNotDefine)
> +    for Item in cf._sections[_SectionName]:
> +        if Item == _SectionKeyName:
> +            continue
> +        if Item not in _ConfigItem:
> +            EdkLogger.error("GenBiosId", FORMAT_INVALID,
> ExtraData=_ConfigItemInvalid % Item)
> +        _ConfigItem[Item]['Value'] =
> cf._sections[_SectionName][Item]
> +        if len(_ConfigItem[Item]['Value']) !=
> _ConfigItem[Item]['Length']:
> +            EdkLogger.error("GenBiosId", FORMAT_INVALID,
> ExtraData=_ConfigLenInvalid % Item)
> +    for Item in _ConfigItem:
> +        if not _ConfigItem[Item]['Value']:
> +            EdkLogger.error("GenBiosId",
> FORMAT_UNKNOWN_ERROR, ExtraData="Item %s is missing" %
> Item)
> +    utcnow = datetime.datetime.utcnow()
> +    TimeStamp = time.strftime("%y%m%d%H%M",
> utcnow.timetuple())
> +
> +    Id_Str = _ConfigItem['BOARD_ID']['Value'] +
> _ConfigItem['BOARD_REV']['Value'] + '.' +
> _ConfigItem['BOARD_EXT']['Value'] + '.' +
> _ConfigItem['VERSION_MAJOR']['Value'] + \
> +             '.' + _ConfigItem["BUILD_TYPE"]['Value'] +
> _ConfigItem['VERSION_MINOR']['Value'] + '.' + TimeStamp
> +    with open(OutputFile, 'wb') as FdOut:
> +        for i in _BIOS_Signature:
> +            FdOut.write(struct.pack('B', ord(i)))
> +
> +        for i in Id_Str:
> +            FdOut.write(struct.pack('H', ord(i)))
> +
> +        FdOut.write(struct.pack('H', 0x00))
> +    if OutputBatchFile:
> +        with open(OutputBatchFile, 'w') as FdOut:
> +            if sys.platform.startswith('win'):
> +                Id_Str = 'SET BIOS_ID=' + Id_Str
> +            else:
> +                Id_Str = 'export BIOS_ID=' + Id_Str
> +            FdOut.write(Id_Str)
> +    return 0
> +
> +if __name__ == '__main__':
> +    r = Main()
> +    ## 0-127 is a safe return range, and 1 is a standard
> default error
> +    if r < 0 or r > 127: r = 1
> +    sys.exit(r)
> --
> 2.18.0.windows.1
> 
> 
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-06-14 15:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-05-28  1:32 [PATCH] BaseTools/GenBiosId: Add a new tool GenBiosId Zhang, Shenglei
2019-05-28 16:48 ` [edk2-devel] " Michael D Kinney
2019-05-31  6:36   ` Zhang, Shenglei
  -- strict thread matches above, loose matches on Subject: below --
2019-06-14  7:38 Zhang, Shenglei
2019-06-14 15:06 ` [edk2-devel] " Michael D Kinney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox