From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR05-VI1-obe.outbound.protection.outlook.com (EUR05-VI1-obe.outbound.protection.outlook.com [40.107.21.58]) by mx.groups.io with SMTP id smtpd.web10.9860.1657636329240493825 for ; Tue, 12 Jul 2022 07:32:10 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@armh.onmicrosoft.com header.s=selector2-armh-onmicrosoft-com header.b=pBir0YRh; spf=pass (domain: arm.com, ip: 40.107.21.58, mailfrom: sami.mujawar@arm.com) ARC-Seal: i=2; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=pass; b=UdlaE6uDeynwB8LEoK6OuArsXBZ/epRBKmp5q/HrQ7FNtyJNBcnzX7rChkpBjiCcy3BEpgtuumTQt3hOtGB3gqNJ4bty6cWnLlEWULapNmkaXCJ45vOPbe4pK2E82edtnWULClnBpvKVH6ABjU5L5LtoFCwP6XE/Jmf+GZjXQvUZo7B+qUMhdHYaa1tg0sVHRN/XIhAPn533W6CeZ4sdJDxkZ8FNdaB9MiCya2+U7qO3JF5uZ9XE1YtpnuHHzbQ3IBWSc+Dki7NHpuHu0PR+V03L4XrJqMum+2RZLP7fMYewGWNa0uDqqhPhwN/cpZvp/R+3oXuOnFTnY26WndVOow== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Xl3VXFCg9BxNjat0H1S+/SkFo2L8/f31rbXkyqCBBnw=; b=TBJq7FygI/oGdOlnc1KFKkkZCJ3yhVSB/mLRTAPkMFtiL2Kg8qLjtrxAqvu8b4UX5YcbtSnPrTRcP+gc0OtZMjAK6f+loQtkG7AX1Y6HOTCLBbZYOmvkwKT4DRWzrqg5zhabYqp6J+kfQjqRmftO4zwK5ePBgQafnawjs1PUIENRsfD8LWQCYwITRSJGmANXdcnr2eXYZJS2CXqpu+hw5lBl75QKYGTKYnKUMJH5zbxnsJVLzwAplHscBjhU6TSBlVjRJl6RE39HV51ZJ8WcEPmMpqa9+RRyqFEViwdkl5zdBGjCJGN9nUAmbAfF4ZwWSkzzcjawghen93nWfwpr0w== ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 63.35.35.123) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=arm.com] dmarc=[1,1,header.from=arm.com]) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Xl3VXFCg9BxNjat0H1S+/SkFo2L8/f31rbXkyqCBBnw=; b=pBir0YRhtVIkZa68Yjf+JpLN4aohjuuo8tyHc2He53nZWBfa915r4PFk/UKY9uZxJnnchpvekA9pchs5VBxfap3dUu8M1TXgnNDmeBj55zrbhc23h2TEDH8dApBFpl0Oqi0RA7RJ4+kCIZS5Zdvv/nYjo+BECHzBt0ML+UFj/nk= Received: from AS9PR06CA0351.eurprd06.prod.outlook.com (2603:10a6:20b:466::17) by AM8PR08MB5794.eurprd08.prod.outlook.com (2603:10a6:20b:1d6::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.17; Tue, 12 Jul 2022 14:32:05 +0000 Received: from AM5EUR03FT037.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:466:cafe::14) by AS9PR06CA0351.outlook.office365.com (2603:10a6:20b:466::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.15 via Frontend Transport; Tue, 12 Jul 2022 14:32:05 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM5EUR03FT037.mail.protection.outlook.com (10.152.17.241) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.15 via Frontend Transport; Tue, 12 Jul 2022 14:32:05 +0000 Received: ("Tessian outbound f9f15f9daab2:v122"); Tue, 12 Jul 2022 14:32:05 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 3ef5491bcff78f3c X-CR-MTA-TID: 64aa7808 Received: from 22b7ceb9d243.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id FDD7C888-DC05-4F50-8282-4726DFCB108C.1; Tue, 12 Jul 2022 14:31:57 +0000 Received: from EUR01-DB5-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 22b7ceb9d243.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Tue, 12 Jul 2022 14:31:57 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=IDqFGBUnVvQ+dchSm8XoBiYH6vbFpFdTKfrHm4wa7FrpTE1ztFzJ+WtkhiobZrtdPFg0RxVOzoyjoS51H3akWBCfNygIUKu/bGlOdLI0bU1n79NyMAxovi1udMc0PuQFkzfKpxt+pe0Der2qJKun/wN1CrVlL2KXEiZ/f1WIHys6+WP6dFHLGXMO9it50Q7AVSudDpU41xs1g8qGJCI5dTbuZz0mJWDBdgH9VfBPfKOCSFDwxRlLbiEuAJEK+n8sq2zJoqzMe/D9a7/1FlonoOOn1dlAU/p9LoB1ud2c0+O5bMDooCoIU+HrbzqQp5W9UVohbn2a+IOdRB8zMEq+Ig== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Xl3VXFCg9BxNjat0H1S+/SkFo2L8/f31rbXkyqCBBnw=; b=Y8RlkLqMYI8YOQ1RtC9v3mSFo3ECIQNkzkO9qPGWtGIbvEyH9aZ5uNBvne5EvrTr0Bb9fWOTfx3BEe1c1Ta6HinxwRLO0d2uVcWNKneQe9LoByuEy0AzBuoe8139yzhgMLqaSTeQneF6fICbQmrc62xfrkdObP7hjznQi98Ea5kY3HBBbanXBCj6YKCoo0uW7mkUifz7f8rPD/eVn5Y/H1wMKwReRMhV7X9AfhpzLWc7V/J6e3SXCQQpjDpCMM0wWdCvkcRcs+ns8zixtXhaPmgROIqfWdwxpAv+kyyLZFJ3b7Ah4x7gwaSPSz6QtpiaFfSQ6PrgiMEke0LuuLWsQA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=edk2.groups.io smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector2-armh-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Xl3VXFCg9BxNjat0H1S+/SkFo2L8/f31rbXkyqCBBnw=; b=pBir0YRhtVIkZa68Yjf+JpLN4aohjuuo8tyHc2He53nZWBfa915r4PFk/UKY9uZxJnnchpvekA9pchs5VBxfap3dUu8M1TXgnNDmeBj55zrbhc23h2TEDH8dApBFpl0Oqi0RA7RJ4+kCIZS5Zdvv/nYjo+BECHzBt0ML+UFj/nk= Received: from AS9PR04CA0152.eurprd04.prod.outlook.com (2603:10a6:20b:48a::26) by HE1PR0801MB1737.eurprd08.prod.outlook.com (2603:10a6:3:81::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.20; Tue, 12 Jul 2022 14:31:50 +0000 Received: from AM5EUR03FT049.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:48a:cafe::69) by AS9PR04CA0152.outlook.office365.com (2603:10a6:20b:48a::26) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5417.26 via Frontend Transport; Tue, 12 Jul 2022 14:31:50 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; pr=C Received: from nebula.arm.com (40.67.248.234) by AM5EUR03FT049.mail.protection.outlook.com (10.152.17.130) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5417.15 via Frontend Transport; Tue, 12 Jul 2022 14:31:50 +0000 Received: from AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.2507.9; Tue, 12 Jul 2022 14:31:49 +0000 Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX01.Emea.Arm.com (10.251.26.4) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.2507.9; Tue, 12 Jul 2022 14:31:47 +0000 Received: from E114225.Arm.com (10.1.196.36) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2507.9 via Frontend Transport; Tue, 12 Jul 2022 14:31:47 +0000 From: "Sami Mujawar" To: CC: Sami Mujawar , , , , , , , , Subject: [PATCH v5 8/8] DynamicTablesPkg: IORT generator updates for Rev E.d spec Date: Tue, 12 Jul 2022 15:31:41 +0100 Message-ID: <20220712143141.18516-9-sami.mujawar@arm.com> X-Mailer: git-send-email 2.16.2.windows.1 In-Reply-To: <20220712143141.18516-1-sami.mujawar@arm.com> References: <20220712143141.18516-1-sami.mujawar@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-Correlation-Id: 271bdb91-33f3-4df1-b605-08da64134b29 X-MS-TrafficTypeDiagnostic: HE1PR0801MB1737:EE_|AM5EUR03FT037:EE_|AM8PR08MB5794:EE_ x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: xANSmRVm82WQDLrfJTg4tIvvKKN9miaRTbp+XbTC+vH4Q9J9LoTINqjb5DBwDvvwcyS+eNbFKkY/dvTEPZOcNw7ecz9bh7qKJk6VPq8wSG7APmLSzo9z8mJeuvem4z0vWhJXOboEPalynSj33ybeHb4nQJzJoyfpeyo19+bXkthksfdb50nCw/soAdd1lOkMpOyIi8ouZ2J3G47IEFpM2j0cQzNlMn+clq+VrQ0OnL2Ii8s8Vbwhst+hGpiXwk/v5dyy7H4v6QALlhJLxDHoOWr0YI206NOv5L0dauIOFsp5ldU4QgFmzfZseYp2WSBlwPTDNPClgQhmBFmbce9MY/MOhsjQ3L4PuLAZD0tBCihxkNIOgpDSiglh+1bY4lGMF0nzmes6+MaEjQfG2KNqImMAOHZO+KGsM+YtFCV5Wbg6i2xJEUi8HCKdW0JKq8mycrHHu73Wje28Ido7+HCnSY49TLKnETUjHusH3BTrSXMvarEV7ifCYUTIYn/Y0UJqSG0VeY2hJRUe/bQk2FvavmPxQkBOIJ3FuA2C+kcvtA39CnSxDgzm6+3Pc28EfsPxcc8Ee5joxzhEYNlm2zTRAdH6RyqxKNhVJePvlvVmV/0knZ6GNvys3GKFKutCFe+wyq4Q0krOuNmStgvtnbHJSfr1XI33PuhZs0zNRRq7Q2xgl2sfeyyBRykvhLACuajn63SWh3W90Bbs346eQpYFhJet8cnu8Boe6vgILY/NpwcT2r+v0KUA4XFVlui1Vj9vv5LhVpvNpWRXkrpw0z4e5CtCiMaUWxnADlLtS749vW19J4uOGmh6m8MuLo3tfnU55CDtFHdY6Hzx31/qq4vjBei3HfdWewRg2SwnSKeWhRa/DRax7/nLrAbrljgw8rFEkgirn+ZKcv4TZqmCslsPVNCyQOq/oIunsv+Yh3Z6SVI= X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:nebula.arm.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230016)(4636009)(376002)(346002)(396003)(39860400002)(136003)(36840700001)(46966006)(40470700004)(70206006)(40460700003)(82310400005)(2906002)(19627235002)(7696005)(316002)(47076005)(478600001)(426003)(186003)(2616005)(26005)(86362001)(70586007)(336012)(8676002)(966005)(1076003)(5660300002)(82740400003)(83380400001)(81166007)(8936002)(36756003)(44832011)(6916009)(40480700001)(356005)(36860700001)(6666004)(30864003)(41300700001)(54906003)(15650500001)(4326008)(36900700001)(579004);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0801MB1737 Return-Path: Sami.Mujawar@arm.com X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM5EUR03FT037.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: acad11f0-3a20-48e5-f993-08da6413421f X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: +NtHwivgZJr1MQq8dvXD+kO9rllLSGOBuALJuQFN4BUwyPVVnr39GxF9/0j7LaFsj/QoC8Gl+B4KrebMgfGSe4y7uAr2s+nZwYQ8drwRFSIJZCif8v0142aroaspG/HGEIluEOBI5Wj0rtHWddKCT+78ogEiHP1VbObvxEmArOAVMOxZl5D6DfGP5dUpi2fZ9dXRQvkKWxLWitC9ccNWv10D1izSIi4mm+StMY6VMhEqCPTgYw0lQGAHF6gObp23HLz66bZLatywzupg54i5K3d1Nlw+a8h+HZC+RrMkMONXm/Kjnjn6e7eiB2+MRr6LVISdq/K1Wbd9OtzLky6t0Y3KYxVW1zRESGJ0YYtMcpqTxoKOefqDw3p44g/qJkE1p7xPjl4Zxn5QG2gEpFlbx48hZBkUS9zXzAw2fIg53sQwgbKzV6vQFOcxE86KLH/o1+0Dr/AvY4eycEXaWI9vWZw5mbgWCPz+hwmphUfGjohsT7zGDIzDRlrcKvCiah2eKoMSyuweWNRKQa5HyXgUfBZ2Ba/6k6tUkFNAOZDIq9sFbPPiUGXfvMZJDQGdO0vCAsjlHpTVPhJN4ydK1kYtwueI/faeBzSbxybjYiW65+F5WIC3R9w+0oGs3o5cNaUA5A/BT77VwLITAqNyTP7lXMULExUIKh4fo/uUw5g/STZnwV22CVrM6CpaudNoF+zhXCA9G3Hrl3Ty23kXRzI/b5Gt9Q0H908NKUMNMCqH9agyPHQZFhgfqh25mUg+uGlArmTgyEG0ps/Jy1QVWY8oYQufxIT9aBNT9YFatlyVL47xglXJrhdfL6hGuz8NW6gz0q1LpFE1/2a9FZkH43lzGnlhR6jKG/j7rq6qihLWyZrgcd1M72kmLKvG3m2DUY/g X-Forefront-Antispam-Report: CIP:63.35.35.123;CTRY:IE;LANG:en;SCL:1;SRV:;IPV:CAL;SFV:NSPM;H:64aa7808-outbound-1.mta.getcheckrecipient.com;PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com;CAT:NONE;SFS:(13230016)(4636009)(396003)(376002)(346002)(136003)(39860400002)(46966006)(40470700004)(36840700001)(8936002)(5660300002)(26005)(40460700003)(40480700001)(82310400005)(36860700001)(7696005)(15650500001)(30864003)(44832011)(82740400003)(2906002)(83380400001)(966005)(47076005)(81166007)(36756003)(19627235002)(86362001)(478600001)(6916009)(70206006)(54906003)(41300700001)(186003)(426003)(70586007)(316002)(8676002)(4326008)(1076003)(336012)(6666004)(2616005)(579004);DIR:OUT;SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Jul 2022 14:32:05.3746 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 271bdb91-33f3-4df1-b605-08da64134b29 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d;Ip=[63.35.35.123];Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: AM5EUR03FT037.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM8PR08MB5794 Content-Type: text/plain Bugzilla: 3458 - Add support IORT Rev E.d specification updates (https://bugzilla.tianocore.org/show_bug.cgi?id=3458) The IO Remapping Table, Platform Design Document, Revision E.d, Feb 2022 (https://developer.arm.com/documentation/den0049/) introduces the following updates, collectively including the updates and errata fixes to Rev E, Rev E.a, Rev E.b, Rev E.c: - increments the IORT table revision to 5. - updates the node definition to add an 'Identifier' field. - adds definition of node type 6 - Reserved Memory Range node. - adds definition for Memory Range Descriptors. - adds flag to indicate PRI support for root complexes. - adds flag to indicate if the root complex supports forwarding of PASID information on translated transactions to the SMMU. - adds flag to indicate if the root complex supports PASID. - adds flags to define access privilege and attributes for the memory ranges. Therefore, update the IORT generator to: - increment IORT table revision count to 5. - populate Identifier filed if revision is greater than 4. - add support to populate Reserved Memory Range nodes and the Memory range descriptors. - add validation to check that the Identifier field is unique. - Populate the PASID capabilities and Flags field of the Root complex node. Signed-off-by: Sami Mujawar --- Notes: v5: - Change IORT revision macro name to make it similar to [THOMAS] macro names for other ACPI tables. - Updated IORT revision macros from [SAMI] EFI_ACPI_IO_REMAPPING_TABLE_REVx to EFI_ACPI_IO_REMAPPING_TABLE_REVISION_0x Ref: https://edk2.groups.io/g/devel/message/91119 - Minor updates initialise RcNode.PasidCapabilities in [SAMI] case of EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00 so that backward compatibility is maintained. v4: - Update IORT generator to support spec revision E.d [SAMI] - Populate the PASID capabilities and Flags field of the [SAMI] Root complex node. v3: - Move error handling for IdMappingToken. [PIERRE] - Moved error handling for IdMappingToken in a separate [SAMI] patch in v3 series. Ref: https://edk2.groups.io/g/devel/topic/83600726#76661 v2: - The macro EFI_ACPI_IO_REMAPPING_TABLE_REVISION was set to [SAMI] Rev 0 as setting to Rev 3 will break existing platforms. Therefore, set the max supported IORT generator revision to 3. DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c | 645 ++++++++++++++++++-- DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h | 5 +- 2 files changed, 600 insertions(+), 50 deletions(-) diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c index 63381441e2d6515a7cc9731c89b9739a12c65599..34521316fc8912db7d51444245b18bc51fe9370a 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c @@ -5,8 +5,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent @par Reference(s): - - IO Remapping Table, Platform Design Document, - Document number: ARM DEN 0049D, Issue D, March 2018 + - IO Remapping Table, Platform Design Document, Revision E.d, Feb 2022 + (https://developer.arm.com/documentation/den0049/) **/ @@ -37,9 +37,11 @@ Requirements: - EArmObjSmmuV1SmmuV2 - EArmObjSmmuV3 - EArmObjPmcg + - EArmObjRmr - EArmObjGicItsIdentifierArray - EArmObjIdMappingArray - - EArmObjGicItsIdentifierArray + - EArmObjSmmuInterruptArray + - EArmObjMemoryRangeDescriptor */ /** This macro expands to a function that retrieves the ITS @@ -96,6 +98,24 @@ GET_OBJECT_LIST ( CM_ARM_PMCG_NODE ); +/** This macro expands to a function that retrieves the + RMR node information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjRmr, + CM_ARM_RMR_NODE + ); + +/** This macro expands to a function that retrieves the + Memory Range Descriptor Array information from the Configuration Manager. +*/ +GET_OBJECT_LIST ( + EObjNameSpaceArm, + EArmObjMemoryRangeDescriptor, + CM_ARM_MEMORY_RANGE_DESCRIPTOR + ); + /** This macro expands to a function that retrieves the ITS Identifier Array information from the Configuration Manager. */ @@ -174,16 +194,19 @@ GetSizeofItsGroupNodes ( Size = 0; while (NodeCount-- != 0) { - (*NodeIndexer)->Token = NodeList->Token; - (*NodeIndexer)->Object = (VOID *)NodeList; - (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Identifier = NodeList->Identifier; DEBUG (( DEBUG_INFO, - "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", + "IORT: Node Indexer = %p, Token = %p, Object = %p," + " Offset = 0x%x, Identifier = 0x%x\n", *NodeIndexer, (*NodeIndexer)->Token, (*NodeIndexer)->Object, - (*NodeIndexer)->Offset + (*NodeIndexer)->Offset, + (*NodeIndexer)->Identifier )); Size += GetItsGroupNodeSize (NodeList); @@ -248,16 +271,19 @@ GetSizeofNamedComponentNodes ( Size = 0; while (NodeCount-- != 0) { - (*NodeIndexer)->Token = NodeList->Token; - (*NodeIndexer)->Object = (VOID *)NodeList; - (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Identifier = NodeList->Identifier; DEBUG (( DEBUG_INFO, - "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", + "IORT: Node Indexer = %p, Token = %p, Object = %p," + " Offset = 0x%x, Identifier = 0x%x\n", *NodeIndexer, (*NodeIndexer)->Token, (*NodeIndexer)->Object, - (*NodeIndexer)->Offset + (*NodeIndexer)->Offset, + (*NodeIndexer)->Identifier )); Size += GetNamedComponentNodeSize (NodeList); @@ -320,16 +346,19 @@ GetSizeofRootComplexNodes ( Size = 0; while (NodeCount-- != 0) { - (*NodeIndexer)->Token = NodeList->Token; - (*NodeIndexer)->Object = (VOID *)NodeList; - (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Identifier = NodeList->Identifier; DEBUG (( DEBUG_INFO, - "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", + "IORT: Node Indexer = %p, Token = %p, Object = %p," + " Offset = 0x%x, Identifier = 0x%x\n", *NodeIndexer, (*NodeIndexer)->Token, (*NodeIndexer)->Object, - (*NodeIndexer)->Offset + (*NodeIndexer)->Offset, + (*NodeIndexer)->Identifier )); Size += GetRootComplexNodeSize (NodeList); @@ -398,16 +427,19 @@ GetSizeofSmmuV1V2Nodes ( Size = 0; while (NodeCount-- != 0) { - (*NodeIndexer)->Token = NodeList->Token; - (*NodeIndexer)->Object = (VOID *)NodeList; - (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Identifier = NodeList->Identifier; DEBUG (( DEBUG_INFO, - "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", + "IORT: Node Indexer = %p, Token = %p, Object = %p," + " Offset = 0x%x, Identifier = 0x%x\n", *NodeIndexer, (*NodeIndexer)->Token, (*NodeIndexer)->Object, - (*NodeIndexer)->Offset + (*NodeIndexer)->Offset, + (*NodeIndexer)->Identifier )); Size += GetSmmuV1V2NodeSize (NodeList); @@ -470,16 +502,19 @@ GetSizeofSmmuV3Nodes ( Size = 0; while (NodeCount-- != 0) { - (*NodeIndexer)->Token = NodeList->Token; - (*NodeIndexer)->Object = (VOID *)NodeList; - (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Identifier = NodeList->Identifier; DEBUG (( DEBUG_INFO, - "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", + "IORT: Node Indexer = %p, Token = %p, Object = %p," + " Offset = 0x%x, Identifier = 0x%x\n", *NodeIndexer, (*NodeIndexer)->Token, (*NodeIndexer)->Object, - (*NodeIndexer)->Offset + (*NodeIndexer)->Offset, + (*NodeIndexer)->Identifier )); Size += GetSmmuV3NodeSize (NodeList); @@ -542,16 +577,19 @@ GetSizeofPmcgNodes ( Size = 0; while (NodeCount-- != 0) { - (*NodeIndexer)->Token = NodeList->Token; - (*NodeIndexer)->Object = (VOID *)NodeList; - (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Identifier = NodeList->Identifier; DEBUG (( DEBUG_INFO, - "IORT: Node Indexer = %p, Token = %p, Object = %p, Offset = 0x%x\n", + "IORT: Node Indexer = %p, Token = %p, Object = %p," + " Offset = 0x%x, Identifier = 0x%x\n", *NodeIndexer, (*NodeIndexer)->Token, (*NodeIndexer)->Object, - (*NodeIndexer)->Offset + (*NodeIndexer)->Offset, + (*NodeIndexer)->Identifier )); Size += GetPmcgNodeSize (NodeList); @@ -562,6 +600,84 @@ GetSizeofPmcgNodes ( return Size; } +/** Returns the size of the RMR node. + + @param [in] Node Pointer to RMR node. + + @retval Size of the RMR node. +**/ +STATIC +UINT32 +GetRmrNodeSize ( + IN CONST CM_ARM_RMR_NODE *Node + ) +{ + ASSERT (Node != NULL); + + /* Size of RMR node + + Size of ID mapping array + + Size of Memory Range Descriptor array + */ + return (UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE) + + (Node->IdMappingCount * + sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE)) + + (Node->MemRangeDescCount * + sizeof (EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC))); +} + +/** Returns the total size required for the RMR nodes and + updates the Node Indexer. + + This function calculates the size required for the node group + and also populates the Node Indexer array with offsets for the + individual nodes. + + @param [in] NodeStartOffset Offset from the start of the + IORT where this node group starts. + @param [in] NodeList Pointer to RMR node list. + @param [in] NodeCount Count of the RMR nodes. + @param [in, out] NodeIndexer Pointer to the next Node Indexer. + + @retval Total size of the RMR nodes. +**/ +STATIC +UINT64 +GetSizeofRmrNodes ( + IN CONST UINT32 NodeStartOffset, + IN CONST CM_ARM_RMR_NODE *NodeList, + IN UINT32 NodeCount, + IN OUT IORT_NODE_INDEXER **CONST NodeIndexer + ) +{ + UINT64 Size; + + ASSERT (NodeList != NULL); + + Size = 0; + while (NodeCount-- != 0) { + (*NodeIndexer)->Token = NodeList->Token; + (*NodeIndexer)->Object = (VOID *)NodeList; + (*NodeIndexer)->Offset = (UINT32)(Size + NodeStartOffset); + (*NodeIndexer)->Identifier = NodeList->Identifier; + DEBUG (( + DEBUG_INFO, + "IORT: Node Indexer = %p, Token = %p, Object = %p," + " Offset = 0x%x, Identifier = 0x%x\n", + *NodeIndexer, + (*NodeIndexer)->Token, + (*NodeIndexer)->Object, + (*NodeIndexer)->Offset, + (*NodeIndexer)->Identifier + )); + + Size += GetRmrNodeSize (NodeList); + (*NodeIndexer)++; + NodeList++; + } + + return Size; +} + /** Returns the offset of the Node referenced by the Token. @param [in] NodeIndexer Pointer to node indexer array. @@ -713,6 +829,7 @@ AddIdMappingArray ( @param [in] This Pointer to the table Generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol Interface. + @param [in] AcpiTableInfo Pointer to the ACPI table info structure. @param [in] Iort Pointer to IORT table structure. @param [in] NodesStartOffset Offset for the start of the ITS Group Nodes. @@ -729,6 +846,7 @@ EFI_STATUS AddItsGroupNodes ( IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_ITS_GROUP_NODE *NodeList, @@ -765,11 +883,19 @@ AddItsGroupNodes ( // Populate the node header ItsGroupNode->Node.Type = EFI_ACPI_IORT_TYPE_ITS_GROUP; ItsGroupNode->Node.Length = (UINT16)NodeLength; - ItsGroupNode->Node.Revision = 0; - ItsGroupNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; ItsGroupNode->Node.NumIdMappings = 0; ItsGroupNode->Node.IdReference = 0; + if (AcpiTableInfo->AcpiTableRevision < + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + ItsGroupNode->Node.Revision = 0; + ItsGroupNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; + } else { + ItsGroupNode->Node.Revision = 1; + ItsGroupNode->Node.Identifier = NodeList->Identifier; + } + // IORT specific data ItsGroupNode->NumItsIdentifiers = NodeList->ItsIdCount; ItsIds = (UINT32 *)((UINT8 *)ItsGroupNode + @@ -820,6 +946,7 @@ AddItsGroupNodes ( @param [in] This Pointer to the table Generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol Interface. + @param [in] AcpiTableInfo Pointer to the ACPI table info structure. @param [in] Iort Pointer to IORT table structure. @param [in] NodesStartOffset Offset for the start of the Named Component Nodes. @@ -836,6 +963,7 @@ EFI_STATUS AddNamedComponentNodes ( IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_NAMED_COMPONENT_NODE *NodeList, @@ -871,10 +999,18 @@ AddNamedComponentNodes ( // Populate the node header NcNode->Node.Type = EFI_ACPI_IORT_TYPE_NAMED_COMP; NcNode->Node.Length = (UINT16)NodeLength; - NcNode->Node.Revision = 2; - NcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; NcNode->Node.NumIdMappings = NodeList->IdMappingCount; + if (AcpiTableInfo->AcpiTableRevision < + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + NcNode->Node.Revision = 2; + NcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; + } else { + NcNode->Node.Revision = 4; + NcNode->Node.Identifier = NodeList->Identifier; + } + ObjectNameLength = AsciiStrLen (NodeList->ObjectName) + 1; NcNode->Node.IdReference = (NodeList->IdMappingCount == 0) ? 0 : ((UINT32)(sizeof (EFI_ACPI_6_0_IO_REMAPPING_NAMED_COMP_NODE) + @@ -955,6 +1091,7 @@ AddNamedComponentNodes ( @param [in] This Pointer to the table Generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol Interface. + @param [in] AcpiTableInfo Pointer to the ACPI table info structure. @param [in] Iort Pointer to IORT table structure. @param [in] NodesStartOffset Offset for the start of the Root Complex Nodes. @@ -971,6 +1108,7 @@ EFI_STATUS AddRootComplexNodes ( IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_ROOT_COMPLEX_NODE *NodeList, @@ -1004,12 +1142,23 @@ AddRootComplexNodes ( // Populate the node header RcNode->Node.Type = EFI_ACPI_IORT_TYPE_ROOT_COMPLEX; RcNode->Node.Length = (UINT16)NodeLength; - RcNode->Node.Revision = 1; - RcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; RcNode->Node.NumIdMappings = NodeList->IdMappingCount; RcNode->Node.IdReference = (NodeList->IdMappingCount == 0) ? 0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_RC_NODE); + if (AcpiTableInfo->AcpiTableRevision < + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + RcNode->Node.Revision = 1; + RcNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; + RcNode->PasidCapabilities = EFI_ACPI_RESERVED_WORD; + } else { + RcNode->Node.Revision = 4; + RcNode->Node.Identifier = NodeList->Identifier; + RcNode->PasidCapabilities = NodeList->PasidCapabilities; + RcNode->Flags = NodeList->Flags; + } + // Root Complex specific data RcNode->CacheCoherent = NodeList->CacheCoherent; RcNode->AllocationHints = NodeList->AllocationHints; @@ -1018,7 +1167,6 @@ AddRootComplexNodes ( RcNode->AtsAttribute = NodeList->AtsAttribute; RcNode->PciSegmentNumber = NodeList->PciSegmentNumber; RcNode->MemoryAddressSize = NodeList->MemoryAddressSize; - RcNode->PasidCapabilities = EFI_ACPI_RESERVED_WORD; RcNode->Reserved1[0] = EFI_ACPI_RESERVED_BYTE; if (NodeList->IdMappingCount > 0) { @@ -1134,6 +1282,7 @@ AddSmmuInterruptArray ( @param [in] This Pointer to the table Generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol Interface. + @param [in] AcpiTableInfo Pointer to the ACPI table info structure. @param [in] Iort Pointer to IORT table structure. @param [in] NodesStartOffset Offset for the start of the SMMU v1/v2 Nodes. @@ -1150,6 +1299,7 @@ EFI_STATUS AddSmmuV1V2Nodes ( IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_SMMUV1_SMMUV2_NODE *NodeList, @@ -1186,8 +1336,6 @@ AddSmmuV1V2Nodes ( // Populate the node header SmmuNode->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv1v2; SmmuNode->Node.Length = (UINT16)NodeLength; - SmmuNode->Node.Revision = 0; - SmmuNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; SmmuNode->Node.NumIdMappings = NodeList->IdMappingCount; SmmuNode->Node.IdReference = (NodeList->IdMappingCount == 0) ? 0 : (sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_NODE) + @@ -1196,6 +1344,16 @@ AddSmmuV1V2Nodes ( (NodeList->PmuInterruptCount * sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT))); + if (AcpiTableInfo->AcpiTableRevision < + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + SmmuNode->Node.Revision = 1; + SmmuNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; + } else { + SmmuNode->Node.Revision = 3; + SmmuNode->Node.Identifier = NodeList->Identifier; + } + // SMMU v1/v2 specific data SmmuNode->Base = NodeList->BaseAddress; SmmuNode->Span = NodeList->Span; @@ -1339,6 +1497,7 @@ AddSmmuV1V2Nodes ( @param [in] This Pointer to the table Generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol Interface. + @param [in] AcpiTableInfo Pointer to the ACPI table info structure. @param [in] Iort Pointer to IORT table structure. @param [in] NodesStartOffset Offset for the start of the SMMUv3 Nodes. @param [in] NodeList Pointer to an array of SMMUv3 Node Objects. @@ -1353,6 +1512,7 @@ EFI_STATUS AddSmmuV3Nodes ( IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_SMMUV3_NODE *NodeList, @@ -1385,12 +1545,20 @@ AddSmmuV3Nodes ( // Populate the node header SmmuV3Node->Node.Type = EFI_ACPI_IORT_TYPE_SMMUv3; SmmuV3Node->Node.Length = (UINT16)NodeLength; - SmmuV3Node->Node.Revision = 2; - SmmuV3Node->Node.Identifier = EFI_ACPI_RESERVED_DWORD; SmmuV3Node->Node.NumIdMappings = NodeList->IdMappingCount; SmmuV3Node->Node.IdReference = (NodeList->IdMappingCount == 0) ? 0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_SMMU3_NODE); + if (AcpiTableInfo->AcpiTableRevision < + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + SmmuV3Node->Node.Revision = 2; + SmmuV3Node->Node.Identifier = EFI_ACPI_RESERVED_DWORD; + } else { + SmmuV3Node->Node.Revision = 4; + SmmuV3Node->Node.Identifier = NodeList->Identifier; + } + // SMMUv3 specific data SmmuV3Node->Base = NodeList->BaseAddress; SmmuV3Node->Flags = NodeList->Flags; @@ -1468,6 +1636,7 @@ AddSmmuV3Nodes ( @param [in] This Pointer to the table Generator. @param [in] CfgMgrProtocol Pointer to the Configuration Manager Protocol Interface. + @param [in] AcpiTableInfo Pointer to the ACPI table info structure. @param [in] Iort Pointer to IORT table structure. @param [in] NodesStartOffset Offset for the start of the PMCG Nodes. @param [in] NodeList Pointer to an array of PMCG Node Objects. @@ -1482,6 +1651,7 @@ EFI_STATUS AddPmcgNodes ( IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, IN CONST UINT32 NodesStartOffset, IN CONST CM_ARM_PMCG_NODE *NodeList, @@ -1516,12 +1686,20 @@ AddPmcgNodes ( // Populate the node header PmcgNode->Node.Type = EFI_ACPI_IORT_TYPE_PMCG; PmcgNode->Node.Length = (UINT16)NodeLength; - PmcgNode->Node.Revision = 1; - PmcgNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; PmcgNode->Node.NumIdMappings = NodeList->IdMappingCount; PmcgNode->Node.IdReference = (NodeList->IdMappingCount == 0) ? 0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_PMCG_NODE); + if (AcpiTableInfo->AcpiTableRevision < + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + PmcgNode->Node.Revision = 1; + PmcgNode->Node.Identifier = EFI_ACPI_RESERVED_DWORD; + } else { + PmcgNode->Node.Revision = 2; + PmcgNode->Node.Identifier = NodeList->Identifier; + } + // PMCG specific data PmcgNode->Base = NodeList->BaseAddress; PmcgNode->OverflowInterruptGsiv = NodeList->OverflowInterrupt; @@ -1588,6 +1766,274 @@ AddPmcgNodes ( return EFI_SUCCESS; } +/** Update the Memory Range Descriptor Array. + + This function retrieves the Memory Range Descriptor objects referenced by + MemRangeDescToken and updates the Memory Range Descriptor array. + + @param [in] This Pointer to the table Generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] DescArray Pointer to an array of Memory Range + Descriptors. + @param [in] DescCount Number of Id Descriptors. + @param [in] DescToken Reference Token for retrieving the + Memory Range Descriptor Array. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. +**/ +STATIC +EFI_STATUS +AddMemRangeDescArray ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *DescArray, + IN UINT32 DescCount, + IN CONST CM_OBJECT_TOKEN DescToken + ) +{ + EFI_STATUS Status; + CM_ARM_MEMORY_RANGE_DESCRIPTOR *MemRangeDesc; + UINT32 MemRangeDescCount; + + ASSERT (DescArray != NULL); + + // Get the Id Mapping Array + Status = GetEArmObjMemoryRangeDescriptor ( + CfgMgrProtocol, + DescToken, + &MemRangeDesc, + &MemRangeDescCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Failed to get Memory Range Descriptor array. Status = %r\n", + Status + )); + return Status; + } + + if (MemRangeDescCount < DescCount) { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Failed to get the required number of Memory" + " Range Descriptors.\n" + )); + return EFI_NOT_FOUND; + } + + // Populate the Memory Range Descriptor array + while (DescCount-- != 0) { + DescArray->Base = MemRangeDesc->BaseAddress; + DescArray->Length = MemRangeDesc->Length; + DescArray->Reserved = EFI_ACPI_RESERVED_DWORD; + + DescArray++; + MemRangeDesc++; + } + + return EFI_SUCCESS; +} + +/** Update the RMR Node Information. + + This function updates the RMR node information in the IORT table. + + @param [in] This Pointer to the table Generator. + @param [in] CfgMgrProtocol Pointer to the Configuration Manager + Protocol Interface. + @param [in] AcpiTableInfo Pointer to the ACPI table info structure. + @param [in] Iort Pointer to IORT table structure. + @param [in] NodesStartOffset Offset for the start of the PMCG Nodes. + @param [in] NodeList Pointer to an array of PMCG Node Objects. + @param [in] NodeCount Number of PMCG Node Objects. + + @retval EFI_SUCCESS Table generated successfully. + @retval EFI_INVALID_PARAMETER A parameter is invalid. + @retval EFI_NOT_FOUND The required object was not found. +**/ +STATIC +EFI_STATUS +AddRmrNodes ( + IN CONST ACPI_TABLE_GENERATOR *CONST This, + IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, + IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, + IN CONST EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort, + IN CONST UINT32 NodesStartOffset, + IN CONST CM_ARM_RMR_NODE *NodeList, + IN UINT32 NodeCount + ) +{ + EFI_STATUS Status; + EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *RmrNode; + EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *IdMapArray; + EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *MemRangeDescArray; + UINT64 NodeLength; + + ASSERT (Iort != NULL); + + RmrNode = (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *)((UINT8 *)Iort + + NodesStartOffset); + + while (NodeCount-- != 0) { + NodeLength = GetRmrNodeSize (NodeList); + if (NodeLength > MAX_UINT16) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: RMR Node length 0x%lx > MAX_UINT16. Status = %r\n", + NodeLength, + Status + )); + return Status; + } + + if (NodeList->MemRangeDescCount == 0) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Memory Range Desc count = %d. Status = %r\n", + NodeList->MemRangeDescCount, + Status + )); + return Status; + } + + if (NodeList->MemRangeDescToken == CM_NULL_TOKEN) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Invalid Memory Range Descriptor token," + " Token = 0x%x. Status = %r\n", + NodeList->MemRangeDescToken, + Status + )); + return Status; + } + + // Populate the node header + RmrNode->Node.Type = EFI_ACPI_IORT_TYPE_RMR; + RmrNode->Node.Length = (UINT16)NodeLength; + RmrNode->Node.Revision = 3; + RmrNode->Node.Identifier = NodeList->Identifier; + RmrNode->Node.NumIdMappings = NodeList->IdMappingCount; + RmrNode->Node.IdReference = (NodeList->IdMappingCount == 0) ? + 0 : sizeof (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE); + + // RMR specific data + RmrNode->Flags = NodeList->Flags; + RmrNode->NumMemRangeDesc = NodeList->MemRangeDescCount; + RmrNode->MemRangeDescRef = (NodeList->MemRangeDescCount == 0) ? + 0 : (sizeof (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE) + + (NodeList->IdMappingCount * + sizeof (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE))); + + if (NodeList->IdMappingCount > 0) { + if (NodeList->IdMappingToken == CM_NULL_TOKEN) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Invalid Id Mapping token," + " Token = 0x%x, Status =%r\n", + NodeList->IdMappingToken, + Status + )); + return Status; + } + + // Ids for RMR node + IdMapArray = (EFI_ACPI_6_0_IO_REMAPPING_ID_TABLE *)((UINT8 *)RmrNode + + RmrNode->Node.IdReference); + + Status = AddIdMappingArray ( + This, + CfgMgrProtocol, + IdMapArray, + NodeList->IdMappingCount, + NodeList->IdMappingToken + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Failed to add Id Mapping Array. Status = %r\n", + Status + )); + return Status; + } + } + + // Memory Range Descriptors for RMR node + MemRangeDescArray = (EFI_ACPI_6_0_IO_REMAPPING_MEM_RANGE_DESC *)( + (UINT8 *)RmrNode + + RmrNode->MemRangeDescRef + ); + + Status = AddMemRangeDescArray ( + This, + CfgMgrProtocol, + MemRangeDescArray, + NodeList->MemRangeDescCount, + NodeList->MemRangeDescToken + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Failed to Memory Range Descriptor Array. Status = %r\n", + Status + )); + return Status; + } + + // Next RMR Node + RmrNode = (EFI_ACPI_6_0_IO_REMAPPING_RMR_NODE *)((UINT8 *)RmrNode + + RmrNode->Node.Length); + NodeList++; + } // RMR Node + + return EFI_SUCCESS; +} + +/** Validates that the IORT nodes Identifier are unique. + + @param [in] NodeIndexer Pointer to the Node Indexer. + @param [in] NodeCount Number of IORT Nodes. + + @retval EFI_SUCCESS Success. + @retval EFI_INVALID_PARAMETER Identifier field not unique. +**/ +STATIC +EFI_STATUS +ValidateNodeIdentifiers ( + IN CONST IORT_NODE_INDEXER *CONST NodeIndexer, + IN UINT32 NodeCount + ) +{ + UINT32 IndexI; + UINT32 IndexJ; + + for (IndexI = 0; IndexI < NodeCount; IndexI++) { + for (IndexJ = 0; IndexJ < NodeCount; IndexJ++) { + if ((IndexI != IndexJ) && + (NodeIndexer[IndexI].Identifier == NodeIndexer[IndexJ].Identifier)) + { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: UID %d of Token %p matches with that of Token %p.\n", + NodeIndexer[IndexI].Identifier, + NodeIndexer[IndexI].Token, + NodeIndexer[IndexJ].Token + )); + return EFI_INVALID_PARAMETER; + } + }// IndexJ + } // IndexI + + return EFI_SUCCESS; +} + /** Construct the IORT ACPI table. This function invokes the Configuration Manager protocol interface @@ -1632,6 +2078,7 @@ BuildIortTable ( UINT32 SmmuV1V2NodeCount; UINT32 SmmuV3NodeCount; UINT32 PmcgNodeCount; + UINT32 RmrNodeCount; UINT32 ItsGroupOffset; UINT32 NamedComponentOffset; @@ -1639,6 +2086,7 @@ BuildIortTable ( UINT32 SmmuV1V2Offset; UINT32 SmmuV3Offset; UINT32 PmcgOffset; + UINT32 RmrOffset; CM_ARM_ITS_GROUP_NODE *ItsGroupNodeList; CM_ARM_NAMED_COMPONENT_NODE *NamedComponentNodeList; @@ -1646,6 +2094,7 @@ BuildIortTable ( CM_ARM_SMMUV1_SMMUV2_NODE *SmmuV1V2NodeList; CM_ARM_SMMUV3_NODE *SmmuV3NodeList; CM_ARM_PMCG_NODE *PmcgNodeList; + CM_ARM_RMR_NODE *RmrNodeList; EFI_ACPI_6_0_IO_REMAPPING_TABLE *Iort; IORT_NODE_INDEXER *NodeIndexer; @@ -1789,6 +2238,29 @@ BuildIortTable ( // Add the PMCG node count IortNodeCount += PmcgNodeCount; + if (AcpiTableInfo->AcpiTableRevision >= + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + // Get the RMR node info + Status = GetEArmObjRmr ( + CfgMgrProtocol, + CM_NULL_TOKEN, + &RmrNodeList, + &RmrNodeCount + ); + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Failed to get RMR Node Info. Status = %r\n", + Status + )); + goto error_handler; + } + + // Add the RMR node count + IortNodeCount += RmrNodeCount; + } + // Allocate Node Indexer array NodeIndexer = (IORT_NODE_INDEXER *)AllocateZeroPool ( (sizeof (IORT_NODE_INDEXER) * @@ -1998,6 +2470,40 @@ BuildIortTable ( )); } + // RMR Nodes + if ((AcpiTableInfo->AcpiTableRevision >= + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) && + (RmrNodeCount > 0)) + { + RmrOffset = (UINT32)TableSize; + // Size of RMR node list. + NodeSize = GetSizeofRmrNodes ( + RmrOffset, + RmrNodeList, + RmrNodeCount, + &NodeIndexer + ); + if (NodeSize > MAX_UINT32) { + Status = EFI_INVALID_PARAMETER; + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Invalid Size of RMR Nodes. Status = %r\n", + Status + )); + goto error_handler; + } + + TableSize += NodeSize; + + DEBUG (( + DEBUG_INFO, + " RmrNodeCount = %d\n" \ + " RmrOffset = %d\n", + RmrNodeCount, + RmrOffset + )); + } + DEBUG (( DEBUG_INFO, "INFO: IORT:\n" \ @@ -2019,6 +2525,21 @@ BuildIortTable ( goto error_handler; } + // Validate that the identifiers for the nodes are unique + if (AcpiTableInfo->AcpiTableRevision >= + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05) + { + Status = ValidateNodeIdentifiers (Generator->NodeIndexer, IortNodeCount); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Node Identifier not unique. Status = %r\n", + Status + )); + goto error_handler; + } + } + // Allocate the Buffer for IORT table *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize); if (*Table == NULL) { @@ -2067,6 +2588,7 @@ BuildIortTable ( Status = AddItsGroupNodes ( This, CfgMgrProtocol, + AcpiTableInfo, Iort, ItsGroupOffset, ItsGroupNodeList, @@ -2086,6 +2608,7 @@ BuildIortTable ( Status = AddNamedComponentNodes ( This, CfgMgrProtocol, + AcpiTableInfo, Iort, NamedComponentOffset, NamedComponentNodeList, @@ -2105,6 +2628,7 @@ BuildIortTable ( Status = AddRootComplexNodes ( This, CfgMgrProtocol, + AcpiTableInfo, Iort, RootComplexOffset, RootComplexNodeList, @@ -2124,6 +2648,7 @@ BuildIortTable ( Status = AddSmmuV1V2Nodes ( This, CfgMgrProtocol, + AcpiTableInfo, Iort, SmmuV1V2Offset, SmmuV1V2NodeList, @@ -2143,6 +2668,7 @@ BuildIortTable ( Status = AddSmmuV3Nodes ( This, CfgMgrProtocol, + AcpiTableInfo, Iort, SmmuV3Offset, SmmuV3NodeList, @@ -2162,6 +2688,7 @@ BuildIortTable ( Status = AddPmcgNodes ( This, CfgMgrProtocol, + AcpiTableInfo, Iort, PmcgOffset, PmcgNodeList, @@ -2170,7 +2697,27 @@ BuildIortTable ( if (EFI_ERROR (Status)) { DEBUG (( DEBUG_ERROR, - "ERROR: IORT: Failed to add SMMUv3 Node. Status = %r\n", + "ERROR: IORT: Failed to add PMCG Node. Status = %r\n", + Status + )); + goto error_handler; + } + } + + if (RmrNodeCount > 0) { + Status = AddRmrNodes ( + This, + CfgMgrProtocol, + AcpiTableInfo, + Iort, + RmrOffset, + RmrNodeList, + RmrNodeCount + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: IORT: Failed to add RMR Node. Status = %r\n", Status )); goto error_handler; @@ -2255,9 +2802,9 @@ ACPI_IORT_GENERATOR IortGenerator = { // Generator Description L"ACPI.STD.IORT.GENERATOR", // ACPI Table Signature - EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE, + EFI_ACPI_6_4_IO_REMAPPING_TABLE_SIGNATURE, // ACPI Table Revision supported by this Generator - EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00, + EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05, // Minimum supported ACPI Table Revision EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00, // Creator ID diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h index 61f6b6153f207b356ed26aabf8366c1cf632fd90..99d86b3d167b56ae4e0c22d292e6e33318e3c78f 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.h @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2018, ARM Limited. All rights reserved. + Copyright (c) 2018 - 2022, Arm Limited. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -25,6 +25,9 @@ typedef struct IortNodeIndexer { VOID *Object; /// Node offset from the start of the IORT table UINT32 Offset; + + /// Unique identifier for the Node + UINT32 Identifier; } IORT_NODE_INDEXER; typedef struct AcpiIortGenerator { -- 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'