From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mx.groups.io with SMTP id smtpd.web11.2602.1591861376188687982 for ; Thu, 11 Jun 2020 00:42:56 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=vlBNp3pk; spf=pass (domain: intel.com, ip: 134.134.136.24, mailfrom: zhichao.gao@intel.com) IronPort-SDR: 5P7y04aufnL7ak3u3MqMYKGQxe2+aJSBzn4nXUFsoupSVLX/lebgdCRWvXcFoI/rqXVrN4WVpL guBo0Xl8sDjQ== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Jun 2020 00:42:54 -0700 IronPort-SDR: bM5ssCyTrzU99JK3cDQby34Slh5+5xSLS+34qdi0ZKYiUXPJIAkRhQRQcZm/+cxlMnAFH5diof 87VxiQfIQUig== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,499,1583222400"; d="scan'208";a="296503028" Received: from orsmsx105.amr.corp.intel.com ([10.22.225.132]) by fmsmga004.fm.intel.com with ESMTP; 11 Jun 2020 00:42:54 -0700 Received: from orsmsx602.amr.corp.intel.com (10.22.229.15) by ORSMSX105.amr.corp.intel.com (10.22.225.132) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 11 Jun 2020 00:42:53 -0700 Received: from orsmsx608.amr.corp.intel.com (10.22.229.21) by ORSMSX602.amr.corp.intel.com (10.22.229.15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Thu, 11 Jun 2020 00:42:53 -0700 Received: from ORSEDG001.ED.cps.intel.com (10.7.248.4) by orsmsx608.amr.corp.intel.com (10.22.229.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Thu, 11 Jun 2020 00:42:53 -0700 Received: from NAM04-CO1-obe.outbound.protection.outlook.com (104.47.45.51) by edgegateway.intel.com (134.134.137.100) with Microsoft SMTP Server (TLS) id 14.3.439.0; Thu, 11 Jun 2020 00:42:53 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=UIXg9f9tEQNwJ4wfEw9awqLh2pfBpKx6wV3xcJ/5i+vWIwSLDTosr81ofQ5Ie0ZGR48qfCPveT9s+LQ1m5kGChVWJmWxAJDtYfU/PDOqMHjfK++4lF57XfSM/mBK7IlJNnGUHU0X5bsV6A/DhES0isa0c8mAS/B/HmeXNkX6KfU+xiBIGUz3iCEaDjAnmrIn7MedVYtG57Yp65fGqB8ExugaN22yEXyLBIuJSDGV6i/+ealUBtHLQ/xRbkEltHcGMc3TADT5t3sutlU7cO7t7VTGQGy2+qhwMrgAETEoDAg/enFlVUSfOkf08SfjbEv8iuVVC9EgKnNCPrpJ22ZXng== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=CCKGbiZs6Lm1vmsTgWXYY1UUAaJRbfK6gkJX4Mu7Ik8=; b=fcyUwhlcSKesiarnh1guGnmyT7/Fp1lg84rdzM9aIf4ebbVF3oiN1fkFgNTBF2xTVDs1o1fGgW4Ql3MbBT7KOA7ma8XHU3I9vJk2DJ0o2Rk6fYVQkC+93jlETF0xWqVpTwgZ8JiYwHzW3fnq2PRYkzp7wVxFemwj13LTiwZVNRLN8zcO2TCVAzzmrQYMuzpq2ATgNP7TmjTGjToS6NXpfLhPf12mAfG066mJds6XIiyVY+0H3Qol4u09rCl47weUgsdMbPJCsW+jx5fuZYFh9vAjhJ2TSc9kWwsJD48+7mpAB1vBL1oZtmGkol/wKOhy8li88tutdx2Q5LKgOqLHMg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=CCKGbiZs6Lm1vmsTgWXYY1UUAaJRbfK6gkJX4Mu7Ik8=; b=vlBNp3pkMBS8ACCWdSyPItqSESf+tQoqn0pPWgE4xz1n6L5upQIgZI5CX8DVmXhGOGnwH1daiWUNZ2zLcc2bdHQ8ZRqbUEDfBhLGCgBGZeT0tKddGzexcXpUv2kQBdRlLrGv4/o+0+fJTMuS3ME2vMVsqMDNzJvwXfEFA/9CxmQ= Received: from DM6PR11MB4425.namprd11.prod.outlook.com (2603:10b6:5:1d9::31) by DM6PR11MB4706.namprd11.prod.outlook.com (2603:10b6:5:2a5::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3088.18; Thu, 11 Jun 2020 07:42:50 +0000 Received: from DM6PR11MB4425.namprd11.prod.outlook.com ([fe80::615a:17b0:aa95:be1]) by DM6PR11MB4425.namprd11.prod.outlook.com ([fe80::615a:17b0:aa95:be1%3]) with mapi id 15.20.3066.023; Thu, 11 Jun 2020 07:42:49 +0000 From: "Gao, Zhichao" To: Krzysztof Koch , "devel@edk2.groups.io" CC: "Ni, Ray" , "Sami.Mujawar@arm.com" , "Laura.Moretta@arm.comMatteo.Carlini@arm.com" , "nd@arm.com" Subject: Re: [PATCH v1 1/6] ShellPkg: acpiview: Add interface for data-driven table parsing Thread-Topic: [PATCH v1 1/6] ShellPkg: acpiview: Add interface for data-driven table parsing Thread-Index: AQHWIvRtj9t9pFqPqU+8q4DOhAMAwqjTJtZQ Date: Thu, 11 Jun 2020 07:42:49 +0000 Message-ID: References: <20200505154604.9848-1-krzysztof.koch@arm.com> <20200505154604.9848-2-krzysztof.koch@arm.com> In-Reply-To: <20200505154604.9848-2-krzysztof.koch@arm.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-reaction: no-action dlp-version: 11.2.0.6 authentication-results: arm.com; dkim=none (message not signed) header.d=none;arm.com; dmarc=none action=none header.from=intel.com; x-originating-ip: [192.102.204.38] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 192d26ec-4a67-4506-5288-08d80ddb0a81 x-ms-traffictypediagnostic: DM6PR11MB4706: x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:10000; x-forefront-prvs: 0431F981D8 x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: Ts1uAgBAtMIsKUzGNIVjeLNcvUauO4C8Vk45NUZ5H5XZRf7Dk7FhPhJbuddShofRrlgPzQdJ9RVO2emmeIHqMALnTLdhj45G/l8RmyljkWalWGUnzDdD4DdcZA8He+izgHiLpXPtPuhBQE4Cn/EnFBRTVEjBwmC4Wi3+05wLhbUIlUj782QBBRVGVT95tkwYvlwc/mn0xiRV2rm8K0vp1D8cB6bkr7aA6aub8zX+2EupDBO4BRam3cqJK4Wy1yJ0EMRf288AzwKIXuMH0N3gFFZmgCMAAMakrkiPWVCcf6MXb3YRx7ANoLgOeyaydlWT x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR11MB4425.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(346002)(39860400002)(366004)(376002)(136003)(396003)(9686003)(8676002)(5660300002)(316002)(55016002)(6506007)(7696005)(52536014)(4326008)(66946007)(66476007)(76116006)(30864003)(53546011)(83380400001)(8936002)(186003)(54906003)(71200400001)(110136005)(478600001)(86362001)(66556008)(26005)(66446008)(33656002)(64756008)(2906002)(579004);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: xnGgoxymrfla9mMijPSUMqYuDnomfnQKDTHigE+ZHbha9O3eWTMJz0f6j/V0vKGv4puvLWDs0xrSkNhC3SJxk78q9AklMNBMMxB2uaLCizAVHsvq0Yljtlfyv1JTTlJd8N0Jtn5SDZ3bZ86idLA5bkK4mYWDw6dWqUX03+bQ8qpEUuYeEPVAFDC06QBqASeadjgOazOa9wfuvH2zQhb+ozoTl6NCVtbj91qWRfRIhe2murJcht5eI4+fol/SWDSDhcJtEJQiQGoS74COaGCGJM8sws6SiQ2Uh6skbjQwHdxS94NzT5V2/4tdcwb30stnZi4yIxTwPt0miXL6qQgFWKib5h+ehGYRbrcr+oygY3FDSmrG4ge17FTwK1jEPP2hd4ZvOEFFMCekpBrrHMYl62rI+CoE+BKOCiYGT3zhw9ei7GE6lYxf/R2fNlNV2oZzYdy/CG35AZia530Y36XWAZ18JzXjIcgFv/+QB6m4+AM+hmwQLljgh1CHn/3EZrDQ MIME-Version: 1.0 X-MS-Exchange-CrossTenant-Network-Message-Id: 192d26ec-4a67-4506-5288-08d80ddb0a81 X-MS-Exchange-CrossTenant-originalarrivaltime: 11 Jun 2020 07:42:49.6422 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: tb8No+jsHgYmFEUSA+iedUhyECmKmjPZwsclOdQhw2lJinBpyJwWg6zxa0Hoy4Mgdc3Ys5W1Xbqr/sYKtRu01w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB4706 Return-Path: zhichao.gao@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable (1) The ASSERT only works with DEBUG build. I think we need add if conditio= n after the ASSERT to return the error code to avoid the null pointer deref= erence. (2) It is suggested to use the const (lower-case) instead of CONST. same to= static. Others are fine to me. Thanks, Zhichao > -----Original Message----- > From: Krzysztof Koch > Sent: Tuesday, May 5, 2020 11:46 PM > To: devel@edk2.groups.io > Cc: Ni, Ray ; Gao, Zhichao ; > Sami.Mujawar@arm.com; Laura.Moretta@arm.comMatteo.Carlini@arm.com; > nd@arm.com > Subject: [PATCH v1 1/6] ShellPkg: acpiview: Add interface for data-driven= table > parsing >=20 > Define and implement an interface to streamline metadata collection and > validation for structures present in each ACPI table. >=20 > Most ACPI tables define substructures which constitute the table. > These substructures are identified by their 'Type' field value. The range= of > possible 'Type' values is defined on a per-table basis. >=20 > For more sophisticated ACPI table validation, additional data about each > structure type needs to be maintained. This patch defines a new > ACPI_STRUCT_INFO structure. It stores additional metadata about a buildin= g > block of an ACPI table. ACPI_STRUCT_INFO's are organised into > ACPI_STRUCT_DATABASE's. ACPI_STRUCT_DATABASE is an array of > ACPI_STRUCT_INFO elements which are indexed using structure's type value. >=20 > For example, in the Multiple APIC Description Table (MADT) all Interrupt > Controller Structure types form a single database. In the database, the G= IC CPU > Interface (GICC) structure's metadata is the 11th entry (i.e. Type =3D 0x= B). >=20 > ACPI_STRUCT_INFO structure consists of: > - ASCII name of the structure > - ACPI-defined stucture Type > - bitmask defining the validity of the structure for various > architectures > - instance counter > - a handler for the structure (ACPI_STRUCT_HANDLER) >=20 > The bitmask allows detection of structures in a table which are not compa= tible > with the target platform. >=20 > For example, the Multiple APIC Description Table (MADT) contains Interrup= t > Controller Structure definitions which apply to either the Advanced > Programmable Interrupt Controller (APIC) model or the Generic Interrupt > Controller (GIC) model. Presence of APIC-related structures on an Arm-bas= ed > platform is a bug which is now detected and reported by acpiview. >=20 > This patch adds support for compatibility checks with the Arm architectur= e only. > However, provisions are made to allow extensions to other architectures. >=20 > ACPI_STRUCT_HANDLER describes how the contents of the structure can be > parsed. The possible options are: > - An ACPI_PARSER array which can be passed to the ParseAcpi() function > - A dedicated function for parsing the structure > (ACPI_STRUCT_PARSER_FUNC) >=20 > If neither of these options is provided, it is assumed that the parsing l= ogic is not > implemented. >=20 > ACPI_STRUCT_PARSER_FUNC expects the the first two arguments to be the > pointer to the start of the structure to parse and the length of structur= e's buffer. > The remaining two optional arguments are context specific. >=20 > This patch adds methods for: > - Resetting the instance count for all structure types in a table. > - Getting the combined instance count for all types in a table. > - Validating the compatibility of a structure with the target arch. > - Printing structure counts for the types which are compatible with > the target architecture and validating that the non-compatible > structures are not present in the table. > - Parsing the structure according to the information provided by its > handle. >=20 > Finally, define a helper PrintAcpiStructName () function to streamline th= e printing > of ACPI structure name together with the structure's current occurrence c= ount. >=20 > References: > - ACPI 6.3, January 2019 >=20 > Signed-off-by: Krzysztof Koch > --- >=20 > Notes: > v1: > - Add interface for data-driven table parsing [Krzysztof] >=20 > ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c | 263 > ++++++++++++++++++++ > ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h | 234 > +++++++++++++++++ > 2 files changed, 497 insertions(+) >=20 > diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c > b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c > index > 3f12a33050a4e4ab3be2187c90ef8dcf0882283d..32566101e2de2eec3ccf44563ee > 79379404bff62 100644 > --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c > +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c > @@ -6,6 +6,8 @@ > **/ >=20 > #include > +#include > +#include > #include > #include > #include "AcpiParser.h" > @@ -466,6 +468,267 @@ PrintFieldName ( > ); > } >=20 > +/** > + Produce a Null-terminated ASCII string with the name and index of an > + ACPI structure. > + > + The output string is in the following format: [] > + > + @param [in] Name Structure name. > + @param [in] Index Structure index. > + @param [in] BufferSize The size, in bytes, of the output buffer. > + @param [out] Buffer Buffer for the output string. > + > + @return The number of bytes written to the buffer (not including Nul= l-byte) > +**/ > +UINTN > +EFIAPI > +PrintAcpiStructName ( > + IN CONST CHAR8* Name, > + IN UINT32 Index, > + IN UINTN BufferSize, > + OUT CHAR8* Buffer > + ) > +{ > + ASSERT (Name !=3D NULL); > + ASSERT (Buffer !=3D NULL); > + > + return AsciiSPrint (Buffer, BufferSize, "%a [%d]", Name , Index); } > + > +/** > + Set all ACPI structure instance counts to 0. > + > + @param [in,out] StructDb ACPI structure database with counts to re= set. > +**/ > +VOID > +EFIAPI > +ResetAcpiStructCounts ( > + IN OUT ACPI_STRUCT_DATABASE* StructDb > + ) > +{ > + UINT32 Type; > + > + ASSERT (StructDb !=3D NULL); > + ASSERT (StructDb->Entries !=3D NULL); > + > + for (Type =3D 0; Type < StructDb->EntryCount; Type++) { > + StructDb->Entries[Type].Count =3D 0; > + } > +} > + > +/** > + Sum all ACPI structure instance counts. > + > + @param [in] StructDb ACPI structure database with per-type counts = to sum. > + > + @return Total number of structure instances recorded in the database= . > +**/ > +UINT32 > +EFIAPI > +SumAcpiStructCounts ( > + IN CONST ACPI_STRUCT_DATABASE* StructDb > + ) > +{ > + UINT32 Type; > + UINT32 Total; > + > + ASSERT (StructDb !=3D NULL); > + ASSERT (StructDb->Entries !=3D NULL); > + > + Total =3D 0; > + > + for (Type =3D 0; Type < StructDb->EntryCount; Type++) { > + Total +=3D StructDb->Entries[Type].Count; } > + > + return Total; > +} > + > +/** > + Validate that a structure with a given type value is defined for the > +given > + ACPI table and target architecture. > + > + The target architecture is evaluated from the firmare build parameters= . > + > + @param [in] Type ACPI-defined structure type. > + @param [in] StructDb ACPI structure database with architecture > + compatibility info. > + > + @retval TRUE Structure is valid. > + @retval FALSE Structure is not valid. > +**/ > +BOOLEAN > +EFIAPI > +IsAcpiStructTypeValid ( > + IN UINT32 Type, > + IN CONST ACPI_STRUCT_DATABASE* StructDb > + ) > +{ > + UINT32 Compatible; > + > + ASSERT (StructDb !=3D NULL); > + ASSERT (StructDb->Entries !=3D NULL); > + > + if (Type >=3D StructDb->EntryCount) { > + return FALSE; > + } > + > +#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) > + Compatible =3D StructDb->Entries[Type].CompatArch & > + (ARCH_COMPAT_ARM | ARCH_COMPAT_AARCH64); #else > + Compatible =3D StructDb->Entries[Type].CompatArch; > +#endif > + > + return (Compatible !=3D 0); > +} > + > +/** > + Print the instance count of each structure in an ACPI table that is > + compatible with the target architecture. > + > + For structures which are not allowed for the target architecture, > + validate that their instance counts are 0. > + > + @param [in] StructDb ACPI structure database with counts to valida= te. > + > + @retval TRUE All structures are compatible. > + @retval FALSE One or more incompatible structures present. > +**/ > +BOOLEAN > +EFIAPI > +ValidateAcpiStructCounts ( > + IN CONST ACPI_STRUCT_DATABASE* StructDb > + ) > +{ > + BOOLEAN AllValid; > + UINT32 Type; > + > + ASSERT (StructDb !=3D NULL); > + ASSERT (StructDb->Entries !=3D NULL); > + > + AllValid =3D TRUE; > + Print (L"\nTable Breakdown:\n"); > + > + for (Type =3D 0; Type < StructDb->EntryCount; Type++) { > + ASSERT (Type =3D=3D StructDb->Entries[Type].Type); > + > + if (IsAcpiStructTypeValid (Type, StructDb)) { > + Print ( > + L"%*a%-*a : %d\n", > + INSTANCE_COUNT_INDENT, > + "", > + OUTPUT_FIELD_COLUMN_WIDTH - INSTANCE_COUNT_INDENT, > + StructDb->Entries[Type].Name, > + StructDb->Entries[Type].Count > + ); > + } else if (StructDb->Entries[Type].Count > 0) { > + AllValid =3D FALSE; > + IncrementErrorCount (); > + Print ( > + L"ERROR: %a Structure is not valid for the target architecture "= \ > + L"(found %d)\n", > + StructDb->Entries[Type].Name, > + StructDb->Entries[Type].Count > + ); > + } > + } > + > + return AllValid; > +} > + > +/** > + Parse the ACPI structure with the type value given according to > +instructions > + defined in the ACPI structure database. > + > + If the input structure type is defined in the database, increment > + structure's instance count. > + > + If ACPI_PARSER array is used to parse the input structure, the index > + of the structure (instance count for the type before update) gets > + printed alongside the structure name. This helps debugging if there > + are many instances of the type in a table. For > + ACPI_STRUCT_PARSER_FUNC, the printing of the index must be implemented > separately. > + > + @param [in] Indent Number of spaces to indent the output. > + @param [in] Ptr Ptr to the start of the structure. > + @param [in,out] StructDb ACPI structure database with instructions on= how > + parse every structure type. > + @param [in] Offset Structure offset from the start of the table= . > + @param [in] Type ACPI-defined structure type. > + @param [in] Length Length of the structure in bytes. > + @param [in] OptArg0 First optional argument to pass to parser fu= nction. > + @param [in] OptArg1 Second optional argument to pass to parser f= unction. > + > + @retval TRUE ACPI structure parsed successfully. > + @retval FALSE Undefined structure type or insufficient data to parse= . > +**/ > +BOOLEAN > +EFIAPI > +ParseAcpiStruct ( > + IN UINT32 Indent, > + IN UINT8* Ptr, > + IN OUT ACPI_STRUCT_DATABASE* StructDb, > + IN UINT32 Offset, > + IN UINT32 Type, > + IN UINT32 Length, > + IN CONST VOID* OptArg0 OPTIONAL, > + IN CONST VOID* OptArg1 OPTIONAL > + ) > +{ > + ACPI_STRUCT_PARSER_FUNC ParserFunc; > + CHAR8 Buffer[80]; > + > + ASSERT (Ptr !=3D NULL); > + ASSERT (StructDb !=3D NULL); > + ASSERT (StructDb->Entries !=3D NULL); > + ASSERT (StructDb->Name !=3D NULL); > + > + PrintFieldName (Indent, L"* Offset *"); Print (L"0x%x\n", Offset); > + > + if (Type >=3D StructDb->EntryCount) { > + IncrementErrorCount (); > + Print (L"ERROR: Unknown %a. Type =3D %d\n", StructDb->Name, Type); > + return FALSE; > + } > + > + if (StructDb->Entries[Type].Handler.ParserFunc !=3D NULL) { > + ParserFunc =3D StructDb->Entries[Type].Handler.ParserFunc; > + ParserFunc (Ptr, Length, OptArg0, OptArg1); } else if > + (StructDb->Entries[Type].Handler.ParserArray !=3D NULL) { > + ASSERT (StructDb->Entries[Type].Handler.Elements !=3D 0); > + > + PrintAcpiStructName ( > + StructDb->Entries[Type].Name, > + StructDb->Entries[Type].Count, > + sizeof (Buffer), > + Buffer > + ); > + > + ParseAcpi ( > + TRUE, > + Indent, > + Buffer, > + Ptr, > + Length, > + StructDb->Entries[Type].Handler.ParserArray, > + StructDb->Entries[Type].Handler.Elements > + ); > + } else { > + StructDb->Entries[Type].Count++; > + Print ( > + L"ERROR: Parsing of %a Structure is not implemented\n", > + StructDb->Entries[Type].Name > + ); > + return FALSE; > + } > + > + StructDb->Entries[Type].Count++; > + return TRUE; > +} > + > /** > This function is used to parse an ACPI table buffer. >=20 > diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h > b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h > index > f81ccac7e118378aa185db4b625e5bcd75f78347..70e540b3a76de0ff9ce70bcabed > 8548063bea0ff 100644 > --- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h > +++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h > @@ -300,6 +300,240 @@ typedef struct AcpiParser { > VOID* Context; > } ACPI_PARSER; >=20 > +/** > + Produce a Null-terminated ASCII string with the name and index of an > + ACPI structure. > + > + The output string is in the following format: [] > + > + @param [in] Name Structure name. > + @param [in] Index Structure index. > + @param [in] BufferSize The size, in bytes, of the output buffer. > + @param [out] Buffer Buffer for the output string. > + > + @return The number of bytes written to the buffer (not including Nul= l-byte) > +**/ > +UINTN > +EFIAPI > +PrintAcpiStructName ( > + IN CONST CHAR8* Name, > + IN UINT32 Index, > + IN UINTN BufferSize, > + OUT CHAR8* Buffer > + ); > + > +/** > + Indentation for printing instance counts for structures in an ACPI tab= le. > +**/ > +#define INSTANCE_COUNT_INDENT 2 > + > +/** > + Common signature for functions which parse ACPI structures. > + > + @param [in] Ptr Pointer to the start of structure's buffer. > + @param [in] Length Length of the buffer. > + @param [in] OptArg0 First optional argument. > + @param [in] OptArg1 Second optional argument. > +*/ > +typedef VOID (*ACPI_STRUCT_PARSER_FUNC) ( > + IN UINT8* Ptr, > + IN UINT32 Length, > + IN CONST VOID* OptArg0 OPTIONAL, > + IN CONST VOID* OptArg1 OPTIONAL > + ); > + > +/** > + Description of how an ACPI structure should be parsed. > + > + One of ParserFunc or ParserArray should be not NULL. Otherwise, it is > + assumed that parsing of an ACPI structure is not supported. If both > + ParserFunc and ParserArray are defined, ParserFunc is used. > +**/ > +typedef struct AcpiStructHandler { > + /// Dedicated function for parsing an ACPI structure > + ACPI_STRUCT_PARSER_FUNC ParserFunc; > + /// Array of instructions on how each structure field should be parsed > + CONST ACPI_PARSER* ParserArray; > + /// Number of elements in ParserArray if ParserArray is defined > + UINT32 Elements; > +} ACPI_STRUCT_HANDLER; > + > +/** > + ACPI structure compatiblity with various architectures. > + > + Some ACPI tables define structures which are, for example, only valid > + in the X64 or Arm context. For instance, the Multiple APIC > + Description Table > + (MADT) describes both APIC and GIC interrupt models. > + > + These definitions provide means to describe the belonging of a > +structure > + in an ACPI table to a particular architecture. This way, incompatible > + structures can be detected. > +**/ > +#define ARCH_COMPAT_IA32 BIT0 > +#define ARCH_COMPAT_X64 BIT1 > +#define ARCH_COMPAT_ARM BIT2 > +#define ARCH_COMPAT_AARCH64 BIT3 > +#define ARCH_COMPAT_RISCV64 BIT4 > + > +/** > + Information about a structure which constitutes an ACPI table **/ > +typedef struct AcpiStructInfo { > + /// ACPI-defined structure Name > + CONST CHAR8* Name; > + /// ACPI-defined structure Type > + CONST UINT32 Type; > + /// Architecture(s) for which this structure is valid > + CONST UINT32 CompatArch; > + /// Structure's instance count in a table > + UINT32 Count; > + /// Information on how to handle the structure > + CONST ACPI_STRUCT_HANDLER Handler; > +} ACPI_STRUCT_INFO; > + > +/** > + Macro for defining ACPI structure info when an ACPI_PARSER array must > + be used to parse the structure. > +**/ > +#define ADD_ACPI_STRUCT_INFO_ARRAY(Name, Type, Compat, Array) = \ > +{ = \ > + Name, Type, Compat, 0, {NULL, Array, ARRAY_SIZE (Array)} = \ > +} > + > +/** > + Macro for defining ACPI structure info when an > +ACPI_STRUCT_PARSER_FUNC > + must be used to parse the structure. > +**/ > +#define ADD_ACPI_STRUCT_INFO_FUNC(Name, Type, Compat, Func) = \ > +{ = \ > + Name, Type, Compat, 0, {Func, NULL, 0} = \ > +} > + > +/** > + Macro for defining ACPI structure info when the structure is defined > +in > + the ACPI spec but no parsing information is provided. > +**/ > +#define ACPI_STRUCT_INFO_PARSER_NOT_IMPLEMENTED(Name, Type, > Compat) \ > +{ = \ > + Name, Type, Compat, 0, {NULL, NULL, 0} = \ > +} > + > +/** > + Database collating information about every structure type defined by > + an ACPI table. > +**/ > +typedef struct AcpiStructDatabase { > + /// ACPI-defined name for the structures being described in the databa= se > + CONST CHAR8* Name; > + /// Per-structure-type information. The list must be ordered by the > +types > + /// defined for the table. All entries must be unique and there > +should be > + /// no gaps. > + ACPI_STRUCT_INFO* Entries; > + /// Total number of unique types defined for the table > + CONST UINT32 EntryCount; > +} ACPI_STRUCT_DATABASE; > + > +/** > + Set all ACPI structure instance counts to 0. > + > + @param [in,out] StructDb ACPI structure database with counts to re= set. > +**/ > +VOID > +EFIAPI > +ResetAcpiStructCounts ( > + IN OUT ACPI_STRUCT_DATABASE* StructDb > + ); > + > +/** > + Sum all ACPI structure instance counts. > + > + @param [in] StructDb ACPI structure database with per-type counts = to sum. > + > + @return Total number of structure instances recorded in the database= . > +**/ > +UINT32 > +EFIAPI > +SumAcpiStructCounts ( > + IN CONST ACPI_STRUCT_DATABASE* StructDb > + ); > + > +/** > + Validate that a structure with a given type value is defined for the > +given > + ACPI table and target architecture. > + > + The target architecture is evaluated from the firmare build parameters= . > + > + @param [in] Type ACPI-defined structure type. > + @param [in] StructDb ACPI structure database with architecture > + compatibility info. > + > + @retval TRUE Structure is valid. > + @retval FALSE Structure is not valid. > +**/ > +BOOLEAN > +EFIAPI > +IsAcpiStructTypeValid ( > + IN UINT32 Type, > + IN CONST ACPI_STRUCT_DATABASE* StructDb > + ); > + > +/** > + Print the instance count of each structure in an ACPI table that is > + compatible with the target architecture. > + > + For structures which are not allowed for the target architecture, > + validate that their instance counts are 0. > + > + @param [in] StructDb ACPI structure database with counts to valida= te. > + > + @retval TRUE All structures are compatible. > + @retval FALSE One or more incompatible structures present. > +**/ > +BOOLEAN > +EFIAPI > +ValidateAcpiStructCounts ( > + IN CONST ACPI_STRUCT_DATABASE* StructDb > + ); > + > +/** > + Parse the ACPI structure with the type value given according to > +instructions > + defined in the ACPI structure database. > + > + If the input structure type is defined in the database, increment > + structure's instance count. > + > + If ACPI_PARSER array is used to parse the input structure, the index > + of the structure (instance count for the type before update) gets > + printed alongside the structure name. This helps debugging if there > + are many instances of the type in a table. For > + ACPI_STRUCT_PARSER_FUNC, the printing of the index must be implemented > separately. > + > + @param [in] Indent Number of spaces to indent the output. > + @param [in] Ptr Ptr to the start of the structure. > + @param [in,out] StructDb ACPI structure database with instructions on= how > + parse every structure type. > + @param [in] Offset Structure offset from the start of the table= . > + @param [in] Type ACPI-defined structure type. > + @param [in] Length Length of the structure in bytes. > + @param [in] OptArg0 First optional argument to pass to parser fu= nction. > + @param [in] OptArg1 Second optional argument to pass to parser f= unction. > + > + @retval TRUE ACPI structure parsed successfully. > + @retval FALSE Undefined structure type or insufficient data to parse= . > +**/ > +BOOLEAN > +EFIAPI > +ParseAcpiStruct ( > + IN UINT32 Indent, > + IN UINT8* Ptr, > + IN OUT ACPI_STRUCT_DATABASE* StructDb, > + IN UINT32 Offset, > + IN UINT32 Type, > + IN UINT32 Length, > + IN CONST VOID* OptArg0 OPTIONAL, > + IN CONST VOID* OptArg1 OPTIONAL > + ); > + > /** > A structure used to store the pointers to the members of the > ACPI description header structure that was parsed. > -- > 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'