From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from EUR01-HE1-obe.outbound.protection.outlook.com (EUR01-HE1-obe.outbound.protection.outlook.com [40.107.13.50]) by mx.groups.io with SMTP id smtpd.web11.10744.1611767462166379624 for ; Wed, 27 Jan 2021 09:11:23 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@armh.onmicrosoft.com header.s=selector2-armh-onmicrosoft-com header.b=L5hKUov3; spf=pass (domain: arm.com, ip: 40.107.13.50, mailfrom: sami.mujawar@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=2JLbjLM++dufqW/lBnyeRSqblx0IEs4iJeIDY+yjcos=; b=L5hKUov3U8WTKm9npGbZrfx2ZG20nDAvrRnk070GHq/ON5kjvig6iY9x8VVTQhiCQDO+vAmC/ZM8sz3yudS7mzULNdTRUiSGBh3iv2PkZZwiSVSz5t7PG7RxfjJqC36FfzXcrGDvd6pbdRr/HbvpX7dQ3DlT2DIW+/gERShhlGw= Received: from AM5PR1001CA0019.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:206:2::32) by AM8PR08MB5763.eurprd08.prod.outlook.com (2603:10a6:20b:1d7::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3784.11; Wed, 27 Jan 2021 17:10:52 +0000 Received: from VE1EUR03FT007.eop-EUR03.prod.protection.outlook.com (2603:10a6:206:2:cafe::f0) by AM5PR1001CA0019.outlook.office365.com (2603:10a6:206:2::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3805.17 via Frontend Transport; Wed, 27 Jan 2021 17:10:52 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; edk2.groups.io; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;edk2.groups.io; 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; Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT007.mail.protection.outlook.com (10.152.18.114) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3784.11 via Frontend Transport; Wed, 27 Jan 2021 17:10:51 +0000 Received: ("Tessian outbound 2b57fdd78668:v71"); Wed, 27 Jan 2021 17:10:51 +0000 X-CR-MTA-TID: 64aa7808 Received: from 1bf2c98613b6.2 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 8E54E376-8EF0-4AE5-8F8C-A6CB6774A8B0.1; Wed, 27 Jan 2021 17:10:46 +0000 Received: from EUR04-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 1bf2c98613b6.2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Wed, 27 Jan 2021 17:10:46 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=jfWSCUuupreVkahBF3Z9XlEdZV6SXC9oqQ3JdEqOh0AzbXnoe8zXg5tuvqRZJcOrcDQWLLfFHfJcxF+7kY2YIpaZ7TmTCWm+sZJuu3Q5ahXS7uAyH4f7ghbjkmXEvsZBi74Md9hsI/KN6Cqm2SU7WjFx8Ufm2XkLZrdplqBj32DsxRiGmmXWyanWv1/DZF2/iBAQs41uZBVT1pAdMiQozAhujTufeQiKY5IsGORbyL3pwUpHYhjYU+ZWWaiJmxJvXzK8jgwn0roTb6JRq9i4YfT+xz8JG6fl4LoTT6xYJ7HWSGGvqa/nYosTu6hNE2tj2mGJPNrZCcWNpjZi+LhWXQ== 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=2JLbjLM++dufqW/lBnyeRSqblx0IEs4iJeIDY+yjcos=; b=FjpP6UJUtlNqTRUaTb3xQLc32JHTceOZAfIyFp8OYpI8TyAbd+wAUx/VrBTqYkgjtgwM5okZtIROZOYEXLGswu28xtBX1wZanc8nySpbVDc7rhH2yQm2hFNsNH3lt8+qjICbGWdcBbDhTjWhxFKMZpuI+A7RGgu1MpW4nbZaWTRw23P0v14udxh8SfBFR6PM9QsOpdZIFO2T7Dq9nEmPbaMAGJFr8MTEReBFRAIUuM3jaBOqbGZ4HbJaXnCUgRNZds9MrW8t0GIfIEsEG6OaIEIvzQrQd0ObpXeoV9c/I8qx195iOLrlvk9NK7GYNU7tjIAtXeY8Jq42zKjZhhefiQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=arm.com; dmarc=pass action=none header.from=arm.com; dkim=pass header.d=arm.com; 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=2JLbjLM++dufqW/lBnyeRSqblx0IEs4iJeIDY+yjcos=; b=L5hKUov3U8WTKm9npGbZrfx2ZG20nDAvrRnk070GHq/ON5kjvig6iY9x8VVTQhiCQDO+vAmC/ZM8sz3yudS7mzULNdTRUiSGBh3iv2PkZZwiSVSz5t7PG7RxfjJqC36FfzXcrGDvd6pbdRr/HbvpX7dQ3DlT2DIW+/gERShhlGw= Received: from DB7PR08MB3097.eurprd08.prod.outlook.com (2603:10a6:5:1d::27) by DB8PR08MB5451.eurprd08.prod.outlook.com (2603:10a6:10:113::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3784.13; Wed, 27 Jan 2021 17:10:43 +0000 Received: from DB7PR08MB3097.eurprd08.prod.outlook.com ([fe80::8c43:eec3:76be:9001]) by DB7PR08MB3097.eurprd08.prod.outlook.com ([fe80::8c43:eec3:76be:9001%4]) with mapi id 15.20.3784.019; Wed, 27 Jan 2021 17:10:43 +0000 From: "Sami Mujawar" To: Sughosh Ganu , "devel@edk2.groups.io" CC: Ard Biesheuvel , Leif Lindholm , Sahil Malhotra , Ilias Apalodimas Subject: Re: [PATCH edk2-platforms v3 1/2] Drivers/OpTeeRpmb: Add an OP-TEE backed RPMB driver Thread-Topic: [PATCH edk2-platforms v3 1/2] Drivers/OpTeeRpmb: Add an OP-TEE backed RPMB driver Thread-Index: AQHW05wANg6qV1bhf02zxj7gesITj6o70FMg Date: Wed, 27 Jan 2021 17:10:43 +0000 Message-ID: References: <20201216110903.17995-1-sughosh.ganu@linaro.org> <20201216110903.17995-2-sughosh.ganu@linaro.org> In-Reply-To: <20201216110903.17995-2-sughosh.ganu@linaro.org> Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ts-tracking-id: DDD622D686354A4F89B688B6F549578F.0 x-checkrecipientchecked: true Authentication-Results-Original: linaro.org; dkim=none (message not signed) header.d=none;linaro.org; dmarc=none action=none header.from=arm.com; x-originating-ip: [2a00:23c6:548a:4800:9c6:e11a:bdb9:1e14] x-ms-publictraffictype: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 9577d624-eea2-4c08-85b7-08d8c2e68036 x-ms-traffictypediagnostic: DB8PR08MB5451:|AM8PR08MB5763: x-ms-exchange-transport-forked: True X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true nodisclaimer: true x-ms-oob-tlc-oobclassifiers: OLM:10000;OLM:10000; X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: zkibKwsgi5Bj8sDxIJe3chrb9N4N6svVgLqawPOhl8mwIC6qIvy3+ECcKDCk+AyxCooMNu1gydfzyiLTbnmuqVcoRrK9/tcDK4JDX7lHJB01Vse6o4cF7KBfZLinmGrYrL8CdUjDAxU9An3D6FdsFDESdvXPHK0AKqBQBKv26whAhnQCdwNRgmoyN7cd83fE8oJKBDtnacUmrvdWPJVpTMXYaLAPKRNyT+lwLFSXacuC69lvFvNSuU84fP7/kdBkAthy9WmJe+bXlRiVJ6H5QjwGBSrNe2AgiRF5ziwsBcXyCRi0snAXdzRtmI3gtAegJo2OS1bF+zsqgaR7rY6YUigF3QqKe6eJkw/EINYqt+833YKn+wyuPxFpQ/IQsvZvI7x8TczpRoYcJxuwFnbnQqdugm+4me6+rbmQSLyzAH8FmtAr5dfp8hxGIzgbHB86pJj5eH+0CuiOD4yQYJlUKA== X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DB7PR08MB3097.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(6029001)(4636009)(346002)(136003)(39860400002)(396003)(376002)(366004)(19627235002)(66446008)(52536014)(66946007)(316002)(5660300002)(2906002)(30864003)(4326008)(64756008)(71200400001)(33656002)(66556008)(66476007)(55016002)(76116006)(966005)(8676002)(478600001)(186003)(83380400001)(8936002)(110136005)(6506007)(54906003)(9686003)(53546011)(86362001)(7696005)(559001)(579004);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata: =?us-ascii?Q?9YZgZfNx8YRt/wnlh93YvcNgtpDbthQPXWbnUrvqUOejb53PTrVaog5wpRHS?= =?us-ascii?Q?dbvCpWRcOnX0lzbqzaa2cS/YESHzvhmHRHkfAE3oSxOOJxeVjFxWfuBtuyeZ?= =?us-ascii?Q?mYjtbSRoOcSCtOfs7iUo5+rBkATGMmqEyjqhfgtmSTFAmYwziIfggPQR+rAi?= =?us-ascii?Q?wltkWQECVEwvWirzDRpwJR2NDMpGjiMy2Ag6+zhVB1m7yx8nV/QHsJ8F9oIn?= =?us-ascii?Q?dHICtVHntOZ3+80G2O1Sk642N3JrFZMwZgroWsGKZg6a7S44cq/FWQclJZAo?= =?us-ascii?Q?pse6sfm42gagoUomkvEMH9wOGbPiI+2SssA8IhW/Prbhl+ARQPwxm24yHN5b?= =?us-ascii?Q?e47PMYGqNuxywT3WbyoynVhNYKZmq4duhnAnIeo0rTayyw2ORwq4GtqO5RM/?= =?us-ascii?Q?pwB/nmBI2bTOaLZoln3ZfAMQ7vTeAShfydBKRJub0WlIyfLxPi2FqaacEHL9?= =?us-ascii?Q?wl6t24SacqeaHqZsquS5w7zieD702aHINkVe4E62EOQu7xciXR6XzKwbcgoX?= =?us-ascii?Q?OeepTT2Xsl40XZms8kxtyxgihS4y5mu9hPkMwhM9Rj5FONvttyV0TeoVbYne?= =?us-ascii?Q?xFC4I5pvmpPLzQZtVLT5+rr0REGgrvQSUjbKDRr2ACL3U0PiHu2sHlf30poP?= =?us-ascii?Q?h/Phg1xAWi9GPvJGrqH+HxQZ1zTdqQk4eISAX6U/tjLYpMzQjNk5EIKhDsJo?= =?us-ascii?Q?FApNE1HQJLFuvh8hclfZAA7D04qcoHsI3wxr3FeoeVm2r6VSAhMXdAQXNxeV?= =?us-ascii?Q?N8bODT9KuWr3JAN/kLGV/7DZV496WFiYVOYWetCacQl+rdgwsVfXcDJFE3F9?= =?us-ascii?Q?n3WXnk/gobCZ4++F/VrdR1AUjyY99XH22RHGzV0hAXZP0qcqReeL9rLh7A15?= =?us-ascii?Q?7+DXvoLoWeartD9ZU8GRNWcu5rGOkbAgDXQO+h+zzMbaFE6i9uX6I5Zcbyj0?= =?us-ascii?Q?bkrJRA5XclESHLOIThWexhZqvdsS/BqZlXkXcTndfWiFKnVA1/tP1fO4XNkh?= =?us-ascii?Q?yFgf73CxgKfOKcLocLkv042T5pptiecUszNOv4jGUPOJ0x0vNYjhRizcf6aS?= =?us-ascii?Q?uzsQV3EP0r0J+CDgubXnO5zO45Z/L/b9uEas3L8lxd9n+ACjiTsco69vqTUo?= =?us-ascii?Q?ISQKzV1B00G0?= MIME-Version: 1.0 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB8PR08MB5451 Original-Authentication-Results: linaro.org; dkim=none (message not signed) header.d=none;linaro.org; dmarc=none action=none header.from=arm.com; Return-Path: Sami.Mujawar@arm.com X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT007.eop-EUR03.prod.protection.outlook.com X-MS-Office365-Filtering-Correlation-Id-Prvs: c338bb99-88da-4a62-9990-08d8c2e67ad9 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: kMSgKA9HplKGGZHxvuL9eBtZgKLLaXU+bFOnKyiw4jWhoWMVLwXu4/S6+CiFarNHxb0S4O2RjRPM41OnMhZC7aPSyhkwCEMtgzn1RlWhL3xLKKFrwHIRJ9tmDR3lHYlw7gmlFhjgkIT+r3q1kEAEFbmhX8k5edNHaGoJf/681ulpEHQkNlrtLTJ+NpLzdas30IyG24h4TJzi1v5D9CPhCbLZV9PNmhYxeW71iCXUBgDJ7YfldA3YbJtDKxuWPZc+AcQCAvSc/4ivhhLKT35xXrwzY5G09dj4brmvHLT+xcKMpgVjYKrTUY2GVWtty5MHRy21IuberlOK8yAs7eUsny8gDywcy3B3kuyWU8wDcXBQojqAaa+TM+JQ6CviJiC0RCv4WAIkqWaNTty5MryzuIYEAqCJ5a46+/tEaVCSMKfdbi/dlhs63U1o7/pmD1w+HrHISU/L56aMoU7PCP1O1E3i0k5LKCqCQH7100DYd8IiFdS3J2kCLZe4NGOKGbztcIxWwxVGEyzbpd6yWYPANzatj3G1/T9JDgbT1CDgQuP+k3vCeWsI2EB525lFKlxzNr0FipCeOIa3H8ZCYg1AS8zFRyKgiQTcOlRMetKdS15OGzBWHRhqH/s+pRgqZvCJTyHnJGShwy5soCDvCE+eVuCsSGbgYnICJYeujgZGAI4= 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:(6029001)(4636009)(396003)(346002)(136003)(39850400004)(376002)(46966006)(82310400003)(33656002)(53546011)(52536014)(186003)(336012)(4326008)(5660300002)(83380400001)(8936002)(2906002)(110136005)(19627235002)(107886003)(86362001)(70206006)(6506007)(966005)(478600001)(70586007)(7696005)(316002)(8676002)(9686003)(54906003)(26005)(356005)(82740400003)(47076005)(81166007)(30864003)(55016002)(579004);DIR:OUT;SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Jan 2021 17:10:51.9100 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 9577d624-eea2-4c08-85b7-08d8c2e68036 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: VE1EUR03FT007.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM8PR08MB5763 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Sughosh, There are some edk2 coding standard incompatibilities (like space between f= unction name and opening bracket, function parameter alignment etc.) and do= cumentation for some functions is missing in the patch. Can you fix these, = please? Please also run the ECC tool in Drivers/OpTeeRpmb folder and fix any report= ed issues. The ECC errors 10002, 10006 and 10022 can be ignored for now. Other than that, please find my response inline marked [SAMI]. Regards, Sami Mujawar -----Original Message----- From: Sughosh Ganu Sent: 16 December 2020 11:09 AM To: devel@edk2.groups.io Cc: Sami Mujawar ; Ard Biesheuvel ; Leif Lindholm ; Sahil Malhotra ; Ilias Apalodimas Subject: [PATCH edk2-platforms v3 1/2] Drivers/OpTeeRpmb: Add an OP-TEE bac= ked RPMB driver From: Ilias Apalodimas A following patch is adding support for building StMM in order to run it from OP-TEE. OP-TEE in combination with a NS-world supplicant can use the RPMB partition of an eMMC to store EFI variables. The supplicant functionality is currently available in U-Boot only but can be ported into EDK2. Assuming similar functionality is added in EDK2, this will allow any hardware with an RPMB partition to store EFI variables securely. So let's add a driver that enables access of the RPMB partition through OP-TEE. Since the upper layers expect a byte addressable interface, the driver allocates memory and patches the PCDs, while syncing the memory/hardware on read/write callbacks. Signed-off-by: Ilias Apalodimas --- Changes since V2: - Allocate a dynamic number of pages based on the Pcd values instead of a static number - Clean up unused structs in header file - Added checks in OpTeeRpmbFvbGetBlockSize and handle NumLba=3D0 Drivers/OpTeeRpmb/FixupPcd.inf | 44 ++ Drivers/OpTeeRpmb/OpTeeRpmbFv.inf | 58 ++ Drivers/OpTeeRpmb/OpTeeRpmbFvb.h | 35 + Drivers/OpTeeRpmb/FixupPcd.c | 74 ++ Drivers/OpTeeRpmb/OpTeeRpmbFvb.c | 803 ++++++++++++++++++++ 5 files changed, 1014 insertions(+) diff --git a/Drivers/OpTeeRpmb/FixupPcd.inf b/Drivers/OpTeeRpmb/FixupPcd.in= f new file mode 100644 index 0000000000..f0cfdf7a4c --- /dev/null +++ b/Drivers/OpTeeRpmb/FixupPcd.inf @@ -0,0 +1,44 @@ +## @file +# Instance of Base Memory Library without assembly. +# +# Copyright (c) 2020, Linaro Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D FixupPcd + FILE_GUID =3D a827c337-a9c6-301b-aeb7-acbc95d8da22 + MODULE_TYPE =3D BASE + VERSION_STRING =3D 0.1 + LIBRARY_CLASS =3D RpmbPcdFixup|MM_STANDALONE + CONSTRUCTOR =3D FixPcdMemory + +[Sources] + FixupPcd.c + OpTeeRpmbFvb.h + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + MmServicesTableLib + PcdLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + + +[Protocols] + gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES diff --git a/Drivers/OpTeeRpmb/OpTeeRpmbFv.inf b/Drivers/OpTeeRpmb/OpTeeRpm= bFv.inf new file mode 100644 index 0000000000..b21f7397e5 --- /dev/null +++ b/Drivers/OpTeeRpmb/OpTeeRpmbFv.inf @@ -0,0 +1,58 @@ +## @file +# +# Component description file for OpTeeRpmbFv module +# +# Copyright (c) 2020, Linaro Ltd. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D OpTeeRpmbFv + FILE_GUID =3D 4803FC20-E583-3BCD-8C60-141E85C9A2CF + MODULE_TYPE =3D MM_STANDALONE + VERSION_STRING =3D 0.1 + PI_SPECIFICATION_VERSION =3D 0x00010032 + ENTRY_POINT =3D OpTeeRpmbFvbInit + +[Sources] + OpTeeRpmbFvb.c + OpTeeRpmbFvb.h + +[Packages] + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + ArmSvcLib + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + MmServicesTableLib + PcdLib + StandaloneMmDriverEntryPoint + +[Guids] + gEfiAuthenticatedVariableGuid + gEfiSystemNvDataFvGuid + gEfiVariableGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +[Protocols] + gEfiSmmFirmwareVolumeBlockProtocolGuid ## PRODUCES + +[Depex] + TRUE diff --git a/Drivers/OpTeeRpmb/OpTeeRpmbFvb.h b/Drivers/OpTeeRpmb/OpTeeRpmb= Fvb.h new file mode 100644 index 0000000000..717fc4a78b --- /dev/null +++ b/Drivers/OpTeeRpmb/OpTeeRpmbFvb.h @@ -0,0 +1,35 @@ +/** @file + + Copyright (c) 2020, Linaro Ltd. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __OPTEE_RPMB_FV_ +#define __OPTEE_RPMB_FV_ [SAMI] This does not follow the edk2 coding standard. See https://edk2-doc= s.gitbook.io/edk-ii-c-coding-standards-specification/5_source_files/53_incl= ude_files#5-3-5-all-include-file-contents-must-be-protected-by-a-include-gu= ard [/SAMI] + +/* SVC Args */ +#define SP_SVC_RPMB_READ 0xC4000066 +#define SP_SVC_RPMB_WRITE 0xC4000067 [SAMI] Is there a specification reference for this? If so, please add to th= e file header. See https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_= source_files/52_spacing#5-2-3-1-every-new-file-shall-begin-with-a-file-head= er-comment-block. [/SAMI] + +#define FILENAME "EFI_VARS" + +#define FLASH_SIGNATURE SIGNATURE_32('r', 'p', 'm', 'b') +#define INSTANCE_FROM_FVB_THIS(a) CR(a, MEM_INSTANCE, FvbProtocol, \ + FLASH_SIGNATURE) + +typedef struct _MEM_INSTANCE MEM_INSTANCE; +typedef EFI_STATUS (*MEM_INITIALIZE) (MEM_INSTANCE* Instance); +struct _MEM_INSTANCE +{ + UINT32 Signature; + MEM_INITIALIZE Initialize; + BOOLEAN Initialized; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FvbProtocol; + EFI_HANDLE Handle; + EFI_PHYSICAL_ADDRESS MemBaseAddress; + UINT16 BlockSize; + UINT16 NBlocks; +}; [SAMI] Please add documentation for structure. See https://edk2-docs.gitboo= k.io/edk-ii-c-coding-standards-specification/5_source_files/56_declarations= _and_types#5-6-3-2-structure-declaration-with-forward-reference-or-self-ref= erence [/SAMI] + +#endif diff --git a/Drivers/OpTeeRpmb/FixupPcd.c b/Drivers/OpTeeRpmb/FixupPcd.c new file mode 100644 index 0000000000..3cc882fa94 --- /dev/null +++ b/Drivers/OpTeeRpmb/FixupPcd.c @@ -0,0 +1,74 @@ +/** @file + + Update the patched PCDs to their correct value + + Copyright (c) 2020, Linaro Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/** + * Patch the relevant PCDs of the RPMB driver with the correct address of = the + * allocated memory + * +**/ +#include +#include +#include +#include + +#include +#include + +#include "OpTeeRpmbFvb.h" + +/** + Fixup the Pcd values for variable storage + + Since the upper layers of EDK2 expect a memory mapped interface and we c= an't + offer that from an RPMB, the driver allocates memory on init and passes = that + on the upper layers. Since the memory is dynamically allocated and we ca= n't set the + PCD is StMM context, we need to patch it correctly on each access + + @retval EFI_SUCCESS Protocol was found and PCDs patched up + + **/ +EFI_STATUS +EFIAPI +FixPcdMemory ( + VOID + ) +{ + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; + MEM_INSTANCE *Instance; + EFI_STATUS Status; + + // + // Locate SmmFirmwareVolumeBlockProtocol + // + Status =3D gMmst->MmLocateProtocol ( + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + NULL, + (VOID **) &FvbProtocol + ); + ASSERT_EFI_ERROR (Status); + + Instance =3D INSTANCE_FROM_FVB_THIS(FvbProtocol); + // Patch PCDs with the the correct values + PatchPcdSet32 (PcdFlashNvStorageVariableBase, Instance->MemBaseAddress); + PatchPcdSet32 (PcdFlashNvStorageFtwWorkingBase, Instance->MemBaseAddress= + + PcdGet32 (PcdFlashNvStorageVariableSize)); + PatchPcdSet32 (PcdFlashNvStorageFtwSpareBase, Instance->MemBaseAddress + + PcdGet32 (PcdFlashNvStorageVariableSize) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize)); [SAMI] Should the 64-bit versions of the PCDs be used here. A recent change added similar support to the ArmPlatformPkg\Drivers\NorFlas= hDxe. [/SAMI] + + DEBUG ((DEBUG_INFO, "%a: Fixup PcdFlashNvStorageVariableBase: 0x%lx\n", + __FUNCTION__, PcdGet32 (PcdFlashNvStorageVariableBase))); + DEBUG ((DEBUG_INFO, "%a: Fixup PcdFlashNvStorageFtwWorkingBase: 0x%lx\n"= , + __FUNCTION__, PcdGet32 (PcdFlashNvStorageFtwWorkingBase))); + DEBUG ((DEBUG_INFO, "%a: Fixup PcdFlashNvStorageFtwSpareBase: 0x%lx\n", + __FUNCTION__, PcdGet32 (PcdFlashNvStorageFtwSpareBase))); + + return Status; +} diff --git a/Drivers/OpTeeRpmb/OpTeeRpmbFvb.c b/Drivers/OpTeeRpmb/OpTeeRpmb= Fvb.c new file mode 100644 index 0000000000..71bb1f33b6 --- /dev/null +++ b/Drivers/OpTeeRpmb/OpTeeRpmbFvb.c @@ -0,0 +1,803 @@ +/** @file + + FV block I/O protocol driver for RPMB eMMC accessed via OP-TEE + + Copyright (c) 2020, Linaro Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "OpTeeRpmbFvb.h" + +static const UINT16 mem_mgr_id =3D 3U; +static const UINT16 storage_id =3D 4U; [SAMI] Please change to STATIC CONST and also update the variable names acc= ording to the edk2 coding standard. See https://edk2-docs.gitbook.io/edk-ii= -c-coding-standards-specification/4_naming_conventions/43_identifiers#4-3-3= -2-any-variable-with-file-scope-or-better-shall-be-prefixed-by-an-m-or-g [/SAMI] + +STATIC MEM_INSTANCE mInstance; + +/** + Sends an SVC call to OP-TEE for reading/writing an RPMB partition + + @param SvcAct SVC ID for read/write + @param Addr Base address of the buffer. When reading contents will= be + copied to that buffer after reading them from the devi= ce. + When writing, the buffer holds the contents we want to + write cwtoin the device + @param NumBytes Number of bytes to read/write + @param Offset Offset into the RPMB file + + @retval OP-TEE return code +**/ + [SAMI] Remove blank line. Same at other places as well. [/SAMI] +STATIC +EFI_STATUS +ReadWriteRpmb ( + UINTN SvcAct, + UINTN Addr, + UINTN NumBytes, + UINTN Offset + ) +{ + ARM_SVC_ARGS SvcArgs; + EFI_STATUS Status; + + ZeroMem (&SvcArgs, sizeof (SvcArgs)); + + SvcArgs.Arg0 =3D ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64; + SvcArgs.Arg1 =3D storage_id; + SvcArgs.Arg2 =3D 0; + SvcArgs.Arg3 =3D SvcAct; + SvcArgs.Arg4 =3D Addr; + SvcArgs.Arg5 =3D NumBytes; + SvcArgs.Arg6 =3D Offset; + + ArmCallSvc (&SvcArgs); + if (SvcArgs.Arg3) { + DEBUG ((DEBUG_ERROR, "%a: Svc Call 0x%08x Addr: 0x%08x len: 0x%x Offse= t: 0x%x failed with 0x%x\n", + __func__, SvcAct, Addr, NumBytes, Offset, SvcArgs.Arg3)); + } + + switch (SvcArgs.Arg3) { + case ARM_SVC_SPM_RET_SUCCESS: + Status =3D EFI_SUCCESS; + break; + + case ARM_SVC_SPM_RET_NOT_SUPPORTED: + Status =3D EFI_UNSUPPORTED; + break; + + case ARM_SVC_SPM_RET_INVALID_PARAMS: + Status =3D EFI_INVALID_PARAMETER; + break; + + case ARM_SVC_SPM_RET_DENIED: + Status =3D EFI_ACCESS_DENIED; + break; + + case ARM_SVC_SPM_RET_NO_MEMORY: + Status =3D EFI_BAD_BUFFER_SIZE; + break; + + default: + Status =3D EFI_ACCESS_DENIED; + } [SAMI] Should the error handling here be updated similar to the FF-A Standa= loneMmPkg patches? [/SAMI] + + return Status; +} + +/** + The GetAttributes() function retrieves the attributes and + current settings of the block. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL insta= nce. + + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the + attributes and current settings are + returned. Type EFI_FVB_ATTRIBUTES_2 is defined + in EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were + returned. + +**/ +STATIC +EFI_STATUS +OpTeeRpmbFvbGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + *Attributes =3D EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabl= ed + EFI_FVB2_WRITE_STATUS | // Writes are currently enab= led + EFI_FVB2_WRITE_ENABLED_CAP | // Writes may be enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required= to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY; // After erasure all bits ta= ke this value (i.e. '1') + + return EFI_SUCCESS; +} + +/** + The SetAttributes() function sets configurable firmware volume + attributes and returns the new settings of the firmware volume. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL ins= tance. + + @param Attributes On input, Attributes is a pointer to + EFI_FVB_ATTRIBUTES_2 that contains the + desired firmware volume settings. On + successful return, it contains the new + settings of the firmware volume. Type + EFI_FVB_ATTRIBUTES_2 is defined in + EFI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were return= ed. + + @retval EFI_INVALID_PARAMETER The attributes requested are in + conflict with the capabilities + as declared in the firmware + volume header. + +**/ +STATIC +EFI_STATUS +OpTeeRpmbFvbSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + return EFI_SUCCESS; // ignore for now +} + +/** + The GetPhysicalAddress() function retrieves the base address of + a memory-mapped firmware volume. This function should be called + only for memory-mapped firmware volumes. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL instanc= e. + + @param Address Pointer to a caller-allocated + EFI_PHYSICAL_ADDRESS that, on successful + return from GetPhysicalAddress(), contains the + base address of the firmware volume. + + @retval EFI_SUCCESS The firmware volume base address was returned. + + @retval EFI_UNSUPPORTED The firmware volume is not memory mapped. + +**/ +STATIC +EFI_STATUS +OpTeeRpmbFvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + MEM_INSTANCE *Instance; + + Instance =3D INSTANCE_FROM_FVB_THIS(This); + *Address =3D Instance->MemBaseAddress; + + return EFI_SUCCESS; +} + +/** + The GetBlockSize() function retrieves the size of the requested + block. It also returns the number of additional blocks with + the identical size. The GetBlockSize() function is used to + retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). + + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL i= nstance. + + @param Lba Indicates the block for which to return the size. + + @param BlockSize Pointer to a caller-allocated UINTN in which + the size of the block is returned. + + @param NumberOfBlocks Pointer to a caller-allocated UINTN in + which the number of consecutive blocks, + starting with Lba, is returned. All + blocks in this range have a size of + BlockSize. + + + @retval EFI_SUCCESS The firmware volume base address was ret= urned. + + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. + +**/ +STATIC +EFI_STATUS +OpTeeRpmbFvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +{ + MEM_INSTANCE *Instance; + + Instance =3D INSTANCE_FROM_FVB_THIS(This); + if (Lba > Instance->NBlocks) { + return EFI_INVALID_PARAMETER; + } + + *NumberOfBlocks =3D Instance->NBlocks - (UINTN) Lba; + *BlockSize =3D Instance->BlockSize; + + return EFI_SUCCESS; +} + +/** + Reads the specified number of bytes into a buffer from the specified blo= ck. + + The Read() function reads the requested number of bytes from the + requested block and stores them in the provided buffer. + Implementations should be mindful that the firmware volume + might be in the ReadDisabled state. If it is in this state, + the Read() function must return the status code + EFI_ACCESS_DENIED without modifying the contents of the + buffer. The Read() function must also prevent spanning block + boundaries. If a read is requested that would span a block + boundary, the read must read up to the boundary but not + beyond. The output parameter NumBytes must be set to correctly + indicate the number of bytes actually read. The caller must be + aware that a read may be partially completed. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL instanc= e. + + @param Lba The starting logical block index + from which to read. + + @param Offset Offset into the block at which to begin reading. + + @param NumBytes Pointer to a UINTN. At entry, *NumBytes + contains the total size of the buffer. At + exit, *NumBytes contains the total number of + bytes read. + + @param Buffer Pointer to a caller-allocated buffer that will + be used to hold the data that is read. + + @retval EFI_SUCCESS The firmware volume was read successfully, + and contents are in Buffer. + + @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA + boundary. On output, NumBytes + contains the total number of bytes + returned in Buffer. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + ReadDisabled state. + + @retval EFI_DEVICE_ERROR The block device is not + functioning correctly and could + not be read. + +**/ + +STATIC +EFI_STATUS +OpTeeRpmbFvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + MEM_INSTANCE *Instance; + VOID *Base; + + Instance =3D INSTANCE_FROM_FVB_THIS(This); + if (Instance->Initialized =3D=3D FALSE) { [SAMI] if (!Instance->Initialized) ? See https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_= source_files/57_c_programming#5-7-2-1-boolean-values-variable-type-boolean-= do-not-require-explicit-comparisons-to-true-or-false [/SAMI] + Instance->Initialize (Instance); + } + + Base =3D (VOID *)Instance->MemBaseAddress + Lba * Instance->BlockSize + = Offset; + // We could read the data from the RPMB instead of memory + // The 2 copies should already be identical + // Copy from memory image + CopyMem (Buffer, Base, *NumBytes); + + return Status; +} + +/** + Writes the specified number of bytes from the input buffer to the block. + + The Write() function writes the specified number of bytes from + the provided buffer to the specified block and offset. If the + firmware volume is sticky write, the caller must ensure that + all the bits of the specified range to write are in the + EFI_FVB_ERASE_POLARITY state before calling the Write() + function, or else the result will be unpredictable. This + unpredictability arises because, for a sticky-write firmware + volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY + state but cannot flip it back again. Before calling the + Write() function, it is recommended for the caller to first call + the EraseBlocks() function to erase the specified block to + write. A block erase cycle will transition bits from the + (NOT)EFI_FVB_ERASE_POLARITY state back to the + EFI_FVB_ERASE_POLARITY state. Implementations should be + mindful that the firmware volume might be in the WriteDisabled + state. If it is in this state, the Write() function must + return the status code EFI_ACCESS_DENIED without modifying the + contents of the firmware volume. The Write() function must + also prevent spanning block boundaries. If a write is + requested that spans a block boundary, the write must store up + to the boundary but not beyond. The output parameter NumBytes + must be set to correctly indicate the number of bytes actually + written. The caller must be aware that a write may be + partially completed. All writes, partial or otherwise, must be + fully flushed to the hardware before the Write() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL instanc= e. + + @param Lba The starting logical block index to write to. + + @param Offset Offset into the block at which to begin writing. + + @param NumBytes The pointer to a UINTN. At entry, *NumBytes + contains the total size of the buffer. At + exit, *NumBytes contains the total number of + bytes actually written. + + @param Buffer The pointer to a caller-allocated buffer that + contains the source for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully= . + + @retval EFI_BAD_BUFFER_SIZE The write was attempted across an + LBA boundary. On output, NumBytes + contains the total number of bytes + actually written. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + WriteDisabled state. + + @retval EFI_DEVICE_ERROR The block device is malfunctioning + and could not be written. + + +**/ +STATIC +EFI_STATUS +OpTeeRpmbFvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + MEM_INSTANCE *Instance; + EFI_STATUS Status =3D EFI_SUCCESS; + VOID *Base; + + Instance =3D INSTANCE_FROM_FVB_THIS(This); + if (Instance->Initialized =3D=3D FALSE) { [SAMI] if (!Instance->Initialized) ? See https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_= source_files/57_c_programming#5-7-2-1-boolean-values-variable-type-boolean-= do-not-require-explicit-comparisons-to-true-or-false [/SAMI] + Instance->Initialize (Instance); + } + Base =3D (VOID *)Instance->MemBaseAddress + Lba * Instance->BlockSize + = Offset; + Status =3D ReadWriteRpmb (SP_SVC_RPMB_WRITE, (UINTN) Buffer, *NumBytes, + Lba * Instance->BlockSize + Offset); + if (Status !=3D EFI_SUCCESS) { [SAMI] if (EFI_ERROR (Status)) ? [/SAMI] + return Status; + } + + // Update the memory copy + CopyMem (Base, Buffer, *NumBytes); + + return EFI_SUCCESS; +} + +/** + Erases and initializes a firmware volume block. + + The EraseBlocks() function erases one or more blocks as denoted + by the variable argument list. The entire parameter list of + blocks must be verified before erasing any blocks. If a block is + requested that does not exist within the associated firmware + volume (it has a larger index than the last block of the + firmware volume), the EraseBlocks() function must return the + status code EFI_INVALID_PARAMETER without modifying the contents + of the firmware volume. Implementations should be mindful that + the firmware volume might be in the WriteDisabled state. If it + is in this state, the EraseBlocks() function must return the + status code EFI_ACCESS_DENIED without modifying the contents of + the firmware volume. All calls to EraseBlocks() must be fully + flushed to the hardware before the EraseBlocks() service + returns. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL + instance. + + @param ... The variable argument list is a list of tuples. + Each tuple describes a range of LBAs to erase + and consists of the following: + - An EFI_LBA that indicates the starting LBA + - A UINTN that indicates the number of blocks to + erase. + + The list is terminated with an + EFI_LBA_LIST_TERMINATOR. For example, the + following indicates that two ranges of blocks + (5-7 and 10-11) are to be erased: EraseBlocks + (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR); + + @retval EFI_SUCCESS The erase request successfully + completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the + WriteDisabled state. + @retval EFI_DEVICE_ERROR The block device is not functioning + correctly and could not be written. + The firmware device may have been + partially erased. + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed + in the variable argument list do + not exist in the firmware volume. + +**/ +STATIC +EFI_STATUS +OpTeeRpmbFvbErase ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +{ + MEM_INSTANCE *Instance; + UINTN NumBytes; + UINTN NumLba; + EFI_LBA Start; + VOID *Base; + VOID *Buf; + VA_LIST Args; + EFI_STATUS Status; + + Instance =3D INSTANCE_FROM_FVB_THIS(This); + + VA_START (Args, This); + for (Start =3D VA_ARG (Args, EFI_LBA); + Start !=3D EFI_LBA_LIST_TERMINATOR; + Start =3D VA_ARG (Args, EFI_LBA)) { + NumLba =3D VA_ARG (Args, UINTN); + if (NumLba =3D=3D 0 || Start + NumLba > Instance->NBlocks) { + return EFI_INVALID_PARAMETER; + } + NumBytes =3D NumLba * Instance->BlockSize; + Base =3D (VOID *)Instance->MemBaseAddress + Start * Instance->BlockSiz= e; + Buf =3D AllocatePool(NumLba * Instance->BlockSize); + if (!Buf) { + return EFI_DEVICE_ERROR; + } + SetMem64 (Buf, NumLba * Instance->BlockSize, ~0UL); + // Write the device + Status =3D ReadWriteRpmb (SP_SVC_RPMB_WRITE, (UINTN) Buf, NumBytes, + Start * Instance->BlockSize); + if (Status !=3D EFI_SUCCESS) { [SAMI] if (EFI_ERROR (Status)) ? [/SAMI] + return Status; + } + // Update the in memory copy + SetMem64 (Base, NumLba * Instance->BlockSize, ~0UL); + FreePool (Buf); + } + + VA_END (Args); + + return EFI_SUCCESS; +} + +/** + Since we use a memory backed storage we need to restore the RPMB content= s + into memory before we register the Fvb protocol. + + @param Instace Address to copy flash contents to + + @retval 0 on success, OP-TEE error on failure +**/ +STATIC +VOID +ReadEntireFlash ( + MEM_INSTANCE *Instance + ) +{ + UINTN ReadAddr; + + UINTN StorageFtwWorkingSize =3D PcdGet32(PcdFlashNvStorageFtwWorkingSize= ); + UINTN StorageVariableSize =3D PcdGet32(PcdFlashNvStorageVariableSize); + UINTN StorageFtwSpareSize =3D PcdGet32(PcdFlashNvStorageFtwSpareSize); + + ReadAddr =3D Instance->MemBaseAddress; + // There's no need to check if the read failed here. The upper EDK2 laye= rs + // will initialize the flash correctly if the in-memory copy is wrong + ReadWriteRpmb(SP_SVC_RPMB_READ, ReadAddr, StorageVariableSize + + StorageFtwWorkingSize + StorageFtwSpareSize , 0); +} + + +STATIC +EFI_STATUS +EFIAPI +ValidateFvHeader ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +{ + UINT16 Checksum; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + + FvLength =3D PcdGet32(PcdFlashNvStorageVariableSize) + + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize); + + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ( (FwVolHeader->Revision !=3D EFI_FVH_REVISION) + || (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) + || (FwVolHeader->FvLength !=3D FvLength) + ) + { + DEBUG ((DEBUG_INFO, "%a: No Firmware Volume header present\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid)= ) { [SAMI] Not a comment for this patch but I noticed that BaseTools has an imp= lementation of CompareGuid() that returns INTN. I wonder if that is intentional. Moreover, it also appears that the Compare= Guid() usage in BaseTools does not consistently follow the explicit compari= son rule (https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specificat= ion/5_source_files/57_c_programming#5-7-2-1-boolean-values-variable-type-bo= olean-do-not-require-explicit-comparisons-to-true-or-false). [/SAMI] + DEBUG ((DEBUG_INFO, "%a: Firmware Volume Guid non-compatible\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + // Verify the header checksum + Checksum =3D CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLen= gth); + if (Checksum !=3D 0) { + DEBUG ((DEBUG_INFO, "%a: FV checksum is invalid (Checksum:0x%X)\n", + __FUNCTION__, Checksum)); + return EFI_NOT_FOUND; [SAMI] Minor: By this point we should be fairly certain that this is a Firm= ware Volume header. So, should the error code returned here be EFI_VOLUME_CORRUPTED? Would the = same apply to the remaining checks below? [/SAMI] + } + + VariableStoreHeader =3D (VOID *)((UINTN)FwVolHeader + [SAMI] Should the typecast be (VARIABLE_STORE_HEADER*) instead of (VOID *)? [/SAMI] + FwVolHeader->HeaderLength); + + // Check the Variable Store Guid + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && + !CompareGuid (&VariableStoreHeader->Signature, + &gEfiAuthenticatedVariableGuid)) { + DEBUG ((DEBUG_INFO, "%a: Variable Store Guid non-compatible\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + VariableStoreLength =3D PcdGet32 (PcdFlashNvStorageVariableSize) - + FwVolHeader->HeaderLength; + if (VariableStoreHeader->Size !=3D VariableStoreLength) { + DEBUG ((DEBUG_INFO, "%a: Variable Store Length does not match\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; + +} + +STATIC +EFI_STATUS +InitializeFvAndVariableStoreHeaders ( + MEM_INSTANCE *Instance + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + EFI_STATUS Status =3D EFI_SUCCESS; + UINTN HeadersLength; + VOID* Headers; + + HeadersLength =3D sizeof(EFI_FIRMWARE_VOLUME_HEADER) + + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + + sizeof(VARIABLE_STORE_HEADER); + Headers =3D AllocateZeroPool(HeadersLength); + + // + // EFI_FIRMWARE_VOLUME_HEADER + // + FirmwareVolumeHeader =3D (EFI_FIRMWARE_VOLUME_HEADER*)Headers; + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid= ); + FirmwareVolumeHeader->FvLength =3D + PcdGet32(PcdFlashNvStorageVariableSize) + + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize); + FirmwareVolumeHeader->Signature =3D EFI_FVH_SIGNATURE; + FirmwareVolumeHeader->Attributes =3D EFI_FVB2_READ_ENABLED_CAP | + EFI_FVB2_READ_STATUS | + EFI_FVB2_STICKY_WRITE | + EFI_FVB2_MEMORY_MAPPED | + EFI_FVB2_ERASE_POLARITY | + EFI_FVB2_WRITE_STATUS | + EFI_FVB2_WRITE_ENABLED_CAP; + + FirmwareVolumeHeader->HeaderLength =3D sizeof(EFI_FIRMWARE_VOLUME_HEADER= ) + + sizeof(EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision =3D EFI_FVH_REVISION; + FirmwareVolumeHeader->BlockMap[0].NumBlocks =3D Instance->NBlocks; + FirmwareVolumeHeader->BlockMap[0].Length =3D Instance->BlockSize; + FirmwareVolumeHeader->BlockMap[1].NumBlocks =3D 0; + FirmwareVolumeHeader->BlockMap[1].Length =3D 0; + FirmwareVolumeHeader->Checksum =3D CalculateCheckSum16 ( + (UINT16*)FirmwareVolumeHeader, + FirmwareVolumeHeader->HeaderLength); + + // + // VARIABLE_STORE_HEADER + // + VariableStoreHeader =3D (VOID *)((UINTN)Headers + [SAMI] Should the typecase be (VARIABLE_STORE_HEADER*) instead of (VOID *)? [/SAMI] + FirmwareVolumeHeader->HeaderLength); + CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGui= d); + VariableStoreHeader->Size =3D PcdGet32(PcdFlashNvStorageVariableSize) - + FirmwareVolumeHeader->HeaderLength; + VariableStoreHeader->Format =3D VARIABLE_STORE_FORMATTED; + VariableStoreHeader->State =3D VARIABLE_STORE_HEALTHY; + + Status =3D ReadWriteRpmb(SP_SVC_RPMB_WRITE, (UINTN) Headers, HeadersLeng= th, 0); + if (Status !=3D EFI_SUCCESS) { [SAMI] if (EFI_ERROR (Status)) ? [/SAMI] + goto Exit; + } + // Install the combined header in memory + CopyMem ((VOID*) Instance->MemBaseAddress, Headers, HeadersLength); + +Exit: + FreePool (Headers); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +FvbInitialize ( + MEM_INSTANCE *Instance + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_STATUS Status; + + if (Instance->Initialized =3D=3D TRUE) { [SAMI] if (Instance->Initialized) ? See https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_= source_files/57_c_programming#5-7-2-1-boolean-values-variable-type-boolean-= do-not-require-explicit-comparisons-to-true-or-false [/SAMI] + return EFI_SUCCESS; + } + + // FirmwareVolumeHeader->FvLength is declared to have the Variable area + // AND the FTW working area AND the FTW Spare contiguous. + ASSERT (PcdGet32 (PcdFlashNvStorageVariableBase) + + PcdGet32 (PcdFlashNvStorageVariableSize) =3D=3D + PcdGet32 (PcdFlashNvStorageFtwWorkingBase)); + ASSERT (PcdGet32 (PcdFlashNvStorageFtwWorkingBase) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) =3D=3D + PcdGet32 (PcdFlashNvStorageFtwSpareBase)); + + // Check if the size of the area is at least one block size + ASSERT ((PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && + (PcdGet32 (PcdFlashNvStorageVariableSize) / Instance->BlockSize = > 0)); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && + (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) / Instance->BlockSiz= e > 0)); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && + (PcdGet32 (PcdFlashNvStorageFtwSpareSize) / Instance->BlockSize = > 0)); + + // Ensure the Variable areas are aligned on block size boundaries + ASSERT ((PcdGet32 (PcdFlashNvStorageVariableBase) % Instance->BlockSize)= =3D=3D 0); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingBase) % Instance->BlockSiz= e) =3D=3D 0); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareBase) % Instance->BlockSize)= =3D=3D 0); [SAMI] These asserts may need to be adjusted if 64-bit versions of the PCDs= are used. [/SAMI] + + // Read the file from disk and copy it to memory + ReadEntireFlash (Instance); + + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *) Instance->MemBaseAddress; + Status =3D ValidateFvHeader(FwVolHeader); + if (EFI_ERROR (Status)) { + // There is no valid header, so time to install one. + DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__= )); + + // Reset memory + SetMem64 ((VOID *)Instance->MemBaseAddress, Instance->NBlocks * Instan= ce->BlockSize, ~0UL); + DEBUG ((DEBUG_INFO, "%a: Erasing Flash.\n", __FUNCTION__)); + Status =3D ReadWriteRpmb(SP_SVC_RPMB_WRITE, Instance->MemBaseAddress, + PcdGet32(PcdFlashNvStorageVariableSize) + + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize), 0); + if (Status !=3D EFI_SUCCESS) { [SAMI] if (EFI_ERROR (Status)) ? [/SAMI] + return Status; + } + // Install all appropriate headers + DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this volume.\n", + __FUNCTION__)); + Status =3D InitializeFvAndVariableStoreHeaders (Instance); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + DEBUG ((DEBUG_INFO, "%a: Found valid FVB Header.\n", __FUNCTION__)); + } + Instance->Initialized =3D TRUE; + + return EFI_SUCCESS; [SAMI] return Status; ? [/SAMI] +} + +EFI_STATUS +EFIAPI +OpTeeRpmbFvbInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *Addr; + UINTN FvLength; + UINTN NBlocks; + + FvLength =3D PcdGet32(PcdFlashNvStorageVariableSize) + + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize); + + NBlocks =3D EFI_SIZE_TO_PAGES(ALIGN_VARIABLE(FvLength)); + Addr =3D AllocatePages(NBlocks); + ASSERT (Addr !=3D NULL); [SAMI] Asserts will vanish in release builds and a failure to allocate memo= ry would result in incorrect results. Please handle this error and return EFI_OUT_OF_RESOURCES. [/SAMI] + + SetMem (&mInstance, sizeof (mInstance), 0); + + mInstance.FvbProtocol.GetPhysicalAddress =3D OpTeeRpmbFvbGetPhysicalAddr= ess; + mInstance.FvbProtocol.GetAttributes =3D OpTeeRpmbFvbGetAttributes; + mInstance.FvbProtocol.SetAttributes =3D OpTeeRpmbFvbSetAttributes; + mInstance.FvbProtocol.GetBlockSize =3D OpTeeRpmbFvbGetBlockSize; + mInstance.FvbProtocol.EraseBlocks =3D OpTeeRpmbFvbErase; + mInstance.FvbProtocol.Write =3D OpTeeRpmbFvbWrite; + mInstance.FvbProtocol.Read =3D OpTeeRpmbFvbRead; + + mInstance.MemBaseAddress =3D (EFI_PHYSICAL_ADDRESS) Addr; + mInstance.Signature =3D FLASH_SIGNATURE; + mInstance.Initialize =3D FvbInitialize; + mInstance.BlockSize =3D EFI_PAGE_SIZE; + mInstance.NBlocks =3D NBlocks; + + // Update the defined PCDs related to Variable Storage + PatchPcdSet32 (PcdFlashNvStorageVariableBase, mInstance.MemBaseAddress); [SAMI] Should the 64-bit versions of the PCDs be used here. A recent change added similar support to the ArmPlatformPkg\Drivers\NorFlas= hDxe. [/SAMI] + PatchPcdSet32 (PcdFlashNvStorageFtwWorkingBase, mInstance.MemBaseAddress= + + PcdGet32 (PcdFlashNvStorageVariableSize)); + PatchPcdSet32 (PcdFlashNvStorageFtwSpareBase, mInstance.MemBaseAddress + + PcdGet32 (PcdFlashNvStorageVariableSize) + + PcdGet32 (PcdFlashNvStorageFtwWorkingSize)); + + Status =3D gMmst->MmInstallProtocolInterface ( + &mInstance.Handle, + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + EFI_NATIVE_INTERFACE, + &mInstance.FvbProtocol + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO, "%a: Register OP-TEE RPMB Fvb\n", __FUNCTION__)); + DEBUG ((DEBUG_INFO, "%a: Using NV store FV in-memory copy at 0x%lx\n", + __FUNCTION__, PatchPcdGet32 (PcdFlashNvStorageVariableBase))); + + return Status; +} -- 2.17.1 IMPORTANT NOTICE: The contents of this email and any attachments are confid= ential and may also be privileged. If you are not the intended recipient, p= lease notify the sender immediately and do not disclose the contents to any= other person, use it for any purpose, or store or copy the information in = any medium. Thank you.