From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.120]) by mx.groups.io with SMTP id smtpd.web10.2302.1587719626936371809 for ; Fri, 24 Apr 2020 02:13:47 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=dyi5FTtx; spf=pass (domain: redhat.com, ip: 205.139.110.120, mailfrom: philmd@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1587719626; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=lMxbrsxLefX8e8oJGbn1CpNSkXYck6zEbuevHJy7feE=; b=dyi5FTtxTwNoAlRC9FE9tp7lsuwUG4qzJYJCetuA2LND3uBvgzmJtPYT1I+R4nTcCHD+Xb 8qolM85TJpt7w8xt1kXJnB+8bM920GSablXrth0Yf1NiTpFCGKHhoyr0Wiivb91sJIugI1 g23vBqTtOegSLsvB2XR3/Px51hq5rsA= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-200--iBax9UdPWapFKi0hphxXw-1; Fri, 24 Apr 2020 05:13:44 -0400 X-MC-Unique: -iBax9UdPWapFKi0hphxXw-1 Received: by mail-wr1-f71.google.com with SMTP id q10so4472312wrv.10 for ; Fri, 24 Apr 2020 02:13:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=srPzc4FW0VtfNfUXcJ7Bn8d9mVNqBCdXnsHbqWiPOy8=; b=q5wuQtHb9N22QIUQ+JPsoEoEQeode2nr+0gFCqkBNUItnkuZEIEhf0dPfmeSrHXhGP h7KTqWFTKPtbNg+4I26QLxtWYFYhtCTiqBHCCnrbgnRNyk3wDRcQ97yCeVcuqJCf6gOs +BE79GX4bYdR6yqYEXwwd+9SsMcXi+g7JWhEXCV7x0HKlOUmXdk3Y0jHC/Jpdjn/RRWt OnG778LBwGOa7W5L6v6ImePHEVHL158b+wfXZJPvB5EhZzlDOD+mY3q90NmSOJ/MSUsz czmxyx8mPq9J1TVmlJ7mKFRYnzRTh91RWqg1PUyV4b3yRLpjOM7bD9v3sQbgSmEqupBd t5Lg== X-Gm-Message-State: AGi0Puai157oo33QDaSst180Df/AbucShXryv/efUZgzQCBzYI/Sa0oX zb4boaxU5/eN++IGdkEKBX1rEdVNUodB4AeYeGaG1pFif32M2hKzF69csyW1sPrHTQolVGj4Spy l4o2AGYnNrqfwAw== X-Received: by 2002:adf:ab09:: with SMTP id q9mr9579909wrc.240.1587719623183; Fri, 24 Apr 2020 02:13:43 -0700 (PDT) X-Google-Smtp-Source: APiQypI4MZXSGbVpXbk43u0Vm9hcB8q2LmFU0rxLKGZcWoml/smTIwg97DSP2VOSFvuxTYRe0TwBcw== X-Received: by 2002:adf:ab09:: with SMTP id q9mr9579873wrc.240.1587719622856; Fri, 24 Apr 2020 02:13:42 -0700 (PDT) Return-Path: Received: from [192.168.1.39] (116.red-83-42-57.dynamicip.rima-tde.net. [83.42.57.116]) by smtp.gmail.com with ESMTPSA id h17sm1957065wmm.6.2020.04.24.02.13.41 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 24 Apr 2020 02:13:42 -0700 (PDT) Subject: Re: [PATCH 1/7] OvmfPkg: introduce QemuFwCfgSimpleParserLib To: Laszlo Ersek , edk2-devel-groups-io Cc: Ard Biesheuvel , Jordan Justen , Per Sundstrom References: <20200424075353.8489-1-lersek@redhat.com> <20200424075353.8489-2-lersek@redhat.com> From: =?UTF-8?B?UGhpbGlwcGUgTWF0aGlldS1EYXVkw6k=?= Message-ID: <3c85c28f-745a-a0eb-2fd6-7a3e73ec0694@redhat.com> Date: Fri, 24 Apr 2020 11:13:36 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 In-Reply-To: <20200424075353.8489-2-lersek@redhat.com> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable On 4/24/20 9:53 AM, Laszlo Ersek wrote: > We already parse some boolean and integer values from named fw_cfg files > (usually into PCDs), and we're going to cover more. Add a dedicated > library for centralizing the parsing logic. >=20 > Cc: Ard Biesheuvel > Cc: Jordan Justen > Cc: Per Sundstrom > Cc: Philippe Mathieu-Daud=C3=A9 > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2681 > Signed-off-by: Laszlo Ersek > --- > OvmfPkg/OvmfPkg.dec |= 4 + > OvmfPkg/OvmfPkgIa32.dsc |= 1 + > OvmfPkg/OvmfPkgIa32X64.dsc |= 1 + > OvmfPkg/OvmfPkgX64.dsc |= 1 + > OvmfPkg/Include/Library/QemuFwCfgSimpleParserLib.h |= 128 +++++++ > OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf |= 27 ++ > OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParser.c |= 398 ++++++++++++++++++++ > 7 files changed, 560 insertions(+) >=20 > diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec > index 28030391cff2..8a46fe73344e 100644 > --- a/OvmfPkg/OvmfPkg.dec > +++ b/OvmfPkg/OvmfPkg.dec > @@ -60,6 +60,10 @@ [LibraryClasses] > # > QemuFwCfgS3Lib|Include/Library/QemuFwCfgS3Lib.h > =20 > + ## @libraryclass Parse the contents of named fw_cfg files as simple > + # (scalar) data types. > + QemuFwCfgSimpleParserLib|Include/Library/QemuFwCfgSimpleParserLib.h > + > ## @libraryclass Rewrite the BootOrder NvVar based on QEMU's "booto= rder" > # fw_cfg file. > # > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc > index d5e90c001370..5e2972063110 100644 > --- a/OvmfPkg/OvmfPkgIa32.dsc > +++ b/OvmfPkg/OvmfPkgIa32.dsc > @@ -160,6 +160,7 @@ [LibraryClasses] > UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf > SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/Serialize= VariablesLib.inf > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf > + QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/Qemu= FwCfgSimpleParserLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptS= evLib.inf > diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc > index 066f49aeaee0..18e6909a33fa 100644 > --- a/OvmfPkg/OvmfPkgIa32X64.dsc > +++ b/OvmfPkg/OvmfPkgIa32X64.dsc > @@ -164,6 +164,7 @@ [LibraryClasses] > UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf > SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/Serialize= VariablesLib.inf > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf > + QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/Qemu= FwCfgSimpleParserLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptS= evLib.inf > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc > index ac510522a9ff..3d24cc4c1cfb 100644 > --- a/OvmfPkg/OvmfPkgX64.dsc > +++ b/OvmfPkg/OvmfPkgX64.dsc > @@ -164,6 +164,7 @@ [LibraryClasses] > UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf > SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/Serialize= VariablesLib.inf > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf > + QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/Qemu= FwCfgSimpleParserLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptS= evLib.inf > diff --git a/OvmfPkg/Include/Library/QemuFwCfgSimpleParserLib.h b/OvmfPkg= /Include/Library/QemuFwCfgSimpleParserLib.h > new file mode 100644 > index 000000000000..c6062bae8770 > --- /dev/null > +++ b/OvmfPkg/Include/Library/QemuFwCfgSimpleParserLib.h > @@ -0,0 +1,128 @@ > +/** @file > + Parse the contents of named fw_cfg files as simple (scalar) data types= . > + > + Copyright (C) 2020, Red Hat, Inc. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#ifndef QEMU_FW_CFG_SIMPLE_PARSER_LIB_H_ > +#define QEMU_FW_CFG_SIMPLE_PARSER_LIB_H_ > + > +#include > + > +/** > + Look up FileName with QemuFwCfgFindFile() from QemuFwCfgLib. Read the = fw_cfg > + file into a small array with automatic storage duration. Parse the arr= ay as > + the textual representation of a BOOLEAN. > + > + @param[in] FileName The name of the fw_cfg file to look up and parse. > + > + @param[out] Value On success, Value is TRUE if the contents of the = fw_cfg > + file case-insensitively match "true", "yes", "y", > + "enable", "enabled", "1". > + > + On success, Value is FALSE if the contents of the= fw_cfg > + file case-insensitively match "false", "no", "n", > + "disable", "disabled", "0". > + > + On failure, Value is not changed. > + > + @retval RETURN_SUCCESS Parsing successful. Value has been set. > + > + @retval RETURN_UNSUPPORTED Firmware configuration is unavailable. > + > + @retval RETURN_PROTOCOL_ERROR Parsing failed. Value has not been chan= ged. > + > + @return Error codes propagated from > + QemuFwCfgFindFile(). Value has not been > + changed. > +**/ > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseBool ( > + IN CONST CHAR8 *FileName, > + OUT BOOLEAN *Value > + ); > + > +/** > + Look up FileName with QemuFwCfgFindFile() from QemuFwCfgLib. Read the = fw_cfg > + file into a small array with automatic storage duration. Parse the arr= ay as > + the textual representation of a UINT8. > + > + @param[in] FileName The name of the fw_cfg file to look up and pars= e. > + > + @param[in] ParseAsHex If TRUE, call BaseLib's AsciiStrHexToUint64S() = for > + parsing the fw_cfg file. > + > + If FALSE, call BaseLib's AsciiStrDecimalToUint6= 4S() > + for parsing the fw_cfg file. > + > + @param[out] Value On success, Value has been parsed with the Base= Lib > + function determined by ParseAsHex, and also > + range-checked for [0, MAX_UINT8]. > + > + On failure, Value is not changed. > + > + @retval RETURN_SUCCESS Parsing successful. Value has been set. > + > + @retval RETURN_UNSUPPORTED Firmware configuration is unavailable. > + > + @retval RETURN_PROTOCOL_ERROR Parsing failed. Value has not been chan= ged. > + > + @retval RETURN_PROTOCOL_ERROR Parsing succeeded, but the result does = not fit > + in the [0, MAX_UINT8] range. Value has = not > + been changed. I wondered about RETURN_BAD_BUFFER_SIZE / RETURN_BUFFER_TOO_SMALL for=20 this case, but RETURN_PROTOCOL_ERROR is less confusing. > + > + @return Error codes propagated from > + QemuFwCfgFindFile() and from the BaseLi= b > + function selected by ParseAsHex. Value = has not > + been changed. > +**/ > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint8 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT8 *Value > + ); > + > +// > +// The following functions behave identically to QemuFwCfgParseUint8(), > +// only their range checks use MAX_UINT16, MAX_UINT32, MAX_UINT64, MAX_U= INTN, > +// respectively. > +// > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint16 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT16 *Value > + ); > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint32 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT32 *Value > + ); > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint64 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT64 *Value > + ); > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUintn ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINTN *Value > + ); > + > +#endif // QEMU_FW_CFG_SIMPLE_PARSER_LIB_H_ > diff --git a/OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimplePars= erLib.inf b/OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserL= ib.inf > new file mode 100644 > index 000000000000..c0e6ab3a1303 > --- /dev/null > +++ b/OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.i= nf > @@ -0,0 +1,27 @@ > +## @file > +# Parse the contents of named fw_cfg files as simple (scalar) data types= . > +# > +# Copyright (C) 2020, Red Hat, Inc. > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION =3D 1.29 > + BASE_NAME =3D QemuFwCfgSimpleParserLib > + FILE_GUID =3D a9a1211d-061e-4b64-af30-5dd0cac9dc9= 9 > + MODULE_TYPE =3D BASE > + VERSION_STRING =3D 1.0 > + LIBRARY_CLASS =3D QemuFwCfgSimpleParserLib > + CONSTRUCTOR =3D QemuFwCfgSimpleParserInit > + > +[Sources] > + QemuFwCfgSimpleParser.c > + > +[Packages] > + MdePkg/MdePkg.dec > + OvmfPkg/OvmfPkg.dec > + > +[LibraryClasses] > + BaseLib > + QemuFwCfgLib > diff --git a/OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimplePars= er.c b/OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParser.c > new file mode 100644 > index 000000000000..5ca22fcf0dee > --- /dev/null > +++ b/OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParser.c > @@ -0,0 +1,398 @@ > +/** @file > + Parse the contents of named fw_cfg files as simple (scalar) data types= . > + > + Copyright (C) 2020, Red Hat, Inc. > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > +**/ > + > +#include > +#include > +#include > + > +// > +// Size of the longest valid UINT64 string, including the terminating NU= L. > +// > +#define UINT64_STRING_MAX_SIZE \ > + MAX (sizeof "18446744073709551615", sizeof "0xFFFFFFFFFFFFFFFF") > + > +// > +// Size of the longest valid BOOL string (see the "mTrueString" and > +// "mFalseString" arrays below), including the terminating NUL. > +// > +#define BOOL_STRING_MAX_SIZE (sizeof "disabled") > + > +// > +// Length of "\r\n", not including the terminating NUL. > +// > +#define CRLF_LENGTH (sizeof "\r\n" - 1) > + > +// > +// Words recognized as representing TRUE or FALSE. > +// > +STATIC CONST CHAR8 * CONST mTrueString[] =3D { > + "true", "yes", "y", "enable", "enabled", "1" > +}; > +STATIC CONST CHAR8 * CONST mFalseString[] =3D { > + "false", "no", "n", "disable", "disabled", "0" > +}; > + > +// > +// Helper functions. > +// > + > +/** > + Look up FileName with QemuFwCfgFindFile() from QemuFwCfgLib. Read the = fw_cfg > + file into the caller-provided CHAR8 array. NUL-terminate the array. > + > + @param[in] FileName The name of the fw_cfg file to look up and = read. > + > + @param[in,out] BufferSize On input, number of bytes available in Buff= er. > + > + On output, the number of bytes that have be= en > + stored to Buffer. > + > + On error, BufferSize is indeterminate. > + > + @param[out] Buffer The buffer to read the fw_cfg file into. If= the > + fw_cfg file contents are not NUL-terminated= , then > + a NUL character is placed into Buffer after= the > + fw_cfg file contents. > + > + On error, Buffer is indeterminate. > + > + @retval RETURN_SUCCESS Buffer has been populated with the fw_c= fg file > + contents. Buffer is NUL-terminated rega= rdless > + of whether the fw_cfg file itself was > + NUL-terminated. > + > + @retval RETURN_UNSUPPORTED Firmware configuration is unavailable. > + > + @retval RETURN_PROTOCOL_ERROR The fw_cfg file does not fit into Buffe= r. > + (This is considered a QEMU configuratio= n > + error; BufferSize is considered authori= tative > + for the contents of the fw_cfg file ide= ntified > + by FileName.) > + > + @retval RETURN_PROTOCOL_ERROR The fw_cfg file contents are not themse= lves > + NUL-terminated, and an extra NUL byte d= oes not > + fit into Buffer. (Again a QEMU configur= ation > + error.) > + > + @return Error codes propagated from > + QemuFwCfgFindFile(). > +**/ > +STATIC > +RETURN_STATUS > +QemuFwCfgGetAsString ( > + IN CONST CHAR8 *FileName, > + IN OUT UINTN *BufferSize, > + OUT CHAR8 *Buffer > + ) > +{ > + RETURN_STATUS Status; > + FIRMWARE_CONFIG_ITEM FwCfgItem; > + UINTN FwCfgSize; > + > + if (!QemuFwCfgIsAvailable ()) { > + return RETURN_UNSUPPORTED; > + } > + > + Status =3D QemuFwCfgFindFile (FileName, &FwCfgItem, &FwCfgSize); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + if (FwCfgSize > *BufferSize) { > + return RETURN_PROTOCOL_ERROR; > + } > + > + QemuFwCfgSelectItem (FwCfgItem); > + QemuFwCfgReadBytes (FwCfgSize, Buffer); > + > + // > + // If Buffer is already NUL-terminated due to fw_cfg contents, we're d= one. > + // > + if (FwCfgSize > 0 && Buffer[FwCfgSize - 1] =3D=3D '\0') { > + *BufferSize =3D FwCfgSize; > + return RETURN_SUCCESS; > + } > + // > + // Otherwise, append a NUL byte to Buffer (if we have room for it). > + // > + if (FwCfgSize =3D=3D *BufferSize) { > + return RETURN_PROTOCOL_ERROR; > + } > + Buffer[FwCfgSize] =3D '\0'; > + *BufferSize =3D FwCfgSize + 1; > + return RETURN_SUCCESS; > +} > + > +/** > + Remove a trailing \r\n or \n sequence from a string. > + > + @param[in,out] BufferSize On input, the number of bytes in Buffer, in= cluding > + the terminating NUL. > + > + On output, the adjusted string size (includ= ing the > + terminating NUL), after stripping the \r\n = or \n > + suffix. > + > + @param[in,out] Buffer The NUL-terminated string to trim. > +**/ > +STATIC > +VOID > +StripNewline ( > + IN OUT UINTN *BufferSize, > + IN OUT CHAR8 *Buffer > + ) > +{ > + UINTN InSize, OutSize; > + > + InSize =3D *BufferSize; > + OutSize =3D InSize; > + > + if (InSize >=3D 3 && > + Buffer[InSize - 3] =3D=3D '\r' && Buffer[InSize - 2] =3D=3D '\n') = { > + OutSize =3D InSize - 2; > + } else if (InSize >=3D 2 && Buffer[InSize - 2] =3D=3D '\n') { > + OutSize =3D InSize - 1; > + } > + > + if (OutSize < InSize) { > + Buffer[OutSize - 1] =3D '\0'; > + *BufferSize =3D OutSize; > + } > +} > + > +/** > + Read the fw_cfg file identified by FileName as a string into a small a= rray > + with automatic storage duration, using QemuFwCfgGetAsString(). Parse t= he > + string as a UINT64. Perform a range-check on the parsed value. > + > + @param[in] FileName The name of the fw_cfg file to look up and pars= e. > + > + @param[in] ParseAsHex If TRUE, call BaseLib's AsciiStrHexToUint64S() = for > + parsing the fw_cfg file. > + > + If FALSE, call BaseLib's AsciiStrDecimalToUint6= 4S() > + for parsing the fw_cfg file. > + > + @param[in] Limit The inclusive upper bound on the parsed UINT64 = value. > + > + @param[out] Value On success, Value has been parsed with the Base= Lib > + function determined by ParseAsHex, and has been > + range-checked against [0, Limit]. > + > + On failure, Value is not changed. > + > + @retval RETURN_SUCCESS Parsing successful. Value has been set. > + > + @retval RETURN_UNSUPPORTED Firmware configuration is unavailable. > + > + @retval RETURN_PROTOCOL_ERROR Parsing failed. Value has not been chan= ged. > + > + @retval RETURN_PROTOCOL_ERROR Parsing succeeded, but the result does = not fit > + in the [0, Limit] range. Value has not = been > + changed. > + > + @return Error codes propagated from > + QemuFwCfgFindFile() and from the BaseLi= b > + function selected by ParseAsHex. Value = has not > + been changed. > +**/ > +STATIC > +RETURN_STATUS > +QemuFwCfgParseUint64WithLimit ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + IN UINT64 Limit, > + OUT UINT64 *Value > + ) > +{ > + UINTN Uint64StringSize; > + CHAR8 Uint64String[UINT64_STRING_MAX_SIZE + CRLF_LENGTH]; > + RETURN_STATUS Status; > + CHAR8 *EndPointer; > + UINT64 Uint64; > + > + Uint64StringSize =3D sizeof Uint64String; > + Status =3D QemuFwCfgGetAsString (FileName, &Uint64StringSize, Uint64St= ring); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + > + StripNewline (&Uint64StringSize, Uint64String); > + > + if (ParseAsHex) { > + Status =3D AsciiStrHexToUint64S (Uint64String, &EndPointer, &Uint64)= ; > + } else { > + Status =3D AsciiStrDecimalToUint64S (Uint64String, &EndPointer, &Uin= t64); > + } > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + > + // > + // Report a wire protocol error if the subject sequence is empty, or t= railing > + // garbage is present, or Limit is not honored. > + // > + if (EndPointer =3D=3D Uint64String || *EndPointer !=3D '\0' || Uint64 = > Limit) { > + return RETURN_PROTOCOL_ERROR; > + } > + > + *Value =3D Uint64; > + return RETURN_SUCCESS; > +} > + > +// > +// Public functions. > +// > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgSimpleParserInit ( > + VOID > + ) > +{ > + // > + // Do nothing, just participate in constructor dependency ordering. > + // > + return RETURN_SUCCESS; > +} > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseBool ( > + IN CONST CHAR8 *FileName, > + OUT BOOLEAN *Value > + ) > +{ > + UINTN BoolStringSize; > + CHAR8 BoolString[BOOL_STRING_MAX_SIZE + CRLF_LENGTH]; > + RETURN_STATUS Status; > + UINTN Idx; > + > + BoolStringSize =3D sizeof BoolString; > + Status =3D QemuFwCfgGetAsString (FileName, &BoolStringSize, BoolString= ); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + > + StripNewline (&BoolStringSize, BoolString); > + > + for (Idx =3D 0; Idx < ARRAY_SIZE (mTrueString); ++Idx) { > + if (AsciiStriCmp (BoolString, mTrueString[Idx]) =3D=3D 0) { > + *Value =3D TRUE; > + return RETURN_SUCCESS; > + } > + } > + > + for (Idx =3D 0; Idx < ARRAY_SIZE (mFalseString); ++Idx) { > + if (AsciiStriCmp (BoolString, mFalseString[Idx]) =3D=3D 0) { > + *Value =3D FALSE; > + return RETURN_SUCCESS; > + } > + } > + > + return RETURN_PROTOCOL_ERROR; > +} > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint8 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT8 *Value > + ) > +{ > + RETURN_STATUS Status; > + UINT64 Uint64; > + > + Status =3D QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UI= NT8, > + &Uint64); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + *Value =3D (UINT8)Uint64; > + return RETURN_SUCCESS; > +} > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint16 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT16 *Value > + ) > +{ > + RETURN_STATUS Status; > + UINT64 Uint64; > + > + Status =3D QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UI= NT16, > + &Uint64); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + *Value =3D (UINT16)Uint64; > + return RETURN_SUCCESS; > +} > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint32 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT32 *Value > + ) > +{ > + RETURN_STATUS Status; > + UINT64 Uint64; > + > + Status =3D QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UI= NT32, > + &Uint64); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + *Value =3D (UINT32)Uint64; > + return RETURN_SUCCESS; > +} > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUint64 ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINT64 *Value > + ) > +{ > + RETURN_STATUS Status; > + UINT64 Uint64; > + > + Status =3D QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UI= NT64, > + &Uint64); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + *Value =3D Uint64; > + return RETURN_SUCCESS; > +} > + > +RETURN_STATUS > +EFIAPI > +QemuFwCfgParseUintn ( > + IN CONST CHAR8 *FileName, > + IN BOOLEAN ParseAsHex, > + OUT UINTN *Value > + ) > +{ > + RETURN_STATUS Status; > + UINT64 Uint64; > + > + Status =3D QemuFwCfgParseUint64WithLimit (FileName, ParseAsHex, MAX_UI= NTN, > + &Uint64); > + if (RETURN_ERROR (Status)) { > + return Status; > + } > + *Value =3D (UINTN)Uint64; > + return RETURN_SUCCESS; > +} >=20 Neat. Reviewed-by: Philippe Mathieu-Daude