From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) by mx.groups.io with SMTP id smtpd.web08.7988.1626961752632531656 for ; Thu, 22 Jul 2021 06:49:13 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@google.com header.s=20161025 header.b=GgS/Wf0p; spf=pass (domain: google.com, ip: 209.85.208.179, mailfrom: chengchieh@google.com) Received: by mail-lj1-f179.google.com with SMTP id t20so7450851ljd.2 for ; Thu, 22 Jul 2021 06:49:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=Ptk8jAnPLocYdI0R7vrEdARhut3u0yVHyASpme7yzQw=; b=GgS/Wf0po+1p32XyEQwlhCR9ppvWU7i1/u98aCZIQLFLcFTEJFsJtMLX2cF+Oosilx 3aFShvy+KwWzlyMfAqN486/Cxumy2NFkvcg9WGmvweq1U6GjNoFsXFW63GV04DtcNn8x NzVjgb+fliLA1nDI8iwVDTMdONlISzve5al96iVLATwYS/N/KwiO+VD8sfsp0Iqpg9V9 xURVEk5V7KnhmbuNnqXB4rvp/0yPMOmNcYpcIxbO4GoDu+7xi4pAasO5Ari4VQZUxpHx V+6BG8Csg97Vk8/tTfc/7c1l+aVDLKLKwkRi+uPXVt9gE5B12bqTm5XDk3Jkoq6jkkx2 rUSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=Ptk8jAnPLocYdI0R7vrEdARhut3u0yVHyASpme7yzQw=; b=ozaUbUFJEQPgbp4HiCWURf7KKGzc9fHBIbaMCjYt8t0YPUa+sVBAH2jNYZD/jcCd4a bMwXLtF+idEv6b1dBlm9aijbSEK/ZpPJu7hSvrVYkJ+cEBaOMjzp97AZtEjf4QfgxkGl dI+Uk6JC+64qI77UUbvy8JBz6gxGD9J2yc6QbtpJSdtQdtE/qwKxPpRAW2HomFMi5lOc zGFTg7tkZQf8g6q4N43SkLiq1fZt61siAJpkglkgmQ7i98ouI+iSPoT44wtdOuscOF5h BWdaQbEidlXtJMzBYo/Sfhek3XSAO9dNpulpPDuJACbnyuVIFZr9R82/w8tQq6gz68FJ GM1g== X-Gm-Message-State: AOAM533aeuhJsdmRDN7BuhCqdk/saPr8ALpAjA79RoW8y3c+gOrHGf8w mjKOTTNpGW1ZZHIZnE8Ob2YF3xO4TCaytuoaijqMpw== X-Google-Smtp-Source: ABdhPJxRY/h6DzXiEZ4x6e2N+bwzEY8pazDCjskEvOrDUyxo/1nKgvEVyS9n41+uXk3xbrS1nHgyWelvplRE2R9nf/A= X-Received: by 2002:a2e:b556:: with SMTP id a22mr73039ljn.142.1626961750603; Thu, 22 Jul 2021 06:49:10 -0700 (PDT) MIME-Version: 1.0 References: <20210721132328.1415485-1-chengchieh@google.com> <20210721132328.1415485-7-chengchieh@google.com> <6c7c62de-3af2-652f-a252-7e96193b4c58@posteo.de> In-Reply-To: <6c7c62de-3af2-652f-a252-7e96193b4c58@posteo.de> From: Cheng-Chieh Huang Date: Thu, 22 Jul 2021 21:48:58 +0800 Message-ID: Subject: Re: [edk2-devel] [PATCH v1 6/6] UefiPayloadPkg: LinuxBoot: use a text format for the configuration block. To: =?UTF-8?Q?Marvin_H=C3=A4user?= Cc: devel@edk2.groups.io, Trammell Hudson Content-Type: multipart/alternative; boundary="00000000000035d5bc05c7b68d20" --00000000000035d5bc05c7b68d20 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Here is the documentation: https://github.com/osresearch/kexec-load/blob/main/README.md On Thu, Jul 22, 2021 at 1:09 AM Marvin H=C3=A4user wro= te: > > > On 21.07.21 15:23, Cheng-Chieh Huang via groups.io wrote: > > From: Trammell Hudson > > > > This adds a text command line for the UefiPayloadPkg that uses > > a textual magic number 'LnxBoot1' and a series of white-space > > separated key=3Dvalue[,value...] pairs for the parameters. > > > > The v1 binary configuration structure is used if it is present instead > > for backwards compatability. > > > > Currently supported text command line arguments are are: > > > > * `serial=3Dbaud,base,width,type,hz,pci` > > (only `baud` needs to be specified, the rest have reasonable > > defaults) > > > > * `mem=3Dstart,end,type` > > Types are based on `/sys/firmware/memmaps/*/types`: > > 1 =3D=3D "System RAM" > > 3 =3D=3D "ACPI Tables" > > 4 =3D=3D "ACPI Non-volatile Storage" > > 5 =3D=3D "Reserved" > > > > * `ACPI20=3Dbase` pointer to RDSP (from `/sys/firmware/efi/systab`) > > > > * `SMBIOS=3Dbase` pointer to the SMBIOS table (also from the EFI table) > > > > Signed-off-by: Cheng-Chieh Huang > > --- > > UefiPayloadPkg/Include/Linuxboot.h | 17 +- > > UefiPayloadPkg/Library/LbParseLib/LbParseLib.c | 252 > +++++++++++++++++--- > > 2 files changed, 230 insertions(+), 39 deletions(-) > > > > diff --git a/UefiPayloadPkg/Include/Linuxboot.h > b/UefiPayloadPkg/Include/Linuxboot.h > > index 34ca18069983..56b39b5a09ff 100644 > > --- a/UefiPayloadPkg/Include/Linuxboot.h > > +++ b/UefiPayloadPkg/Include/Linuxboot.h > > @@ -24,8 +24,7 @@ typedef struct MemoryMapEntryStruct { > > UINT32 Type; > > } MemoryMapEntry; > > > > -typedef struct UefiPayloadConfigStruct { > > - UINT64 Version; > > +typedef struct { > > UINT64 AcpiBase; > > UINT64 AcpiSize; > > UINT64 SmbiosBase; > > @@ -33,10 +32,22 @@ typedef struct UefiPayloadConfigStruct { > > SerialPortConfig SerialConfig; > > UINT32 NumMemoryMapEntries; > > MemoryMapEntry MemoryMapEntries[0]; > > +} UefiPayloadConfigV1; > > + > > +typedef struct UefiPayloadConfigStruct { > > + UINT64 Version; > > + union { > > + UefiPayloadConfigV1 v1; > > + struct { > > + char cmdline[0]; // up to 64 KB > > + } v2; > > + } config; > > } UefiPayloadConfig; > > #pragma pack() > > > > -#define UEFI_PAYLOAD_CONFIG_VERSION 1 > > +// magic version config is "LnxBoot1" > > +#define UEFI_PAYLOAD_CONFIG_VERSION1 1 > > +#define UEFI_PAYLOAD_CONFIG_VERSION2 0x31746f6f42786e4cULL > > > > #define LINUXBOOT_MEM_RAM 1 > > #define LINUXBOOT_MEM_DEFAULT 2 > > diff --git a/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c > b/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c > > index 34bfb6a1073f..5e68091cac91 100644 > > --- a/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c > > +++ b/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c > > @@ -1,13 +1,12 @@ > > /** @file > > - This library will parse the linuxboot table in memory and extract > those required > > - information. > > + This library will parse the linuxboot table in memory and extract > those > > +required information. > > > > Copyright (c) 2021, the u-root Authors. All rights reserved.
> > SPDX-License-Identifier: BSD-2-Clause-Patent > > > > **/ > > > > - > > #include > > #include > > #include > > @@ -18,17 +17,42 @@ > > #include > > #include > > #include > > +#include > > +#include > > +//#include > > +//#include > > + > > +#define strncmp(a, b, n) AsciiStrnCmp((a), (b), (n)) > > + > > +static uint64_t parse_int(const char* s, char** end) { > > + UINT64 x; > > + > > + if (s[0] =3D=3D '0' && s[1] =3D=3D 'x') > > + AsciiStrHexToUint64S(s, end, &x); > > + else > > + AsciiStrDecimalToUint64S(s, end, &x); > > + > > + return x; > > +} > > + > > +static int isspace(const char c) { return c =3D=3D ' ' || c =3D=3D '\t= ' || c =3D=3D > '\n'; } > > > > // Retrieve UefiPayloadConfig from Linuxboot's uefiboot > > -UefiPayloadConfig* GetUefiPayLoadConfig() { > > - UefiPayloadConfig* config =3D > > +const UefiPayloadConfig* GetUefiPayLoadConfig() { > > + const UefiPayloadConfig* config =3D > > (UefiPayloadConfig*)(UINTN)(PcdGet32(PcdPayloadFdMemBase) - > SIZE_64KB); > > - if (config->Version !=3D UEFI_PAYLOAD_CONFIG_VERSION) { > > - DEBUG((DEBUG_ERROR, "Expect payload config version: %d, but get > %d\n", > > - UEFI_PAYLOAD_CONFIG_VERSION, config->Version)); > > - CpuDeadLoop (); > > - } > > - return config; > > + > > + if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1 || > > + config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION2) > > + return config; > > + > > + DEBUG((DEBUG_ERROR, > > + "Expect payload config version %016lx or %016lx, but get > %016lx\n", > > + UEFI_PAYLOAD_CONFIG_VERSION1, UEFI_PAYLOAD_CONFIG_VERSION2, > > + config->Version)); > > + CpuDeadLoop(); > > + while (1) > > + ; > > } > > > > // Align the address and add memory rang to MemInfoCallback > > @@ -54,6 +78,57 @@ void AddMemoryRange(IN BL_MEM_INFO_CALLBACK > MemInfoCallback, IN UINTN start, > > MemInfoCallback(&MemoryMap, NULL); > > } > > > > +const char* cmdline_next(const char* cmdline, const char** option) { > > + // at the end of the string, we're done > > + if (!cmdline || *cmdline =3D=3D '\0') return NULL; > > + > > + // skip any leading whitespace > > + while (isspace(*cmdline)) cmdline++; > > + > > + // if we've hit the end of the string, we're done > > + if (*cmdline =3D=3D '\0') return NULL; > > + > > + *option =3D cmdline; > > + > > + // find the end of this option or the string > > + while (!isspace(*cmdline) && *cmdline !=3D '\0') cmdline++; > > + > > + // cmdline points to the whitespace or end of string > > + return cmdline; > > +} > > + > > +int cmdline_ints(const char* option, uint64_t args[], int max) { > > + // skip any leading text up to an '=3D' > > + const char* s =3D option; > > + while (1) { > > + const char c =3D *s++; > > + if (c =3D=3D '=3D') break; > > + > > + if (c =3D=3D '\0' || isspace(c)) { > > + s =3D option; > > + break; > > + } > > + } > > + > > + for (int i =3D 0; i < max; i++) { > > + char* end; > > + args[i] =3D parse_int(s, &end); > > + > > + // end of string or end of the option? > > + if (*end =3D=3D '\0' || isspace(*end)) return i + 1; > > + > > + // not separator? signal an error if we have consumed any ints, > > + // otherwise return 0 saying that none were found > > + if (*end !=3D ',') return i =3D=3D 0 ? 0 : -1; > > + > > + // skip the , and get the next value > > + s =3D end + 1; > > + } > > + > > + // too many values! > > + return -1; > > +} > > + > > /** > > Acquire the memory information from the linuxboot table in memory. > > > > @@ -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) { > > - UefiPayloadConfig* config; > > - int i; > > + const UefiPayloadConfig* config =3D GetUefiPayLoadConfig(); > > + if (!config) { > > + DEBUG( > > + (DEBUG_ERROR, "ParseMemoryInfo: Could not find UEFI Payload > config\n")); > > + return RETURN_SUCCESS; > > + } > > + > > + if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1) { > > + const UefiPayloadConfigV1* config1 =3D &config->config.v1; > > + DEBUG( > > + (DEBUG_INFO, "MemoryMap #entries: %d\n", > config1->NumMemoryMapEntries)); > > + > > + for (int i =3D 0; i < config1->NumMemoryMapEntries; i++) { > > + const MemoryMapEntry* entry =3D &config1->MemoryMapEntries[i]; > > + DEBUG((DEBUG_INFO, "Start: 0x%lx End: 0x%lx Type:%d\n", > entry->Start, > > + entry->End, entry->Type)); > > + AddMemoryRange(MemInfoCallback, entry->Start, entry->End, > entry->Type); > > + } > > + } else > > > > - config =3D GetUefiPayLoadConfig(); > > + if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION2) { > > + const char* cmdline =3D config->config.v2.cmdline; > > + const char* option; > > + uint64_t args[3]; > > > > - DEBUG((DEBUG_INFO, "MemoryMap #entries: %d\n", > config->NumMemoryMapEntries)); > > + // look for the mem=3Dstart,end,type > > + while ((cmdline =3D cmdline_next(cmdline, &option))) { > > + if (strncmp(option, "mem=3D", 4) !=3D 0) continue; > > > > - MemoryMapEntry* entry =3D &config->MemoryMapEntries[0]; > > - for (i =3D 0; i < config->NumMemoryMapEntries; i++) { > > - DEBUG((DEBUG_INFO, "Start: 0x%lx End: 0x%lx Type:%d\n", > entry->Start, > > - entry->End, entry->Type)); > > - AddMemoryRange(MemInfoCallback, entry->Start, entry->End, > entry->Type); > > - entry++; > > + if (cmdline_ints(option, args, 3) !=3D 3) { > > + DEBUG((DEBUG_ERROR, "Parse error: '%a'\n", option)); > > + continue; > > + } > > + > > + const uint64_t start =3D args[0]; > > + const uint64_t end =3D args[1]; > > + const uint64_t type =3D args[2]; > > + > > + DEBUG( > > + (DEBUG_INFO, "Start: 0x%lx End: 0x%lx Type:%d\n", start, end= , > type)); > > + AddMemoryRange(MemInfoCallback, start, end, type); > > + } > > } > > + > > return RETURN_SUCCESS; > > } > > > > @@ -96,14 +201,52 @@ ParseMemoryInfo(IN BL_MEM_INFO_CALLBACK > MemInfoCallback, IN VOID* Params) { > > RETURN_STATUS > > EFIAPI > > ParseSystemTable(OUT SYSTEM_TABLE_INFO* SystemTableInfo) { > > - UefiPayloadConfig* config; > > + const UefiPayloadConfig* config =3D GetUefiPayLoadConfig(); > > + if (!config) { > > + DEBUG((DEBUG_ERROR, > > + "ParseSystemTable: Could not find UEFI Payload config\n")); > > + return RETURN_SUCCESS; > > + } > > > > - config =3D GetUefiPayLoadConfig(); > > - SystemTableInfo->AcpiTableBase =3D config->AcpiBase; > > - SystemTableInfo->AcpiTableSize =3D config->AcpiSize; > > + if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1) { > > + const UefiPayloadConfigV1* config1 =3D &config->config.v1; > > + SystemTableInfo->AcpiTableBase =3D config1->AcpiBase; > > + SystemTableInfo->AcpiTableSize =3D config1->AcpiSize; > > > > - SystemTableInfo->SmbiosTableBase =3D config->SmbiosBase; > > - SystemTableInfo->SmbiosTableSize =3D config->SmbiosSize; > > + SystemTableInfo->SmbiosTableBase =3D config1->SmbiosBase; > > + SystemTableInfo->SmbiosTableSize =3D config1->SmbiosSize; > > + } else > > + > > + if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION2) { > > + const char* cmdline =3D config->config.v2.cmdline; > > + const char* option; > > + uint64_t args[2]; > > + > > + // look for the acpi config > > + while ((cmdline =3D cmdline_next(cmdline, &option))) { > > + if (strncmp(option, "ACPI20=3D", 7) =3D=3D 0) { > > + const int count =3D cmdline_ints(option, args, 2); > > + if (count < 0) { > > + DEBUG((DEBUG_ERROR, "Parse error: '%a'\n", option)); > > + continue; > > + } > > + > > + if (count > 0) SystemTableInfo->AcpiTableBase =3D args[0]; > > + if (count > 1) SystemTableInfo->AcpiTableSize =3D args[1]; > > + } > > + > > + if (strncmp(option, "SMBIOS=3D", 7) =3D=3D 0) { > > + const int count =3D cmdline_ints(option, args, 2); > > + if (count < 0) { > > + DEBUG((DEBUG_ERROR, "Parse error: '%a'\n", option)); > > + continue; > > + } > > + > > + if (count > 0) SystemTableInfo->SmbiosTableBase =3D args[0]; > > + if (count > 1) SystemTableInfo->SmbiosTableSize =3D args[1]; > > + } > > Sorry, from only a quick peak, can this not leave {Acpi,Smbios}TableBase > and {Acpi,Smbios}TableSize undefined entirely, while returning > RETURN_SUCCESS? > Even if not, it looks kind of odd a command-line argument can change the > base address without changing the size, is there a documentation of this > behaviour? > What is the structure supposed to carry if no such arguments are given > at all? > > Thanks for your time! > > Best regards, > Marvin > > > + } > > + } > > > > return RETURN_SUCCESS; > > } > > @@ -120,15 +263,52 @@ ParseSystemTable(OUT SYSTEM_TABLE_INFO* > SystemTableInfo) { > > RETURN_STATUS > > EFIAPI > > ParseSerialInfo(OUT SERIAL_PORT_INFO* SerialPortInfo) { > > - UefiPayloadConfig* config; > > - config =3D GetUefiPayLoadConfig(); > > - > > - SerialPortInfo->BaseAddr =3D config->SerialConfig.BaseAddr; > > - SerialPortInfo->RegWidth =3D config->SerialConfig.RegWidth; > > - SerialPortInfo->Type =3D config->SerialConfig.Type; > > - SerialPortInfo->Baud =3D config->SerialConfig.Baud; > > - SerialPortInfo->InputHertz =3D config->SerialConfig.InputHertz; > > - SerialPortInfo->UartPciAddr =3D config->SerialConfig.UartPciAddr; > > + // fill in some reasonable defaults > > + SerialPortInfo->BaseAddr =3D 0x3f8; > > + SerialPortInfo->RegWidth =3D 1; > > + SerialPortInfo->Type =3D 1; // uefi.SerialPortTypeIO > > + SerialPortInfo->Baud =3D 115200; > > + SerialPortInfo->InputHertz =3D 1843200; > > + SerialPortInfo->UartPciAddr =3D 0; > > + > > + const UefiPayloadConfig* config =3D GetUefiPayLoadConfig(); > > + if (!config) { > > + DEBUG((DEBUG_ERROR, "ParseSerialInfo: using default config\n")); > > + return RETURN_SUCCESS; > > + } > > + > > + if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1) { > > + const UefiPayloadConfigV1* config1 =3D &config->config.v1; > > + SerialPortInfo->BaseAddr =3D config1->SerialConfig.BaseAddr; > > + SerialPortInfo->RegWidth =3D config1->SerialConfig.RegWidth; > > + SerialPortInfo->Type =3D config1->SerialConfig.Type; > > + SerialPortInfo->Baud =3D config1->SerialConfig.Baud; > > + SerialPortInfo->InputHertz =3D config1->SerialConfig.InputHertz; > > + SerialPortInfo->UartPciAddr =3D config1->SerialConfig.UartPciAddr; > > + } else > > + > > + if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION2) { > > + const char* cmdline =3D config->config.v2.cmdline; > > + const char* option; > > + uint64_t args[6] =3D {}; > > + > > + while ((cmdline =3D cmdline_next(cmdline, &option))) { > > + if (strncmp(option, "serial=3D", 7) !=3D 0) continue; > > + > > + const int count =3D cmdline_ints(option, args, 6); > > + if (count < 0) { > > + DEBUG((DEBUG_ERROR, "Parse error: %a\n", option)); > > + continue; > > + } > > + > > + if (count > 0) SerialPortInfo->Baud =3D args[0]; > > + if (count > 1) SerialPortInfo->BaseAddr =3D args[1]; > > + if (count > 2) SerialPortInfo->RegWidth =3D args[2]; > > + if (count > 3) SerialPortInfo->Type =3D args[3]; > > + if (count > 4) SerialPortInfo->InputHertz =3D args[4]; > > + if (count > 5) SerialPortInfo->UartPciAddr =3D args[5]; > > + } > > + } > > > > return RETURN_SUCCESS; > > } > > --00000000000035d5bc05c7b68d20 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Thu, Jul 22, 2021 at 1:09 AM Marvin = H=C3=A4user <mhaeuser@posteo.de> wrote:

On 21.07.21 15:23, Cheng-Chieh Huang via
groups.io wrote:
> From: Trammell Hudson <hudson@trmm.net>
>
> This adds a text command line for the UefiPayloadPkg that uses
> a textual magic number 'LnxBoot1' and a series of white-space<= br> > separated key=3Dvalue[,value...] pairs for the parameters.
>
> The v1 binary configuration structure is used if it is present instead=
> for backwards compatability.
>
> Currently supported text command line arguments are are:
>
> * `serial=3Dbaud,base,width,type,hz,pci`
> (only `baud` needs to be specified, the rest have reasonable
> defaults)
>
> * `mem=3Dstart,end,type`
> Types are based on `/sys/firmware/memmaps/*/types`:
>=C2=A0 =C2=A0 =C2=A0 1 =3D=3D "System RAM"
>=C2=A0 =C2=A0 =C2=A0 3 =3D=3D "ACPI Tables"
>=C2=A0 =C2=A0 =C2=A0 4 =3D=3D "ACPI Non-volatile Storage"
>=C2=A0 =C2=A0 =C2=A0 5 =3D=3D "Reserved"
>
> * `ACPI20=3Dbase` pointer to RDSP (from `/sys/firmware/efi/systab`) >
> * `SMBIOS=3Dbase` pointer to the SMBIOS table (also from the EFI table= )
>
> Signed-off-by: Cheng-Chieh Huang <chengchieh@google.com>
> ---
>=C2=A0 =C2=A0UefiPayloadPkg/Include/Linuxboot.h=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 17 +-
>=C2=A0 =C2=A0UefiPayloadPkg/Library/LbParseLib/LbParseLib.c | 252 +++++= ++++++++++++---
>=C2=A0 =C2=A02 files changed, 230 insertions(+), 39 deletions(-)
>
> diff --git a/UefiPayloadPkg/Include/Linuxboot.h b/UefiPayloadPkg/Inclu= de/Linuxboot.h
> index 34ca18069983..56b39b5a09ff 100644
> --- a/UefiPayloadPkg/Include/Linuxboot.h
> +++ b/UefiPayloadPkg/Include/Linuxboot.h
> @@ -24,8 +24,7 @@ typedef struct MemoryMapEntryStruct {
>=C2=A0 =C2=A0 =C2=A0UINT32 Type;
>=C2=A0 =C2=A0} MemoryMapEntry;
>=C2=A0 =C2=A0
> -typedef struct UefiPayloadConfigStruct {
> -=C2=A0 UINT64 Version;
> +typedef struct {
>=C2=A0 =C2=A0 =C2=A0UINT64 AcpiBase;
>=C2=A0 =C2=A0 =C2=A0UINT64 AcpiSize;
>=C2=A0 =C2=A0 =C2=A0UINT64 SmbiosBase;
> @@ -33,10 +32,22 @@ typedef struct UefiPayloadConfigStruct {
>=C2=A0 =C2=A0 =C2=A0SerialPortConfig SerialConfig;
>=C2=A0 =C2=A0 =C2=A0UINT32 NumMemoryMapEntries;
>=C2=A0 =C2=A0 =C2=A0MemoryMapEntry MemoryMapEntries[0];
> +} UefiPayloadConfigV1;
> +
> +typedef struct UefiPayloadConfigStruct {
> +=C2=A0 UINT64 Version;
> +=C2=A0 union {
> +=C2=A0 =C2=A0 UefiPayloadConfigV1 v1;
> +=C2=A0 =C2=A0 struct {
> +=C2=A0 =C2=A0 =C2=A0 char cmdline[0]; // up to 64 KB
> +=C2=A0 =C2=A0 } v2;
> +=C2=A0 } config;
>=C2=A0 =C2=A0} UefiPayloadConfig;
>=C2=A0 =C2=A0#pragma pack()
>=C2=A0 =C2=A0
> -#define UEFI_PAYLOAD_CONFIG_VERSION 1
> +// magic version config is "LnxBoot1"
> +#define UEFI_PAYLOAD_CONFIG_VERSION1 1
> +#define UEFI_PAYLOAD_CONFIG_VERSION2 0x31746f6f42786e4cULL
>=C2=A0 =C2=A0
>=C2=A0 =C2=A0#define LINUXBOOT_MEM_RAM 1
>=C2=A0 =C2=A0#define LINUXBOOT_MEM_DEFAULT 2
> diff --git a/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c b/UefiPayl= oadPkg/Library/LbParseLib/LbParseLib.c
> index 34bfb6a1073f..5e68091cac91 100644
> --- a/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c
> +++ b/UefiPayloadPkg/Library/LbParseLib/LbParseLib.c
> @@ -1,13 +1,12 @@
>=C2=A0 =C2=A0/** @file
> -=C2=A0 This library will parse the linuxboot table in memory and extr= act those required
> -=C2=A0 information.
> +=C2=A0 This library will parse the linuxboot table in memory and extr= act those
> +required information.
>=C2=A0 =C2=A0
>=C2=A0 =C2=A0 =C2=A0Copyright (c) 2021, the u-root Authors. All rights = reserved.<BR>
>=C2=A0 =C2=A0 =C2=A0SPDX-License-Identifier: BSD-2-Clause-Patent
>=C2=A0 =C2=A0
>=C2=A0 =C2=A0**/
>=C2=A0 =C2=A0
> -
>=C2=A0 =C2=A0#include <IndustryStandard/Acpi.h>
>=C2=A0 =C2=A0#include <IndustryStandard/SmBios.h>
>=C2=A0 =C2=A0#include <Library/BaseLib.h>
> @@ -18,17 +17,42 @@
>=C2=A0 =C2=A0#include <Library/PcdLib.h>
>=C2=A0 =C2=A0#include <Linuxboot.h>
>=C2=A0 =C2=A0#include <Uefi/UefiBaseType.h>
> +#include <stdint.h>
> +#include <stdlib.h>
> +//#include <string.h>
> +//#include <ctype.h>
> +
> +#define strncmp(a, b, n) AsciiStrnCmp((a), (b), (n))
> +
> +static uint64_t parse_int(const char* s, char** end) {
> +=C2=A0 UINT64 x;
> +
> +=C2=A0 if (s[0] =3D=3D '0' && s[1] =3D=3D 'x'= )
> +=C2=A0 =C2=A0 AsciiStrHexToUint64S(s, end, &x);
> +=C2=A0 else
> +=C2=A0 =C2=A0 AsciiStrDecimalToUint64S(s, end, &x);
> +
> +=C2=A0 return x;
> +}
> +
> +static int isspace(const char c) { return c =3D=3D ' ' || c = =3D=3D '\t' || c =3D=3D '\n'; }
>=C2=A0 =C2=A0
>=C2=A0 =C2=A0// Retrieve UefiPayloadConfig from Linuxboot's uefiboo= t
> -UefiPayloadConfig* GetUefiPayLoadConfig() {
> -=C2=A0 UefiPayloadConfig* config =3D
> +const UefiPayloadConfig* GetUefiPayLoadConfig() {
> +=C2=A0 const UefiPayloadConfig* config =3D
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(UefiPayloadConfig*)(UINTN)(PcdGet32(= PcdPayloadFdMemBase) - SIZE_64KB);
> -=C2=A0 if (config->Version !=3D UEFI_PAYLOAD_CONFIG_VERSION) {
> -=C2=A0 =C2=A0 DEBUG((DEBUG_ERROR, "Expect payload config version= : %d, but get %d\n",
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UEFI_PAYLOAD_CONFIG_VERSION,= config->Version));
> -=C2=A0 =C2=A0 CpuDeadLoop ();
> -=C2=A0 }
> -=C2=A0 return config;
> +
> +=C2=A0 if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1 ||<= br> > +=C2=A0 =C2=A0 =C2=A0 config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VE= RSION2)
> +=C2=A0 =C2=A0 return config;
> +
> +=C2=A0 DEBUG((DEBUG_ERROR,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"Expect payload config version= %016lx or %016lx, but get %016lx\n",
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UEFI_PAYLOAD_CONFIG_VERSION1, UEFI_= PAYLOAD_CONFIG_VERSION2,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0config->Version));
> +=C2=A0 CpuDeadLoop();
> +=C2=A0 while (1)
> +=C2=A0 =C2=A0 ;
>=C2=A0 =C2=A0}
>=C2=A0 =C2=A0
>=C2=A0 =C2=A0// Align the address and add memory rang to MemInfoCallbac= k
> @@ -54,6 +78,57 @@ void AddMemoryRange(IN BL_MEM_INFO_CALLBACK MemInfo= Callback, IN UINTN start,
>=C2=A0 =C2=A0 =C2=A0MemInfoCallback(&MemoryMap, NULL);
>=C2=A0 =C2=A0}
>=C2=A0 =C2=A0
> +const char* cmdline_next(const char* cmdline, const char** option) {<= br> > +=C2=A0 // at the end of the string, we're done
> +=C2=A0 if (!cmdline || *cmdline =3D=3D '\0') return NULL;
> +
> +=C2=A0 // skip any leading whitespace
> +=C2=A0 while (isspace(*cmdline)) cmdline++;
> +
> +=C2=A0 // if we've hit the end of the string, we're done
> +=C2=A0 if (*cmdline =3D=3D '\0') return NULL;
> +
> +=C2=A0 *option =3D cmdline;
> +
> +=C2=A0 // find the end of this option or the string
> +=C2=A0 while (!isspace(*cmdline) && *cmdline !=3D '\0'= ;) cmdline++;
> +
> +=C2=A0 // cmdline points to the whitespace or end of string
> +=C2=A0 return cmdline;
> +}
> +
> +int cmdline_ints(const char* option, uint64_t args[], int max) {
> +=C2=A0 // skip any leading text up to an '=3D'
> +=C2=A0 const char* s =3D option;
> +=C2=A0 while (1) {
> +=C2=A0 =C2=A0 const char c =3D *s++;
> +=C2=A0 =C2=A0 if (c =3D=3D '=3D') break;
> +
> +=C2=A0 =C2=A0 if (c =3D=3D '\0' || isspace(c)) {
> +=C2=A0 =C2=A0 =C2=A0 s =3D option;
> +=C2=A0 =C2=A0 =C2=A0 break;
> +=C2=A0 =C2=A0 }
> +=C2=A0 }
> +
> +=C2=A0 for (int i =3D 0; i < max; i++) {
> +=C2=A0 =C2=A0 char* end;
> +=C2=A0 =C2=A0 args[i] =3D parse_int(s, &end);
> +
> +=C2=A0 =C2=A0 // end of string or end of the option?
> +=C2=A0 =C2=A0 if (*end =3D=3D '\0' || isspace(*end)) return i= + 1;
> +
> +=C2=A0 =C2=A0 // not separator? signal an error if we have consumed a= ny ints,
> +=C2=A0 =C2=A0 // otherwise return 0 saying that none were found
> +=C2=A0 =C2=A0 if (*end !=3D ',') return i =3D=3D 0 ? 0 : -1;<= br> > +
> +=C2=A0 =C2=A0 // skip the , and get the next value
> +=C2=A0 =C2=A0 s =3D end + 1;
> +=C2=A0 }
> +
> +=C2=A0 // too many values!
> +=C2=A0 return -1;
> +}
> +
>=C2=A0 =C2=A0/**
>=C2=A0 =C2=A0 =C2=A0Acquire the memory information from the linuxboot t= able in memory.
>=C2=A0 =C2=A0
> @@ -67,20 +142,50 @@ void AddMemoryRange(IN BL_MEM_INFO_CALLBACK MemIn= foCallback, IN UINTN start,
>=C2=A0 =C2=A0RETURN_STATUS
>=C2=A0 =C2=A0EFIAPI
>=C2=A0 =C2=A0ParseMemoryInfo(IN BL_MEM_INFO_CALLBACK MemInfoCallback, I= N VOID* Params) {
> -=C2=A0 UefiPayloadConfig* config;
> -=C2=A0 int i;
> +=C2=A0 const UefiPayloadConfig* config =3D GetUefiPayLoadConfig(); > +=C2=A0 if (!config) {
> +=C2=A0 =C2=A0 DEBUG(
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 (DEBUG_ERROR, "ParseMemoryInfo: Coul= d not find UEFI Payload config\n"));
> +=C2=A0 =C2=A0 return RETURN_SUCCESS;
> +=C2=A0 }
> +
> +=C2=A0 if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1) {<= br> > +=C2=A0 =C2=A0 const UefiPayloadConfigV1* config1 =3D &config->= config.v1;
> +=C2=A0 =C2=A0 DEBUG(
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 (DEBUG_INFO, "MemoryMap #entries: %d= \n", config1->NumMemoryMapEntries));
> +
> +=C2=A0 =C2=A0 for (int i =3D 0; i < config1->NumMemoryMapEntrie= s; i++) {
> +=C2=A0 =C2=A0 =C2=A0 const MemoryMapEntry* entry =3D &config1->= ;MemoryMapEntries[i];
> +=C2=A0 =C2=A0 =C2=A0 DEBUG((DEBUG_INFO, "Start: 0x%lx End: 0x%lx= Type:%d\n", entry->Start,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0entry->End, entry-= >Type));
> +=C2=A0 =C2=A0 =C2=A0 AddMemoryRange(MemInfoCallback, entry->Start,= entry->End, entry->Type);
> +=C2=A0 =C2=A0 }
> +=C2=A0 } else
>=C2=A0 =C2=A0
> -=C2=A0 config =3D GetUefiPayLoadConfig();
> +=C2=A0 =C2=A0 =C2=A0 if (config->Version =3D=3D UEFI_PAYLOAD_CONFI= G_VERSION2) {
> +=C2=A0 =C2=A0 const char* cmdline =3D config->config.v2.cmdline; > +=C2=A0 =C2=A0 const char* option;
> +=C2=A0 =C2=A0 uint64_t args[3];
>=C2=A0 =C2=A0
> -=C2=A0 DEBUG((DEBUG_INFO, "MemoryMap #entries: %d\n", confi= g->NumMemoryMapEntries));
> +=C2=A0 =C2=A0 // look for the mem=3Dstart,end,type
> +=C2=A0 =C2=A0 while ((cmdline =3D cmdline_next(cmdline, &option))= ) {
> +=C2=A0 =C2=A0 =C2=A0 if (strncmp(option, "mem=3D", 4) !=3D = 0) continue;
>=C2=A0 =C2=A0
> -=C2=A0 MemoryMapEntry* entry =3D &config->MemoryMapEntries[0];=
> -=C2=A0 for (i =3D 0; i < config->NumMemoryMapEntries; i++) { > -=C2=A0 =C2=A0 DEBUG((DEBUG_INFO, "Start: 0x%lx End: 0x%lx Type:%= d\n", entry->Start,
> -=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0entry->End, entry->Typ= e));
> -=C2=A0 =C2=A0 AddMemoryRange(MemInfoCallback, entry->Start, entry-= >End, entry->Type);
> -=C2=A0 =C2=A0 entry++;
> +=C2=A0 =C2=A0 =C2=A0 if (cmdline_ints(option, args, 3) !=3D 3) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG((DEBUG_ERROR, "Parse error: &#= 39;%a'\n", option));
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;
> +=C2=A0 =C2=A0 =C2=A0 }
> +
> +=C2=A0 =C2=A0 =C2=A0 const uint64_t start =3D args[0];
> +=C2=A0 =C2=A0 =C2=A0 const uint64_t end =3D args[1];
> +=C2=A0 =C2=A0 =C2=A0 const uint64_t type =3D args[2];
> +
> +=C2=A0 =C2=A0 =C2=A0 DEBUG(
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (DEBUG_INFO, "Start: 0x%lx En= d: 0x%lx Type:%d\n", start, end, type));
> +=C2=A0 =C2=A0 =C2=A0 AddMemoryRange(MemInfoCallback, start, end, type= );
> +=C2=A0 =C2=A0 }
>=C2=A0 =C2=A0 =C2=A0}
> +
>=C2=A0 =C2=A0 =C2=A0return RETURN_SUCCESS;
>=C2=A0 =C2=A0}
>=C2=A0 =C2=A0
> @@ -96,14 +201,52 @@ ParseMemoryInfo(IN BL_MEM_INFO_CALLBACK MemInfoCa= llback, IN VOID* Params) {
>=C2=A0 =C2=A0RETURN_STATUS
>=C2=A0 =C2=A0EFIAPI
>=C2=A0 =C2=A0ParseSystemTable(OUT SYSTEM_TABLE_INFO* SystemTableInfo) {=
> -=C2=A0 UefiPayloadConfig* config;
> +=C2=A0 const UefiPayloadConfig* config =3D GetUefiPayLoadConfig(); > +=C2=A0 if (!config) {
> +=C2=A0 =C2=A0 DEBUG((DEBUG_ERROR,
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"ParseSystemTable: Coul= d not find UEFI Payload config\n"));
> +=C2=A0 =C2=A0 return RETURN_SUCCESS;
> +=C2=A0 }
>=C2=A0 =C2=A0
> -=C2=A0 config =3D GetUefiPayLoadConfig();
> -=C2=A0 SystemTableInfo->AcpiTableBase =3D config->AcpiBase;
> -=C2=A0 SystemTableInfo->AcpiTableSize =3D config->AcpiSize;
> +=C2=A0 if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1) {<= br> > +=C2=A0 =C2=A0 const UefiPayloadConfigV1* config1 =3D &config->= config.v1;
> +=C2=A0 =C2=A0 SystemTableInfo->AcpiTableBase =3D config1->AcpiB= ase;
> +=C2=A0 =C2=A0 SystemTableInfo->AcpiTableSize =3D config1->AcpiS= ize;
>=C2=A0 =C2=A0
> -=C2=A0 SystemTableInfo->SmbiosTableBase =3D config->SmbiosBase;=
> -=C2=A0 SystemTableInfo->SmbiosTableSize =3D config->SmbiosSize;=
> +=C2=A0 =C2=A0 SystemTableInfo->SmbiosTableBase =3D config1->Smb= iosBase;
> +=C2=A0 =C2=A0 SystemTableInfo->SmbiosTableSize =3D config1->Smb= iosSize;
> +=C2=A0 } else
> +
> +=C2=A0 =C2=A0 =C2=A0 if (config->Version =3D=3D UEFI_PAYLOAD_CONFI= G_VERSION2) {
> +=C2=A0 =C2=A0 const char* cmdline =3D config->config.v2.cmdline; > +=C2=A0 =C2=A0 const char* option;
> +=C2=A0 =C2=A0 uint64_t args[2];
> +
> +=C2=A0 =C2=A0 // look for the acpi config
> +=C2=A0 =C2=A0 while ((cmdline =3D cmdline_next(cmdline, &option))= ) {
> +=C2=A0 =C2=A0 =C2=A0 if (strncmp(option, "ACPI20=3D", 7) = =3D=3D 0) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 const int count =3D cmdline_ints(option, = args, 2);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (count < 0) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG((DEBUG_ERROR, "Parse er= ror: '%a'\n", option));
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> +
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (count > 0) SystemTableInfo->Acp= iTableBase =3D args[0];
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (count > 1) SystemTableInfo->Acp= iTableSize =3D args[1];
> +=C2=A0 =C2=A0 =C2=A0 }
> +
> +=C2=A0 =C2=A0 =C2=A0 if (strncmp(option, "SMBIOS=3D", 7) = =3D=3D 0) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 const int count =3D cmdline_ints(option, = args, 2);
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (count < 0) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG((DEBUG_ERROR, "Parse er= ror: '%a'\n", option));
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> +
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (count > 0) SystemTableInfo->Smb= iosTableBase =3D args[0];
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (count > 1) SystemTableInfo->Smb= iosTableSize =3D args[1];
> +=C2=A0 =C2=A0 =C2=A0 }

Sorry, from only a quick peak, can this not leave {Acpi,Smbios}TableBase and {Acpi,Smbios}TableSize undefined entirely, while returning
RETURN_SUCCESS?
Even if not, it looks kind of odd a command-line argument can change the base address without changing the size, is there a documentation of this behaviour?
What is the structure supposed to carry if no such arguments are given
at all?

Thanks for your time!

Best regards,
Marvin

> +=C2=A0 =C2=A0 }
> +=C2=A0 }
>=C2=A0 =C2=A0
>=C2=A0 =C2=A0 =C2=A0return RETURN_SUCCESS;
>=C2=A0 =C2=A0}
> @@ -120,15 +263,52 @@ ParseSystemTable(OUT SYSTEM_TABLE_INFO* SystemTa= bleInfo) {
>=C2=A0 =C2=A0RETURN_STATUS
>=C2=A0 =C2=A0EFIAPI
>=C2=A0 =C2=A0ParseSerialInfo(OUT SERIAL_PORT_INFO* SerialPortInfo) { > -=C2=A0 UefiPayloadConfig* config;
> -=C2=A0 config =3D GetUefiPayLoadConfig();
> -
> -=C2=A0 SerialPortInfo->BaseAddr =3D config->SerialConfig.BaseAd= dr;
> -=C2=A0 SerialPortInfo->RegWidth =3D config->SerialConfig.RegWid= th;
> -=C2=A0 SerialPortInfo->Type =3D config->SerialConfig.Type;
> -=C2=A0 SerialPortInfo->Baud =3D config->SerialConfig.Baud;
> -=C2=A0 SerialPortInfo->InputHertz =3D config->SerialConfig.Inpu= tHertz;
> -=C2=A0 SerialPortInfo->UartPciAddr =3D config->SerialConfig.Uar= tPciAddr;
> +=C2=A0 // fill in some reasonable defaults
> +=C2=A0 SerialPortInfo->BaseAddr =3D 0x3f8;
> +=C2=A0 SerialPortInfo->RegWidth =3D 1;
> +=C2=A0 SerialPortInfo->Type =3D 1;=C2=A0 // uefi.SerialPortTypeIO<= br> > +=C2=A0 SerialPortInfo->Baud =3D 115200;
> +=C2=A0 SerialPortInfo->InputHertz =3D 1843200;
> +=C2=A0 SerialPortInfo->UartPciAddr =3D 0;
> +
> +=C2=A0 const UefiPayloadConfig* config =3D GetUefiPayLoadConfig(); > +=C2=A0 if (!config) {
> +=C2=A0 =C2=A0 DEBUG((DEBUG_ERROR, "ParseSerialInfo: using defaul= t config\n"));
> +=C2=A0 =C2=A0 return RETURN_SUCCESS;
> +=C2=A0 }
> +
> +=C2=A0 if (config->Version =3D=3D UEFI_PAYLOAD_CONFIG_VERSION1) {<= br> > +=C2=A0 =C2=A0 const UefiPayloadConfigV1* config1 =3D &config->= config.v1;
> +=C2=A0 =C2=A0 SerialPortInfo->BaseAddr =3D config1->SerialConfi= g.BaseAddr;
> +=C2=A0 =C2=A0 SerialPortInfo->RegWidth =3D config1->SerialConfi= g.RegWidth;
> +=C2=A0 =C2=A0 SerialPortInfo->Type =3D config1->SerialConfig.Ty= pe;
> +=C2=A0 =C2=A0 SerialPortInfo->Baud =3D config1->SerialConfig.Ba= ud;
> +=C2=A0 =C2=A0 SerialPortInfo->InputHertz =3D config1->SerialCon= fig.InputHertz;
> +=C2=A0 =C2=A0 SerialPortInfo->UartPciAddr =3D config1->SerialCo= nfig.UartPciAddr;
> +=C2=A0 } else
> +
> +=C2=A0 =C2=A0 =C2=A0 if (config->Version =3D=3D UEFI_PAYLOAD_CONFI= G_VERSION2) {
> +=C2=A0 =C2=A0 const char* cmdline =3D config->config.v2.cmdline; > +=C2=A0 =C2=A0 const char* option;
> +=C2=A0 =C2=A0 uint64_t args[6] =3D {};
> +
> +=C2=A0 =C2=A0 while ((cmdline =3D cmdline_next(cmdline, &option))= ) {
> +=C2=A0 =C2=A0 =C2=A0 if (strncmp(option, "serial=3D", 7) != =3D 0) continue;
> +
> +=C2=A0 =C2=A0 =C2=A0 const int count =3D cmdline_ints(option, args, 6= );
> +=C2=A0 =C2=A0 =C2=A0 if (count < 0) {
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG((DEBUG_ERROR, "Parse error: %a= \n", option));
> +=C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;
> +=C2=A0 =C2=A0 =C2=A0 }
> +
> +=C2=A0 =C2=A0 =C2=A0 if (count > 0) SerialPortInfo->Baud =3D ar= gs[0];
> +=C2=A0 =C2=A0 =C2=A0 if (count > 1) SerialPortInfo->BaseAddr = =3D args[1];
> +=C2=A0 =C2=A0 =C2=A0 if (count > 2) SerialPortInfo->RegWidth = =3D args[2];
> +=C2=A0 =C2=A0 =C2=A0 if (count > 3) SerialPortInfo->Type =3D ar= gs[3];
> +=C2=A0 =C2=A0 =C2=A0 if (count > 4) SerialPortInfo->InputHertz = =3D args[4];
> +=C2=A0 =C2=A0 =C2=A0 if (count > 5) SerialPortInfo->UartPciAddr= =3D args[5];
> +=C2=A0 =C2=A0 }
> +=C2=A0 }
>=C2=A0 =C2=A0
>=C2=A0 =C2=A0 =C2=A0return RETURN_SUCCESS;
>=C2=A0 =C2=A0}

--00000000000035d5bc05c7b68d20--