<div dir="ltr">Thanks for the information. I will drop this patch in Patch set v2 for now and work with Trammell to revise this patch to fit EDK2 style.<div><div><br></div><div>--</div><div>Cheng-Chieh</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Aug 4, 2021 at 11:00 AM Dong, Guo <<a href="mailto:guo.dong@intel.com">guo.dong@intel.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Please run BaseTools\Scripts\PatchCheck.py to make sure it passed the check.<br>
<br>
Update LbParseLib.c following <a href="https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/" rel="noreferrer" target="_blank">https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/</a>.<br>
current code is more like Linux style. E.g.<br>
+static uint64_t parse_int(const char* s, char** end) {<br>
+  UINT64 x;<br>
<br>
Removed unused comments<br>
+//#include <string.h><br>
+//#include <ctype.h><br>
<br>
<br>
Thanks,<br>
Guo<br>
-----Original Message-----<br>
From: <a href="mailto:devel@edk2.groups.io" target="_blank">devel@edk2.groups.io</a> <<a href="mailto:devel@edk2.groups.io" target="_blank">devel@edk2.groups.io</a>> On Behalf Of Cheng-Chieh Huang via <a href="http://groups.io" rel="noreferrer" target="_blank">groups.io</a><br>
Sent: Wednesday, July 21, 2021 6:23 AM<br>
To: <a href="mailto:devel@edk2.groups.io" target="_blank">devel@edk2.groups.io</a><br>
Cc: Trammell Hudson <<a href="mailto:hudson@trmm.net" target="_blank">hudson@trmm.net</a>>; Cheng-Chieh Huang <<a href="mailto:chengchieh@google.com" target="_blank">chengchieh@google.com</a>><br>
Subject: [edk2-devel] [PATCH v1 6/6] UefiPayloadPkg: LinuxBoot: use a text format for the configuration block.<br>
<br>
From: Trammell Hudson <<a href="mailto:hudson@trmm.net" target="_blank">hudson@trmm.net</a>><br>
<br>
This adds a text command line for the UefiPayloadPkg that uses a textual magic number 'LnxBoot1' and a series of white-space separated key=value[,value...] pairs for the parameters.<br>
<br>
The v1 binary configuration structure is used if it is present instead for backwards compatability.<br>
<br>
Currently supported text command line arguments are are:<br>
<br>
* `serial=baud,base,width,type,hz,pci`<br>
(only `baud` needs to be specified, the rest have reasonable<br>
defaults)<br>
<br>
* `mem=start,end,type`<br>
Types are based on `/sys/firmware/memmaps/*/types`:<br>
    1 == "System RAM"<br>
    3 == "ACPI Tables"<br>
    4 == "ACPI Non-volatile Storage"<br>
    5 == "Reserved"<br>
<br>
* `ACPI20=base` pointer to RDSP (from `/sys/firmware/efi/systab`)<br>
<br>
* `SMBIOS=base` pointer to the SMBIOS table (also from the EFI table)<br>
<br>
Signed-off-by: Cheng-Chieh Huang <<a href="mailto:chengchieh@google.com" target="_blank">chengchieh@google.com</a>><br>
---<br>
 UefiPayloadPkg/Include/Linuxboot.h             |  17 +-<br>
 UefiPayloadPkg/Library/LbParseLib/LbParseLib.c | 252 +++++++++++++++++---<br>
 2 files changed, 230 insertions(+), 39 deletions(-)<br>
<br>
diff --git a/UefiPayloadPkg/Include/Linuxboot.h b/UefiPayloadPkg/Include/Linuxboot.h<br>
index 34ca18069983..56b39b5a09ff 100644<br>
--- a/UefiPayloadPkg/Include/Linuxboot.h<br>
+++ b/UefiPayloadPkg/Include/Linuxboot.h<br>
@@ -24,8 +24,7 @@ typedef struct MemoryMapEntryStruct {<br>
   UINT32 Type;<br>
 } MemoryMapEntry;<br>
<br>
-typedef struct UefiPayloadConfigStruct {<br>
-  UINT64 Version;<br>
+typedef struct {<br>
   UINT64 AcpiBase;<br>
   UINT64 AcpiSize;<br>
   UINT64 SmbiosBase;<br>
@@ -33,10 +32,22 @@ typedef struct UefiPayloadConfigStruct {<br>
   SerialPortConfig SerialConfig;<br>
   UINT32 NumMemoryMapEntries;<br>
   MemoryMapEntry MemoryMapEntries[0];<br>
+} UefiPayloadConfigV1;<br>
+<br>
+typedef struct UefiPayloadConfigStruct {<br>
+  UINT64 Version;<br>
+  union {<br>
+    UefiPayloadConfigV1 v1;<br>
+    struct {<br>
+      char cmdline[0]; // up to 64 KB<br>
+    } v2;<br>
+  } config;<br>
 } UefiPayloadConfig;<br>
 #pragma pack()<br>
<br>
-#define UEFI_PAYLOAD_CONFIG_VERSION 1<br>
+// magic version config is "LnxBoot1"<br>
+#define UEFI_PAYLOAD_CONFIG_VERSION1 1<br>
+#define UEFI_PAYLOAD_CONFIG_VERSION2 0x31746f6f42786e4cULL<br>
<br>
 #define LINUXBOOT_MEM_RAM 1<br>
 #define LINUXBOOT_MEM_DEFAULT 2<br>
diff --git a/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c b/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c<br>
index 34bfb6a1073f..5e68091cac91 100644<br>
--- a/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c<br>
+++ b/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c<br>
@@ -1,13 +1,12 @@<br>
 /** @file<br>
-  This library will parse the linuxboot table in memory and extract those required<br>
-  information.<br>
+  This library will parse the linuxboot table in memory and extract <br>
+those required information.<br>
<br>
   Copyright (c) 2021, the u-root Authors. All rights reserved.<BR><br>
   SPDX-License-Identifier: BSD-2-Clause-Patent<br>
<br>
 **/<br>
<br>
-<br>
 #include <IndustryStandard/Acpi.h><br>
 #include <IndustryStandard/SmBios.h><br>
 #include <Library/BaseLib.h><br>
@@ -18,17 +17,42 @@<br>
 #include <Library/PcdLib.h><br>
 #include <Linuxboot.h><br>
 #include <Uefi/UefiBaseType.h><br>
+#include <stdint.h><br>
+#include <stdlib.h><br>
+//#include <string.h><br>
+//#include <ctype.h><br>
+<br>
+#define strncmp(a, b, n) AsciiStrnCmp((a), (b), (n))<br>
+<br>
+static uint64_t parse_int(const char* s, char** end) {<br>
+  UINT64 x;<br>
+<br>
+  if (s[0] == '0' && s[1] == 'x')<br>
+    AsciiStrHexToUint64S(s, end, &x);<br>
+  else<br>
+    AsciiStrDecimalToUint64S(s, end, &x);<br>
+<br>
+  return x;<br>
+}<br>
+<br>
+static int isspace(const char c) { return c == ' ' || c == '\t' || c == <br>
+'\n'; }<br>
<br>
 // Retrieve UefiPayloadConfig from Linuxboot's uefiboot<br>
-UefiPayloadConfig* GetUefiPayLoadConfig() {<br>
-  UefiPayloadConfig* config =<br>
+const UefiPayloadConfig* GetUefiPayLoadConfig() {<br>
+  const UefiPayloadConfig* config =<br>
       (UefiPayloadConfig*)(UINTN)(PcdGet32(PcdPayloadFdMemBase) - SIZE_64KB);<br>
-  if (config->Version != UEFI_PAYLOAD_CONFIG_VERSION) {<br>
-    DEBUG((DEBUG_ERROR, "Expect payload config version: %d, but get %d\n",<br>
-           UEFI_PAYLOAD_CONFIG_VERSION, config->Version));<br>
-    CpuDeadLoop ();<br>
-  }<br>
-  return config;<br>
+<br>
+  if (config->Version == UEFI_PAYLOAD_CONFIG_VERSION1 ||<br>
+      config->Version == UEFI_PAYLOAD_CONFIG_VERSION2)<br>
+    return config;<br>
+<br>
+  DEBUG((DEBUG_ERROR,<br>
+         "Expect payload config version %016lx or %016lx, but get %016lx\n",<br>
+         UEFI_PAYLOAD_CONFIG_VERSION1, UEFI_PAYLOAD_CONFIG_VERSION2,<br>
+         config->Version));<br>
+  CpuDeadLoop();<br>
+  while (1)<br>
+    ;<br>
 }<br>
<br>
 // Align the address and add memory rang to MemInfoCallback @@ -54,6 +78,57 @@ void AddMemoryRange(IN BL_MEM_INFO_CALLBACK MemInfoCallback, IN UINTN start,<br>
   MemInfoCallback(&MemoryMap, NULL);<br>
 }<br>
<br>
+const char* cmdline_next(const char* cmdline, const char** option) {<br>
+  // at the end of the string, we're done<br>
+  if (!cmdline || *cmdline == '\0') return NULL;<br>
+<br>
+  // skip any leading whitespace<br>
+  while (isspace(*cmdline)) cmdline++;<br>
+<br>
+  // if we've hit the end of the string, we're done  if (*cmdline == <br>
+ '\0') return NULL;<br>
+<br>
+  *option = cmdline;<br>
+<br>
+  // find the end of this option or the string  while <br>
+ (!isspace(*cmdline) && *cmdline != '\0') cmdline++;<br>
+<br>
+  // cmdline points to the whitespace or end of string<br>
+  return cmdline;<br>
+}<br>
+<br>
+int cmdline_ints(const char* option, uint64_t args[], int max) {<br>
+  // skip any leading text up to an '='<br>
+  const char* s = option;<br>
+  while (1) {<br>
+    const char c = *s++;<br>
+    if (c == '=') break;<br>
+<br>
+    if (c == '\0' || isspace(c)) {<br>
+      s = option;<br>
+      break;<br>
+    }<br>
+  }<br>
+<br>
+  for (int i = 0; i < max; i++) {<br>
+    char* end;<br>
+    args[i] = parse_int(s, &end);<br>
+<br>
+    // end of string or end of the option?<br>
+    if (*end == '\0' || isspace(*end)) return i + 1;<br>
+<br>
+    // not separator? signal an error if we have consumed any ints,<br>
+    // otherwise return 0 saying that none were found<br>
+    if (*end != ',') return i == 0 ? 0 : -1;<br>
+<br>
+    // skip the , and get the next value<br>
+    s = end + 1;<br>
+  }<br>
+<br>
+  // too many values!<br>
+  return -1;<br>
+}<br>
+<br>
 /**<br>
   Acquire the memory information from the linuxboot table in memory.<br>
<br>
@@ -67,20 +142,50 @@ void AddMemoryRange(IN BL_MEM_INFO_CALLBACK MemInfoCallback, IN UINTN start,  RETURN_STATUS  EFIAPI  ParseMemoryInfo(IN BL_MEM_INFO_CALLBACK MemInfoCallback, IN VOID* Params) {<br>
-  UefiPayloadConfig* config;<br>
-  int i;<br>
+  const UefiPayloadConfig* config = GetUefiPayLoadConfig();  if <br>
+ (!config) {<br>
+    DEBUG(<br>
+        (DEBUG_ERROR, "ParseMemoryInfo: Could not find UEFI Payload config\n"));<br>
+    return RETURN_SUCCESS;<br>
+  }<br>
+<br>
+  if (config->Version == UEFI_PAYLOAD_CONFIG_VERSION1) {<br>
+    const UefiPayloadConfigV1* config1 = &config->config.v1;<br>
+    DEBUG(<br>
+        (DEBUG_INFO, "MemoryMap #entries: %d\n", <br>
+ config1->NumMemoryMapEntries));<br>
+<br>
+    for (int i = 0; i < config1->NumMemoryMapEntries; i++) {<br>
+      const MemoryMapEntry* entry = &config1->MemoryMapEntries[i];<br>
+      DEBUG((DEBUG_INFO, "Start: 0x%lx End: 0x%lx Type:%d\n", entry->Start,<br>
+             entry->End, entry->Type));<br>
+      AddMemoryRange(MemInfoCallback, entry->Start, entry->End, entry->Type);<br>
+    }<br>
+  } else<br>
<br>
-  config = GetUefiPayLoadConfig();<br>
+      if (config->Version == UEFI_PAYLOAD_CONFIG_VERSION2) {<br>
+    const char* cmdline = config->config.v2.cmdline;<br>
+    const char* option;<br>
+    uint64_t args[3];<br>
<br>
-  DEBUG((DEBUG_INFO, "MemoryMap #entries: %d\n", config->NumMemoryMapEntries));<br>
+    // look for the mem=start,end,type<br>
+    while ((cmdline = cmdline_next(cmdline, &option))) {<br>
+      if (strncmp(option, "mem=", 4) != 0) continue;<br>
<br>
-  MemoryMapEntry* entry = &config->MemoryMapEntries[0];<br>
-  for (i = 0; i < config->NumMemoryMapEntries; i++) {<br>
-    DEBUG((DEBUG_INFO, "Start: 0x%lx End: 0x%lx Type:%d\n", entry->Start,<br>
-           entry->End, entry->Type));<br>
-    AddMemoryRange(MemInfoCallback, entry->Start, entry->End, entry->Type);<br>
-    entry++;<br>
+      if (cmdline_ints(option, args, 3) != 3) {<br>
+        DEBUG((DEBUG_ERROR, "Parse error: '%a'\n", option));<br>
+        continue;<br>
+      }<br>
+<br>
+      const uint64_t start = args[0];<br>
+      const uint64_t end = args[1];<br>
+      const uint64_t type = args[2];<br>
+<br>
+      DEBUG(<br>
+          (DEBUG_INFO, "Start: 0x%lx End: 0x%lx Type:%d\n", start, end, type));<br>
+      AddMemoryRange(MemInfoCallback, start, end, type);<br>
+    }<br>
   }<br>
+<br>
   return RETURN_SUCCESS;<br>
 }<br>
<br>
@@ -96,14 +201,52 @@ ParseMemoryInfo(IN BL_MEM_INFO_CALLBACK MemInfoCallback, IN VOID* Params) {  RETURN_STATUS  EFIAPI  ParseSystemTable(OUT SYSTEM_TABLE_INFO* SystemTableInfo) {<br>
-  UefiPayloadConfig* config;<br>
+  const UefiPayloadConfig* config = GetUefiPayLoadConfig();  if <br>
+ (!config) {<br>
+    DEBUG((DEBUG_ERROR,<br>
+           "ParseSystemTable: Could not find UEFI Payload config\n"));<br>
+    return RETURN_SUCCESS;<br>
+  }<br>
<br>
-  config = GetUefiPayLoadConfig();<br>
-  SystemTableInfo->AcpiTableBase = config->AcpiBase;<br>
-  SystemTableInfo->AcpiTableSize = config->AcpiSize;<br>
+  if (config->Version == UEFI_PAYLOAD_CONFIG_VERSION1) {<br>
+    const UefiPayloadConfigV1* config1 = &config->config.v1;<br>
+    SystemTableInfo->AcpiTableBase = config1->AcpiBase;<br>
+    SystemTableInfo->AcpiTableSize = config1->AcpiSize;<br>
<br>
-  SystemTableInfo->SmbiosTableBase = config->SmbiosBase;<br>
-  SystemTableInfo->SmbiosTableSize = config->SmbiosSize;<br>
+    SystemTableInfo->SmbiosTableBase = config1->SmbiosBase;<br>
+    SystemTableInfo->SmbiosTableSize = config1->SmbiosSize;  } else<br>
+<br>
+      if (config->Version == UEFI_PAYLOAD_CONFIG_VERSION2) {<br>
+    const char* cmdline = config->config.v2.cmdline;<br>
+    const char* option;<br>
+    uint64_t args[2];<br>
+<br>
+    // look for the acpi config<br>
+    while ((cmdline = cmdline_next(cmdline, &option))) {<br>
+      if (strncmp(option, "ACPI20=", 7) == 0) {<br>
+        const int count = cmdline_ints(option, args, 2);<br>
+        if (count < 0) {<br>
+          DEBUG((DEBUG_ERROR, "Parse error: '%a'\n", option));<br>
+          continue;<br>
+        }<br>
+<br>
+        if (count > 0) SystemTableInfo->AcpiTableBase = args[0];<br>
+        if (count > 1) SystemTableInfo->AcpiTableSize = args[1];<br>
+      }<br>
+<br>
+      if (strncmp(option, "SMBIOS=", 7) == 0) {<br>
+        const int count = cmdline_ints(option, args, 2);<br>
+        if (count < 0) {<br>
+          DEBUG((DEBUG_ERROR, "Parse error: '%a'\n", option));<br>
+          continue;<br>
+        }<br>
+<br>
+        if (count > 0) SystemTableInfo->SmbiosTableBase = args[0];<br>
+        if (count > 1) SystemTableInfo->SmbiosTableSize = args[1];<br>
+      }<br>
+    }<br>
+  }<br>
<br>
   return RETURN_SUCCESS;<br>
 }<br>
@@ -120,15 +263,52 @@ ParseSystemTable(OUT SYSTEM_TABLE_INFO* SystemTableInfo) {  RETURN_STATUS  EFIAPI  ParseSerialInfo(OUT SERIAL_PORT_INFO* SerialPortInfo) {<br>
-  UefiPayloadConfig* config;<br>
-  config = GetUefiPayLoadConfig();<br>
-<br>
-  SerialPortInfo->BaseAddr = config->SerialConfig.BaseAddr;<br>
-  SerialPortInfo->RegWidth = config->SerialConfig.RegWidth;<br>
-  SerialPortInfo->Type = config->SerialConfig.Type;<br>
-  SerialPortInfo->Baud = config->SerialConfig.Baud;<br>
-  SerialPortInfo->InputHertz = config->SerialConfig.InputHertz;<br>
-  SerialPortInfo->UartPciAddr = config->SerialConfig.UartPciAddr;<br>
+  // fill in some reasonable defaults<br>
+  SerialPortInfo->BaseAddr = 0x3f8;<br>
+  SerialPortInfo->RegWidth = 1;<br>
+  SerialPortInfo->Type = 1;  // uefi.SerialPortTypeIO  <br>
+ SerialPortInfo->Baud = 115200;  SerialPortInfo->InputHertz = 1843200;  <br>
+ SerialPortInfo->UartPciAddr = 0;<br>
+<br>
+  const UefiPayloadConfig* config = GetUefiPayLoadConfig();  if <br>
+ (!config) {<br>
+    DEBUG((DEBUG_ERROR, "ParseSerialInfo: using default config\n"));<br>
+    return RETURN_SUCCESS;<br>
+  }<br>
+<br>
+  if (config->Version == UEFI_PAYLOAD_CONFIG_VERSION1) {<br>
+    const UefiPayloadConfigV1* config1 = &config->config.v1;<br>
+    SerialPortInfo->BaseAddr = config1->SerialConfig.BaseAddr;<br>
+    SerialPortInfo->RegWidth = config1->SerialConfig.RegWidth;<br>
+    SerialPortInfo->Type = config1->SerialConfig.Type;<br>
+    SerialPortInfo->Baud = config1->SerialConfig.Baud;<br>
+    SerialPortInfo->InputHertz = config1->SerialConfig.InputHertz;<br>
+    SerialPortInfo->UartPciAddr = config1->SerialConfig.UartPciAddr;<br>
+  } else<br>
+<br>
+      if (config->Version == UEFI_PAYLOAD_CONFIG_VERSION2) {<br>
+    const char* cmdline = config->config.v2.cmdline;<br>
+    const char* option;<br>
+    uint64_t args[6] = {};<br>
+<br>
+    while ((cmdline = cmdline_next(cmdline, &option))) {<br>
+      if (strncmp(option, "serial=", 7) != 0) continue;<br>
+<br>
+      const int count = cmdline_ints(option, args, 6);<br>
+      if (count < 0) {<br>
+        DEBUG((DEBUG_ERROR, "Parse error: %a\n", option));<br>
+        continue;<br>
+      }<br>
+<br>
+      if (count > 0) SerialPortInfo->Baud = args[0];<br>
+      if (count > 1) SerialPortInfo->BaseAddr = args[1];<br>
+      if (count > 2) SerialPortInfo->RegWidth = args[2];<br>
+      if (count > 3) SerialPortInfo->Type = args[3];<br>
+      if (count > 4) SerialPortInfo->InputHertz = args[4];<br>
+      if (count > 5) SerialPortInfo->UartPciAddr = args[5];<br>
+    }<br>
+  }<br>
<br>
   return RETURN_SUCCESS;<br>
 }<br>
--<br>
2.32.0.402.g57bb445576-goog<br>
<br>
<br>
<br>
<br>
<br>
<br>
</blockquote></div>


 <div width="1" style="color:white;clear:both">_._,_._,_</div> <hr>   Groups.io Links:<p>   You receive all messages sent to this group.    <p> <a target="_blank" href="https://edk2.groups.io/g/devel/message/78846">View/Reply Online (#78846)</a> |    |  <a target="_blank" href="https://groups.io/mt/84357538/1813853">Mute This Topic</a>  | <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br>    <a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> | <a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> |  <a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a>  [edk2-devel-archive@redhat.com]<br> <div width="1" style="color:white;clear:both">_._,_._,_</div>