From nobody Wed Dec 25 01:27:36 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1513744933363462.21545114185733; Tue, 19 Dec 2017 20:42:13 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 6A123222447BA; Tue, 19 Dec 2017 20:37:22 -0800 (PST) Received: from NAM01-BY2-obe.outbound.protection.outlook.com (mail-by2nam01on0060.outbound.protection.outlook.com [104.47.34.60]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A4106222447B7 for ; Tue, 19 Dec 2017 20:37:20 -0800 (PST) Received: from BN6PR03CA0052.namprd03.prod.outlook.com (10.173.137.14) by CY4PR03MB2693.namprd03.prod.outlook.com (10.173.43.136) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.323.15; Wed, 20 Dec 2017 04:42:06 +0000 Received: from BL2FFO11FD044.protection.gbl (2a01:111:f400:7c09::189) by BN6PR03CA0052.outlook.office365.com (2603:10b6:404:4c::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.345.14 via Frontend Transport; Wed, 20 Dec 2017 04:42:06 +0000 Received: from tx30smr01.am.freescale.net (192.88.168.50) by BL2FFO11FD044.mail.protection.outlook.com (10.173.161.140) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.20.302.6 via Frontend Transport; Wed, 20 Dec 2017 04:41:52 +0000 Received: from uefi-OptiPlex-790.ap.freescale.net ([10.232.132.56]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id vBK4fsdg019373; Tue, 19 Dec 2017 21:42:03 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=104.47.34.60; helo=nam01-by2-obe.outbound.protection.outlook.com; envelope-from=vabhav.sharma@nxp.com; receiver=edk2-devel@lists.01.org Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=nxp.com; nxp.com; dkim=none (message not signed) header.d=none;nxp.com; dmarc=fail action=none header.from=nxp.com; Received-SPF: Fail (protection.outlook.com: domain of nxp.com does not designate 192.88.168.50 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; From: Vabhav To: , , , Date: Tue, 19 Dec 2017 22:10:10 +0530 Message-ID: <1513701611-19990-4-git-send-email-vabhav.sharma@nxp.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1513701611-19990-1-git-send-email-vabhav.sharma@nxp.com> References: <1513701611-19990-1-git-send-email-vabhav.sharma@nxp.com> X-EOPAttributedMessage: 0 X-Matching-Connectors: 131582185131494685; (91ab9b29-cfa4-454e-5278-08d120cd25b8); () X-Forefront-Antispam-Report: CIP:192.88.168.50; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(336005)(7966004)(39380400002)(39860400002)(376002)(346002)(396003)(2980300002)(1110001)(1109001)(339900001)(199004)(189003)(2906002)(36756003)(50466002)(53946003)(47776003)(6306002)(2950100002)(6666003)(53936002)(16200700003)(48376002)(104016004)(53376002)(4326008)(8936002)(51416003)(8656006)(106466001)(105606002)(5660300001)(86362001)(97736004)(81166006)(8676002)(966005)(81156014)(2201001)(76176011)(498600001)(15188155005)(16799955002)(85426001)(77096006)(68736007)(316002)(305945005)(54906003)(110136005)(356003)(16586007)(59450400001)(50226002)(579004)(559001)(569006); DIR:OUT; SFP:1101; SCL:1; SRVR:CY4PR03MB2693; H:tx30smr01.am.freescale.net; FPR:; SPF:Fail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BL2FFO11FD044; 1:mpy5JmW889v4ij6B9OHmHgltaLGVSED9G3QCgs/5EVT10sWQsatMG7pZGzjak/+n82RA2t9xb5rtiiPc+1Bhf9/t61OytLTr79PG2+Uwq5zCbmHct+7CTW+7wew2EkKQ MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 9bc10c8d-1234-4878-4d1d-08d54763fdff X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600026)(4604075)(4534020)(4628075)(201703131517081)(2017052603307); SRVR:CY4PR03MB2693; X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2693; 3:8tVM2CdbigoqRZH2gPo/BRbTHZQ0xJFJCdmzXqHqmOcU++16q5zJHE29ktaELHUi2UY1IACoQaweS/7UUkjClVPgj+yX5FuZA/wkIFXK1a2vAzOJTizxZBCIfDmslyuNJ85YQkmdKqtYmAA7KlcgVqAX2d/fSu2+OuJZ4HOLfafiaeVbuCsi9m7Jc0edTbpGt/oSljKJ/HKMuHYWQXjwBikfrJwxVlk0H9e1ous3Y/4j4RRW4Biq1FxbtPpd1cUS/jmBpPxPo2xLWgewEandnBvsp4cLd5J8/+pPlYfdgRAAInetY+8Syy0fm2UmeFF7QPXg8kd45iqcj6x+IvVhyrDud6tO4HtcCIz2rE2iBPY=; 25:FxFBsIdXYo+pYSpD5M6FkV6UxbnUPUOBjtH8F70HaYO8BDPkig0jBrYN6eZbg1iJ7VgMwC6l0MJ0F6W4B+afTi1Lj/r+K7YYUoQvF/kL3YbA/OFquDmScGeS4FK0JsXwQtzSBqEqyaL+sNl/d7px2QNI23A8EItxyfKSXE2UmP62v1GQ8nQ2Se6R1kyUEbSGHuwXWAewd2iJLnveyKeqrdQRwXHfbZ2oHQvxmxO4iN5xCKg9oM+R3MO/QhG9Jl24Sw6o/FIp/6uBNFOzdddlo6u2nwB3az4gb8v0eS8+ZqRr7iskkI0GraZnWawi6tgCwHah8b32YLOtssg3vmrvUg== X-MS-TrafficTypeDiagnostic: CY4PR03MB2693: X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2693; 31:3mVMklEuXbjxIVtek3IT8fA0p0cHQOMtC2AJZJpfeM4G+b74rjZbtOEOn52iDpMfVLW8UsldRNw6NKdc6hDlRSAgQi08V3fyGi/dceOU57XYfUUA88CzU89tPjeAMzUeUMhDeadxk6VGvOhHDeL+nOFqDIyIjgfX+j0kHusA4aF8ukk3nv0wLAF7djl/vo38lK3PCFvnQI7kbi9G1dpZmMQsZEyIkqSmija74hny6wk=; 4:ayvFfCxZvH7pTlay3k1lTNfHhgEWWjlbVL+YUdB25kidxhZ9wRbKdYkwzrmzEMpisWnJt+6Q3tZGMa2fV2KWqjS4Y4g7Z2hdQJASjJ5vajHVIVSAIu8w8yknESSIJSDXw66Sk+PM9qKjccd3qoOT6HS1J7CxeYTiHKF12zUJaltVLxPEk+3Vw1BoNk22MB1EQ3bredyvseZvgJWG/8KFbMewEYKUxc9vRb8BldxxAPFRF5YGM1a7EtpdpSQZMf7oDW3kDMRHaCo0Zh5WgaDKVAbSA0wI/+YqaYwmBc8wzP8l1EPCx4m0bINwAYapTVYm4ecV+NS804i2ODPsQimtYO2rJEA7Hf2ffbt7dK0KXqc= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(185117386973197)(17755550239193); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6095135)(2401047)(5005006)(8121501046)(10201501046)(3002001)(3231023)(93006095)(93001095)(6055026)(6096035)(20161123559100)(201703131430075)(201703131433075)(201703131441075)(201703131448075)(201703161259150)(20161123556025)(20161123565025)(20161123563025)(20161123561025)(201708071742011); SRVR:CY4PR03MB2693; BCL:0; PCL:0; RULEID:(100000803101)(100110400095)(400006); SRVR:CY4PR03MB2693; X-Forefront-PRVS: 0527DFA348 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY4PR03MB2693; 23:EA6y9TEkJpxvzv/2ypG7pxOFAhOn7S42IMVxBQlaD?= =?us-ascii?Q?3bv9qN4wbIJGQ0U7iwDGvzZqYTCLSJQmS21t9AVVPv5kVCbEVp7KAOn2Jybw?= =?us-ascii?Q?G+OQ+w5c0Q2pNpcscgjWV07bn4sw2c+wyINvR/4DtmWKS0RefkzvWIAhlpXS?= =?us-ascii?Q?T5jANsG4X/CyUZ+7AYgi1EEFoUupHm8LCNqNLi18ZMKje3+shMDl5V/E2kYq?= =?us-ascii?Q?ALtz8KjXYllfWBm43lD2nPXhVcK3a8zOY6t72dNbw9U10vfLgf96FRt3x2Q9?= =?us-ascii?Q?o0eeRJgYV1SypqAKVizpDGqalBOkIdEXSPe60VuKoIzis62QUAPPRHMVdinR?= =?us-ascii?Q?ohvCIuV13JmCPlPX6T1iK8Ui+vgLoT2XrJHNLZdQZTuWhb0cLnXkrC2ZZ3VE?= =?us-ascii?Q?z/EW06rTIqp21xr4a/32aDZ/pTb45Ra4B+mL82KkFK9803+FlaKfxoMCMbJi?= =?us-ascii?Q?OVzE3ruScGfQPpF5fc4F+9bOHhotjzgxgAKdoC1pyLJladVrRBdSWHblSU3n?= =?us-ascii?Q?qh4KN/IDUdRp4QNx67AxPIxzozhnuorkIYfMvHkO2cuEJgjOwGPkZ+PtRGKG?= =?us-ascii?Q?E/ImExtJ0/5YyWxAGuH4laX8qcBNwI0xHDtJIYvgwFL+b2lAZoT1XM9oIIxx?= =?us-ascii?Q?+id3xiDBTv+wyttv7r9OKSz0Xpv46KHzrKrouNERvwXuaCRmvXEuF5FncoL2?= =?us-ascii?Q?i3Chh4UkA58fyZkUy62dJC7K4P8ufbMBPKAv2Y2hDZh6+aEu2zlGrBOdOScI?= =?us-ascii?Q?pFDsBZDhUX2EUW1h5t2mdGA2V9zsFqRKAXa+nDi2FsiPdA+jnrvxyWuR18TH?= =?us-ascii?Q?A6qyx6fCbZEH+NCZ+aIJ3wLaOKfFLH0WI6YYH1CeBFFgVhBeJHKDao3MY3yu?= =?us-ascii?Q?K4WUnXJWbsecWY54JrQ3zOI5qzIzihsCSLDDVoRx6gLo+KSyiAljsAoIII+/?= =?us-ascii?Q?Juxa9s6csj1kZV+LV7/bpZUsLHCqIzedfpoJwRrW/REBY7VdXimps9XQPVEe?= =?us-ascii?Q?pJwb0FpTqn8+kOnUhOHVTDFMpirB12OSEKVwgM8PX818V69fHxtkrCg9BWpC?= =?us-ascii?Q?4Xc5FX7AxOk2v1rCCxd/AE2dNXtx4m3ofOfJwuLA56gVtvrs7NY9LfUc3j9m?= =?us-ascii?Q?TjyxfMtHB8e7tcQRu8ZWtJ1x12RFQMEygyo+Brev/RpoVcBJ1q4NsVjPsFCN?= =?us-ascii?Q?JeYkSb2jlsoK9OIAaOXXcYlEyJZptivJX8HvkYN5ERe77SgMoZPoxXEX+P3+?= =?us-ascii?Q?/lD+2L6vEP6q8BzLiXMzkn1F5Kq0AUm+oySLiNIj2AOYsYhkdk+ac9XDyai0?= =?us-ascii?Q?9ttFVhygk5CPxzJmRVoXXHvnIs4ANV7ztQuR23YdcqV?= X-Microsoft-Exchange-Diagnostics: 1; CY4PR03MB2693; 6:WN6imwty5Azlbn/Oe6HbTUL3neeuVORuDbalHO0zyNKvMh7DPkiyBUJgYQkoZuFjFpw2Xv2pV/fjIHs5y3ZNjmRhOxsxw/CY9GTNc70GRErCUrZMQN7F+kr7wcOOEyO+VqN2JyXj0fVkpJ14JcPpg+K8RtEaHPLtKpCfE2RKTJgKTpb6Ih7Fb1Pwer67k3rvCObbiPlraljGLEPSwmibazpbLhYarCVZPJwtzu3bO50XhiZ2KbkzJihOKI6yU/YadzuKasZKfOrI2EdYET/tKkMyVIIceXMWUDn0+qs6EwhZMYIdy7LRpzE9R7vleKQqOAuVrk4G6BgELvi8+UDC18x1DMnOViPUk9Z/LOG0/YU=; 5:FzU9luhmpmzsrPgrMFTY7K/bo3RZoNb4BzjYfju+EHpW5q2wAZqj1OxOt+/QPvl/XkqhPQNPpURPHPFrz3JQFrXXTe9NwS4613WNrJvCEb2JQ4EO3PqPXW2IwkorUyNpUHIOyocNReSDF+hjq3bbhB/Mu1Z/32iWKCTaz+BbHzs=; 24:YdxpRbaaMbRGRGIxc95uPQvyF3tor7VncmBtipNQgnan/Dz76BKjbcJws8AgWQX29C1xs+BWedZni8Am+etThVn/P6taEgrt3/bEWu2GJXM=; 7:KInGeuZ8jwa1g75S4ilts3Dd6/St5qtrIiPJZIPgSKaEJ+47Y4d5L3q9wLtO7d+/dqN7/DJ0rXnRKkRuZFABFoGIy8/Fsnu+0F+FqnlrMr5Qnv9rPebQwRpz5QtKV6DYhevEryRtjY3AHcuh79EHDY9H1QI4FDkamNJY26LzcZ7PYpv9hUIdZE5reE98By1yHTTHe9OcTVPbbW6QRLhsi9hGN7cacqDGscJZQV7m2DEyqZ1l5EXmSZFkBbD9pDEi SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 20 Dec 2017 04:41:52.9934 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 9bc10c8d-1234-4878-4d1d-08d54763fdff X-MS-Exchange-CrossTenant-Id: 5afe0b00-7697-4969-b663-5eab37d5f47e X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=5afe0b00-7697-4969-b663-5eab37d5f47e; Ip=[192.88.168.50]; Helo=[tx30smr01.am.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY4PR03MB2693 Subject: [edk2] [PATCH edk2-platforms v2 3/4] Platform/NXP : Add Support for NOR Flash driver X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Adding support for NOR flash Driver Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Vabhav --- .../NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | 254 +++++++ Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c | 444 +++++++++++ Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf | 65 ++ Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c | 814 +++++++++++++++++= ++++ Platform/NXP/Include/Library/NorFlash.h | 222 ++++++ Silicon/NXP/Chassis/Chassis.c | 15 + Silicon/NXP/Chassis/Chassis.h | 7 + Silicon/NXP/Chassis/Chassis2/Soc.c | 1 + Silicon/NXP/Chassis/LS1043aSocLib.inf | 2 + 9 files changed, 1824 insertions(+) create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c create mode 100755 Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf create mode 100644 Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c create mode 100644 Platform/NXP/Include/Library/NorFlash.h diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/Platfo= rm/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c new file mode 100644 index 0000000..bad397f --- /dev/null +++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c @@ -0,0 +1,254 @@ +/** @NorFlashBlockIoDxe.c + + Based on NorFlash implementation available in ArmPlatformPkg/Drivers/Nor= FlashDxe/NorFlashBlockIoDxe.c + + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved. + Copyright 2017 NXP + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include +#include + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset +// +EFI_STATUS +EFIAPI +NorFlashBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + NOR_FLASH_INSTANCE *Instance; + + Instance =3D INSTANCE_FROM_BLKIO_THIS (This); + + DEBUG ((DEBUG_INFO, "NorFlashBlockIoReset (MediaId=3D0x%x)\n", + This->Media->MediaId)); + + return NorFlashPlatformReset (Instance->DeviceBaseAddress); +} + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks +// +EFI_STATUS +EFIAPI +NorFlashBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID *Buffer + ) +{ + NOR_FLASH_INSTANCE *Instance; + EFI_STATUS Status; + EFI_BLOCK_IO_MEDIA *Media; + UINTN NumBlocks; + UINT8 *pReadBuffer; + UINTN BlockCount; + UINTN BlockSizeInBytes; + EFI_LBA CurrentBlock; + + Status =3D EFI_SUCCESS; + + if ((This =3D=3D NULL) || (Buffer =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + Instance =3D INSTANCE_FROM_BLKIO_THIS (This); + Media =3D This->Media; + + if (Media =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a : Media is NULL\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + NumBlocks =3D ((UINTN)BufferSizeInBytes) / Instance->Media.BlockSize ; + + DEBUG ((DEBUG_BLKIO, "%a : (MediaId=3D0x%x, Lba=3D%ld, " + "BufferSize=3D0x%x bytes (%d kB)" + ", BufferPtr @ 0x%p)\n", + __FUNCTION__,MediaId, Lba, + BufferSizeInBytes, Buffer)); + + if (!Media) { + Status =3D EFI_INVALID_PARAMETER; + } + else if (!Media->MediaPresent) { + Status =3D EFI_NO_MEDIA; + } + else if (Media->MediaId !=3D MediaId) { + Status =3D EFI_MEDIA_CHANGED; + } + else if ((Media->IoAlign >=3D 2) && + (((UINTN)Buffer & (Media->IoAlign - 1)) !=3D 0)) { + Status =3D EFI_INVALID_PARAMETER; + } + else if (BufferSizeInBytes =3D=3D 0) { + // Return if we have not any byte to read + Status =3D EFI_SUCCESS; + } + else if ((BufferSizeInBytes % Media->BlockSize) !=3D 0) { + // The size of the buffer must be a multiple of the block size + DEBUG ((DEBUG_ERROR, "%a : BlockSize in bytes =3D 0x%x\n",__FUNCTION__, + BufferSizeInBytes)); + Status =3D EFI_INVALID_PARAMETER; + } else if ((Lba + NumBlocks - 1) > Media->LastBlock) { + // All blocks must be within the device + DEBUG ((DEBUG_ERROR, "%a : Read will exceed last block %d, %d, %d \n", + __FUNCTION__, Lba, NumBlocks, Media->LastBlock)); + Status =3D EFI_INVALID_PARAMETER; + } else { + BlockSizeInBytes =3D Instance->Media.BlockSize; + + /* Because the target *Buffer is a pointer to VOID, + * we must put all the data into a pointer + * to a proper data type, so use *pReadBuffer */ + pReadBuffer =3D (UINT8 *)Buffer; + + CurrentBlock =3D Lba; + // Read data block by Block + for (BlockCount =3D 0; BlockCount < NumBlocks; BlockCount++, CurrentBl= ock++, + pReadBuffer =3D pReadBuffer + BlockSizeInBytes) { + DEBUG ((DEBUG_BLKIO, "%a: Reading block #%d\n", + __FUNCTION__,(UINTN)CurrentBlock)); + + Status =3D NorFlashPlatformRead (Instance, CurrentBlock, (UINTN)0 , + BlockSizeInBytes,pReadBuffer); + if (EFI_ERROR (Status)) { + break; + } + } + } + DEBUG ((DEBUG_BLKIO,"%a: Exit Status =3D \"%r\".\n",__FUNCTION__,Status)= ); + + return Status; +} + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks +// +EFI_STATUS +EFIAPI +NorFlashBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID *Buffer + ) +{ + NOR_FLASH_INSTANCE *Instance; + EFI_STATUS Status; + EFI_BLOCK_IO_MEDIA *Media; + UINTN NumBlocks; + EFI_LBA CurrentBlock; + UINTN BlockSizeInBytes; + UINT32 BlockCount; + UINTN SectorAddress; + UINT8 *pWriteBuffer; + + Status =3D EFI_SUCCESS; + + if ((This =3D=3D NULL) || (Buffer =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + Instance =3D INSTANCE_FROM_BLKIO_THIS (This); + Media =3D This->Media; + + if (Media =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "%a : Media is NULL\n", __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + NumBlocks =3D ((UINTN)BufferSizeInBytes) / Instance->Media.BlockSize ; + + DEBUG ((DEBUG_BLKIO, "%a : (MediaId=3D0x%x, Lba=3D%ld, BufferSize=3D0x%x= " + "bytes (%d kB) BufferPtr @ 0x%08x)\n", + __FUNCTION__,MediaId, Lba,BufferSizeInBytes, Buffer)); + + if (!Media->MediaPresent) { + Status =3D EFI_NO_MEDIA; + } + else if (Media->MediaId !=3D MediaId) { + Status =3D EFI_MEDIA_CHANGED; + } + else if (Media->ReadOnly) { + Status =3D EFI_WRITE_PROTECTED; + } + else if (BufferSizeInBytes =3D=3D 0) { + Status =3D EFI_BAD_BUFFER_SIZE; + } + else if ((BufferSizeInBytes % Media->BlockSize) !=3D 0) { + // The size of the buffer must be a multiple of the block size + DEBUG ((DEBUG_ERROR, "%a : BlockSize in bytes =3D 0x%x\n",__FUNCTION__, + BufferSizeInBytes)); + Status =3D EFI_INVALID_PARAMETER; + } else if ((Lba + NumBlocks - 1) > Media->LastBlock) { + // All blocks must be within the device + DEBUG ((DEBUG_ERROR, "%a: Write will exceed last block %d, %d, %d \n", + __FUNCTION__,Lba, NumBlocks, Media->LastBlock)); + Status =3D EFI_INVALID_PARAMETER; + } else { + BlockSizeInBytes =3D Instance->Media.BlockSize; + + pWriteBuffer =3D (UINT8 *)Buffer; + + CurrentBlock =3D Lba; + // Program data block by Block + for (BlockCount =3D 0; BlockCount < NumBlocks; + BlockCount++, CurrentBlock++, + pWriteBuffer =3D (pWriteBuffer + BlockSizeInBytes)) { + DEBUG ((DEBUG_BLKIO, "%a: Writing block #%d\n", + __FUNCTION__,(UINTN)CurrentBlock)); + // Erase the Block(Sector) to be written to + SectorAddress =3D GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + CurrentBlock, + Instance->Media.BlockSize + ); + Status =3D NorFlashPlatformEraseSector (Instance, (UINTN)SectorAddre= ss); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Failed to erase Target 0x%x (0x%x) \n", + __FUNCTION__,SectorAddress, Status)); + break; + } + // Program Block(Sector) to be written to + Status =3D NorFlashWrite (Instance, CurrentBlock, (UINTN)0, + &BlockSizeInBytes, pWriteBuffer); + if (EFI_ERROR (Status)) { + break; + } + } + } + DEBUG ((DEBUG_BLKIO, "%a: Exit Status =3D \"%r\".\n",__FUNCTION__,Status= )); + return Status; +} + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks +// +EFI_STATUS +EFIAPI +NorFlashBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +{ + + DEBUG ((DEBUG_BLKIO, "%a NOT IMPLEMENTED (not required)\n", __FUNCTION__= )); + + // Nothing to do so just return without error + return EFI_SUCCESS; +} diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c b/Platform/NXP/= Drivers/NorFlashDxe/NorFlashDxe.c new file mode 100644 index 0000000..ca17001 --- /dev/null +++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.c @@ -0,0 +1,444 @@ +/** @file NorFlashDxe.c + + Based on NorFlash implementation available in ArmPlatformPkg/Drivers/Nor= FlashDxe/NorFlashDxe.c + + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved. + Copyright 2017 NXP + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#include +#include +#include +#include + +STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent; + +// +// Global variable declarations +// +NOR_FLASH_INSTANCE **mNorFlashInstances; +UINT32 mNorFlashDeviceCount; + +NOR_FLASH_INSTANCE mNorFlashInstanceTemplate =3D { + .Signature =3D NOR_FLASH_SIGNATURE, + .Initialized =3D FALSE, + .Initialize =3D NULL, + .StartLba =3D 0, + .BlockIoProtocol =3D { + .Revision =3D EFI_BLOCK_IO_PROTOCOL_REVISION2, + .Reset =3D NorFlashBlockIoReset, + .ReadBlocks =3D NorFlashBlockIoReadBlocks, + .WriteBlocks =3D NorFlashBlockIoWriteBlocks, + .FlushBlocks =3D NorFlashBlockIoFlushBlocks, + }, + + .Media =3D { + .RemovableMedia =3D FALSE, + .MediaPresent =3D TRUE, + .LogicalPartition =3D FALSE, + .ReadOnly =3D FALSE, + .WriteCaching =3D FALSE, + .IoAlign =3D 4, + .LowestAlignedLba =3D 0, + .LogicalBlocksPerPhysicalBlock =3D 1, + }, + + .FvbProtocol =3D { + .GetAttributes =3D FvbGetAttributes, + .SetAttributes =3D FvbSetAttributes, + .GetPhysicalAddress =3D FvbGetPhysicalAddress, + .GetBlockSize =3D FvbGetBlockSize, + .Read =3D FvbRead, + .Write =3D FvbWrite, + .EraseBlocks =3D FvbEraseBlocks, + .ParentHandle =3D NULL, + }, + .ShadowBuffer =3D NULL, + .DevicePath =3D { + .Vendor =3D { + .Header =3D { + .Type =3D HARDWARE_DEVICE_PATH, + .SubType =3D HW_VENDOR_DP, + .Length =3D {(UINT8)sizeof (VENDOR_DEVICE_PATH), + (UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8) } + }, + .Guid =3D EFI_CALLER_ID_GUID, // GUID ... NEED TO BE FILLED + }, + .End =3D { + .Type =3D END_DEVICE_PATH_TYPE, + .SubType =3D END_ENTIRE_DEVICE_PATH_SUBTYPE, + .Length =3D { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } + } + } +}; + +EFI_STATUS +NorFlashCreateInstance ( + IN UINTN NorFlashDeviceBase, + IN UINTN NorFlashRegionBase, + IN UINTN NorFlashSize, + IN UINT32 MediaId, + IN UINT32 BlockSize, + IN BOOLEAN SupportFvb, + OUT NOR_FLASH_INSTANCE** NorFlashInstance + ) +{ + EFI_STATUS Status; + NOR_FLASH_INSTANCE* Instance; + + ASSERT(NorFlashInstance !=3D NULL); + + Instance =3D AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INSTANCE), + &mNorFlashInstanceTemplate); + if (Instance =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Instance->DeviceBaseAddress =3D NorFlashDeviceBase; + Instance->RegionBaseAddress =3D NorFlashRegionBase; + Instance->Size =3D NorFlashSize; + + Instance->BlockIoProtocol.Media =3D &Instance->Media; + Instance->Media.MediaId =3D MediaId; + Instance->Media.BlockSize =3D BlockSize; + Instance->Media.LastBlock =3D (NorFlashSize / BlockSize)-1; + + Instance->ShadowBuffer =3D AllocateRuntimePool (BlockSize); + if (Instance->ShadowBuffer =3D=3D NULL) { + FreePool (Instance); + return EFI_OUT_OF_RESOURCES; + } + + if (SupportFvb) { + Instance->SupportFvb =3D TRUE; + Instance->Initialize =3D NorFlashFvbInitialize; + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &Instance->Handle, + &gEfiDevicePathProtocolGuid, &Instance->DevicePath, + &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (Instance->ShadowBuffer); + FreePool (Instance); + return Status; + } + } else { + Instance->Initialized =3D TRUE; + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &Instance->Handle, + &gEfiDevicePathProtocolGuid, &Instance->DevicePath, + &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + FreePool (Instance->ShadowBuffer); + FreePool (Instance); + return Status; + } + } + + *NorFlashInstance =3D Instance; + + return Status; +} + +/* + Write a full or portion of a block. + It must not span block boundaries; that is, + Offset + NumBytes <=3D Instance->Media.BlockSize. + */ +EFI_STATUS +NorFlashWrite ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer +) +{ + EFI_STATUS Status; + UINTN BlockSize; + BOOLEAN DoErase; + VOID *Source; + UINTN SectorAddress; + + Status =3D EFI_SUCCESS; + Source =3D NULL; + + DEBUG ((DEBUG_BLKIO, "%a(Parameters: Lba=3D%ld, Offset=3D0x%x, NumBytes= =3D0x%x, " + "Buffer @ 0x%08x)\n", __FUNCTION__, + Lba, Offset, *NumBytes, Buffer)); + + // The buffer must be valid + if (Buffer =3D=3D NULL) { + return EFI_INVALID_PARAMETER; + } + + // Detect WriteDisabled state + if (Instance->Media.ReadOnly =3D=3D TRUE) { + DEBUG ((DEBUG_ERROR, "NorFlashWrite: ERROR - Can not write: " + "Device is in WriteDisabled state.\n")); + // It is in WriteDisabled state, return an error right away + return EFI_ACCESS_DENIED; + } + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize =3D Instance->Media.BlockSize; + + // We must have some bytes to write + if ((*NumBytes =3D=3D 0) || (*NumBytes > BlockSize)) { + DEBUG ((DEBUG_ERROR, "NorFlashWrite: ERROR - EFI_BAD_BUFFER_SIZE: " + "(Offset=3D0x%x + NumBytes=3D0x%x) > BlockSize=3D0x%x\n", \ + Offset, *NumBytes, BlockSize )); + return EFI_BAD_BUFFER_SIZE; + } + + if (((Lba * BlockSize) + Offset + *NumBytes) > Instance->Size) { + DEBUG ((DEBUG_ERROR, "%a: ERROR - Write will exceed device size.\n", + __FUNCTION__)); + return EFI_INVALID_PARAMETER; + } + + // Check we did get some memory. Buffer is BlockSize. + if (Instance->ShadowBuffer =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n")); + return EFI_DEVICE_ERROR; + } + + SectorAddress =3D GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Lba, + Instance->Media.BlockSize + ); + + // Pick 128bytes as a good start for word operations as opposed to erasi= ng the + // block and writing the data regardless if an erase is really needed. + // It looks like most individual NV variable writes are smaller than 128= bytes. + if (*NumBytes <=3D 128) { + Source =3D Instance->ShadowBuffer; + //First Read the data into shadow buffer from location where data is t= o be written + Status =3D NorFlashPlatformRead ( + Instance, + Lba, + Offset, + *NumBytes, + Source + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: ERROR - Failed to " + "Read @ %p Status=3D%d\n", __FUNCTION__, + Offset + SectorAddress, Status)); + return Status; + } + // Check to see if we need to erase before programming the data into N= orFlash. + // If the destination bits are only changing from 1s to 0s we can + // just write. After a block is erased all bits in the block is set to= 1. + // If any byte requires us to erase we just give up and rewrite all of= it. + DoErase =3D TestBitSetClear (Source, Buffer, *NumBytes, TRUE); + + // if we got here then write all the data. Otherwise do the + // Erase-Write cycle. + if (!DoErase) { + Status =3D NorFlashPlatformWriteBuffer ( + Instance, + Lba, + Offset, + NumBytes, + Buffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: ERROR - Failed to " + "Write @ %p Status=3D%d\n", __FUNCTION__, + Offset + SectorAddress, Status)); + return Status; + } + return EFI_SUCCESS; + } + } + + // If we are not going to write full block, read block and then update b= ytes in it + if (*NumBytes !=3D BlockSize) { + // Read NorFlash Flash data into shadow buffer + Status =3D NorFlashBlockIoReadBlocks ( + &(Instance->BlockIoProtocol), + Instance->Media.MediaId, + Lba, + BlockSize, + Instance->ShadowBuffer + ); + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + // Put the data at the appropriate location inside the buffer area + CopyMem ((VOID *)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *Nu= mBytes); + } + //Erase Block + Status =3D NorFlashPlatformEraseSector (Instance, SectorAddress); + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + if (*NumBytes !=3D BlockSize) { + // Write the modified shadow buffer back to the NorFlash + Status =3D NorFlashPlatformWriteBuffer ( + Instance, + Lba, + 0, + &BlockSize, + Instance->ShadowBuffer + ); + } else { + // Write the Buffer to an entire block in NorFlash + Status =3D NorFlashPlatformWriteBuffer ( + Instance, + Lba, + 0, + &BlockSize, + Buffer + ); + } + if (EFI_ERROR (Status)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +NorFlashVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINTN Index; + + for (Index =3D 0; Index < mNorFlashDeviceCount; Index++) { + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->DeviceBase= Address); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->RegionBase= Address); + + // Convert BlockIo protocol + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoPro= tocol.FlushBlocks); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoPro= tocol.ReadBlocks); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoPro= tocol.Reset); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoPro= tocol.WriteBlocks); + + // Convert Fvb + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtoco= l.EraseBlocks); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtoco= l.GetAttributes); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtoco= l.GetBlockSize); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtoco= l.GetPhysicalAddress); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtoco= l.Read); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtoco= l.SetAttributes); + EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtoco= l.Write); + if (mNorFlashInstances[Index]->ShadowBuffer !=3D NULL) { + EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->ShadowB= uffer); + } + } + + return; +} + +EFI_STATUS +EFIAPI +NorFlashInitialise ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 Index; + NorFlashDescription* NorFlashDevices; + BOOLEAN ContainVariableStorage; + + ContainVariableStorage =3D 0; + + Status =3D NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDevic= eCount); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR,"%a : Failed to get Nor devices (0x%x)\n", + __FUNCTION__, Status)); + return Status; + } + + Status =3D NorFlashPlatformFlashGetAttributes (NorFlashDevices, + mNorFlashDeviceCount); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR,"%a : Failed to get NOR device attributes (0x%x)\n= ", + __FUNCTION__, Status)); + ASSERT_EFI_ERROR (Status); /* System becomes unusable if NOR flash is = not detected */ + return Status; + } + + mNorFlashInstances =3D AllocateRuntimePool ( + sizeof(NOR_FLASH_INSTANCE*) * mNorFlashDeviceC= ount); + if (mNorFlashInstances =3D=3D NULL) { + DEBUG ((DEBUG_ERROR,"%a : Failed to allocate runtime memory \n")); + return EFI_OUT_OF_RESOURCES; + } + + for (Index =3D 0; Index < mNorFlashDeviceCount; Index++) { + // Check if this NOR Flash device contain the variable storage region + ContainVariableStorage =3D + (NorFlashDevices[Index].RegionBaseAddress <=3D PcdGet64 (PcdFlashNvS= torageVariableBase64)) && + (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvSt= orageVariableSize) <=3D + NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].S= ize); + + Status =3D NorFlashCreateInstance ( + NorFlashDevices[Index].DeviceBaseAddress, + NorFlashDevices[Index].RegionBaseAddress, + NorFlashDevices[Index].Size, + Index, + NorFlashDevices[Index].BlockSize, + ContainVariableStorage, + &mNorFlashInstances[Index] + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"%a : Failed to create instance for " + "NorFlash[%d] (0x%x)\n",Index, Status)); + } + + } + + // + // Register for the virtual address change event + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + NorFlashVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mNorFlashVirtualAddrChangeEvent + ); + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR,"Failed to create VirtualAddressChange event 0x%x\= n", + Status)); + } + + return Status; +} diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf b/Platform/NX= P/Drivers/NorFlashDxe/NorFlashDxe.inf new file mode 100755 index 0000000..2da8a51 --- /dev/null +++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashDxe.inf @@ -0,0 +1,65 @@ +#/** @file +# +# Component description file for NorFlashDxe module +# +# Copyright 2017 NXP +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may = be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IM= PLIED. +# +#**/ + +[Defines] + INF_VERSION =3D 0x0001001A + BASE_NAME =3D NorFlashDxe + FILE_GUID =3D 616fe8d8-f4aa-42e0-a393-b332bdb2d3c1 + MODULE_TYPE =3D DXE_RUNTIME_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D NorFlashInitialise + +[Sources.common] + NorFlashDxe.c + NorFlashFvbDxe.c + NorFlashBlockIoDxe.c + +[Packages] + ArmPlatformPkg/ArmPlatformPkg.dec + Platform/NXP/NxpQoriqLs.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + DxeServicesTableLib + HobLib + NorFlashLib + UefiDriverEntryPoint + UefiRuntimeLib + +[Guids] + gEfiSystemNvDataFvGuid + gEfiVariableGuid + gEfiAuthenticatedVariableGuid + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiFirmwareVolumeBlockProtocolGuid + +[Pcd.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + +[Depex] + # + # NorFlashDxe must be loaded before VariableRuntimeDxe in case empty fla= sh needs populating with default values + # + BEFORE gVariableRuntimeDxeFileGuid diff --git a/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/Platform/N= XP/Drivers/NorFlashDxe/NorFlashFvbDxe.c new file mode 100644 index 0000000..f74ffc9 --- /dev/null +++ b/Platform/NXP/Drivers/NorFlashDxe/NorFlashFvbDxe.c @@ -0,0 +1,814 @@ +/*@NorFlashFvbDxe.c + + Based on NorFlash implementation available in ArmPlatformPkg/Drivers/NorF= lashDxe/NorFlashFvbDxe.c + + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved. + Copyright 2017 NXP + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD= License + which accompanies this distribution. The full text of the license may be= found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPL= IED. + + --*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +STATIC EFI_EVENT mFvbVirtualAddrChangeEvent; +STATIC UINTN mFlashNvStorageVariableBase; + +/// +/// The Firmware Volume Block Protocol is the low-level interface +/// to a firmware volume. File-level access to a firmware volume +/// should not be done using the Firmware Volume Block Protocol. +/// Normal access to a firmware volume must use the Firmware +/// Volume Protocol. Typically, only the file system driver that +/// produces the Firmware Volume Protocol will bind to the +/// Firmware Volume Block Protocol. +/// + +/** + Initialises the FV Header and Variable Store Header + to support variable operations. + + @param[in] Ptr - Location to initialise the headers + +**/ +EFI_STATUS +InitializeFvAndVariableStoreHeaders ( + IN NOR_FLASH_INSTANCE *Instance + ) +{ + EFI_STATUS Status; + VOID* Headers; + UINTN HeadersLength; + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + + if (!Instance->Initialized && Instance->Initialize) { + Instance->Initialize (Instance); + } + + HeadersLength =3D sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_B= LOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER); + Headers =3D AllocateZeroPool (HeadersLength); + if (Headers =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "Memory allocation failed for Headers \n")); + return EFI_OUT_OF_RESOURCES; + } + + // FirmwareVolumeHeader->FvLength is declared to have the Variable area = AND the FTW working area AND the FTW Spare contiguous. + ASSERT (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashN= vStorageVariableSize) =3D=3D PcdGet64 (PcdFlashNvStorageFtwWorkingBase64)); + ASSERT (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) + PcdGet32 (PcdFlas= hNvStorageFtwWorkingSize) =3D=3D PcdGet64 (PcdFlashNvStorageFtwSpareBase64)= ); + + // Check if the size of the area is at least one block size + ASSERT ((PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && (PcdGet32 (Pcd= FlashNvStorageVariableSize) / Instance->Media.BlockSize > 0)); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32 (P= cdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0)); + ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32 (Pcd= FlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0)); + + // Ensure the Variable area Base Addresses are aligned on a block size b= oundaries + ASSERT (PcdGet64 (PcdFlashNvStorageVariableBase64) % Instance->Media.Blo= ckSize =3D=3D 0); + ASSERT (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) % Instance->Media.B= lockSize =3D=3D 0); + ASSERT (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) % Instance->Media.Blo= ckSize =3D=3D 0); + + // + // 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_FVB_ATTRIBUTES_2) ( + EFI_FVB2_READ_ENABLED_CAP | //= Reads may be enabled + EFI_FVB2_READ_STATUS | //= Reads are currently 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 take this value (i.e. '1') + EFI_FVB2_WRITE_STATUS | //= Writes are currently enabled + EFI_FVB2_WRITE_ENABLED_CAP //= Writes may be enabled + ); + FirmwareVolumeHeader->HeaderLength =3D sizeof (EFI_FIRMWARE_VOLUME_HEADE= R) + sizeof (EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision =3D EFI_FVH_REVISION; + //i.e. if blocks are 0-5 then last block =3D 5, total blocks =3D 6 + FirmwareVolumeHeader->BlockMap[0].NumBlocks =3D Instance->Media.LastBloc= k + 1; + FirmwareVolumeHeader->BlockMap[0].Length =3D Instance->Media.BlockS= ize; + FirmwareVolumeHeader->BlockMap[1].NumBlocks =3D 0; + FirmwareVolumeHeader->BlockMap[1].Length =3D 0; + FirmwareVolumeHeader->Checksum =3D CalculateCheckSum16 ((UINT16*)Firmwar= eVolumeHeader,FirmwareVolumeHeader->HeaderLength); + + // + // VARIABLE_STORE_HEADER + // + VariableStoreHeader =3D (VARIABLE_STORE_HEADER*)((UINTN)Headers + Firmwa= reVolumeHeader->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; + + // Install the combined super-header in the NorFlash + Status =3D FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Heade= rs); + + FreePool (Headers); + return Status; +} + +/** + Check the integrity of firmware volume header. + + @param[in] FwVolHeader - A pointer to a firmware volume header + + @retval EFI_SUCCESS - The firmware volume is consistent + @retval EFI_NOT_FOUND - The firmware volume has been corrupted. + +**/ +EFI_STATUS +ValidateFvHeader ( + IN NOR_FLASH_INSTANCE *Instance + ) +{ + UINT16 Checksum; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + + FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER*)mFlashNvStorageVariableBase; + + FvLength =3D PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFla= shNvStorageFtwWorkingSize) + + 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_ERROR, "%a: No Firmware Volume header present\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) = =3D=3D FALSE ) { + DEBUG ((DEBUG_ERROR, "%a: Firmware Volume Guid non-compatible\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + // Verify the header checksum + Checksum =3D CalculateSum16 ((UINT16*)FwVolHeader, FwVolHeader->HeaderLe= ngth); + if (Checksum !=3D 0) { + DEBUG ((DEBUG_ERROR, "%a: FV checksum is invalid (Checksum:0x%X)\n", + __FUNCTION__, Checksum)); + return EFI_NOT_FOUND; + } + + VariableStoreHeader =3D (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + + FwVolHeader->HeaderLength); + + // Check the Variable Store Guid + if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) && + !CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVar= iableGuid)) { + DEBUG ((DEBUG_ERROR, "%a: Variable Store Guid non-compatible\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + VariableStoreLength =3D PcdGet32 (PcdFlashNvStorageVariableSize) - FwVol= Header->HeaderLength; + if (VariableStoreHeader->Size !=3D VariableStoreLength) { + DEBUG ((DEBUG_ERROR, "%a: Variable Store Length does not match\n", + __FUNCTION__)); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + The GetAttributes() function retrieves the attributes and + current settings of the block. + + @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL ins= tance. + + @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the attribut= es 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. + + **/ +EFI_STATUS +EFIAPI +FvbGetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes; + NOR_FLASH_INSTANCE *Instance; + + Instance =3D INSTANCE_FROM_FVB_THIS (This); + + FlashFvbAttributes =3D (EFI_FVB_ATTRIBUTES_2) ( + + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bit= s into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this valu= e (i.e. '1') + + ); + + // Check if it is write protected + if (Instance->Media.ReadOnly !=3D TRUE) { + + FlashFvbAttributes =3D FlashFvbAttributes | + EFI_FVB2_WRITE_STATUS | // Writes are curren= tly enabled + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be ena= bled + } + + *Attributes =3D FlashFvbAttributes; + + DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes)); + + 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_BLOCK2_= PROTOCOL instance. + + @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 E= FI_FIRMWARE_VOLUME_HEADER. + + @retval EFI_SUCCESS The firmware volume attributes were retur= ned. + + @retval EFI_INVALID_PARAMETER The attributes requested are in conflict = with the capabilities + as declared in the firmware volume header. + + **/ +EFI_STATUS +EFIAPI +FvbSetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n",*Attrib= utes)); + return EFI_UNSUPPORTED; +} + +/** + 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_BLOCK2_PROTOC= OL instance. + + @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_NOT_SUPPORTED The firmware volume is not memory mapped. + + **/ +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + *Address =3D mFlashNvStorageVariableBase; + 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_BLOCK2_= PROTOCOL instance. + + @param Lba Indicates the block for which to return t= he size. + + @param BlockSize Pointer to a caller-allocated UINTN in wh= ich + 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 retu= rned. + + @retval EFI_INVALID_PARAMETER The requested LBA is out of range. + + **/ +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +{ + EFI_STATUS Status; + NOR_FLASH_INSTANCE *Instance; + + Instance =3D INSTANCE_FROM_FVB_THIS(This); + + DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=3D%ld, BlockSize=3D0x%x, LastB= lock=3D%ld)\n", + Lba, Instance->Media.BlockSize, Instance->Media.LastBlock)); + + if (Lba > Instance->Media.LastBlock) { + DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%= ld)\n", + __FUNCTION__, Lba, Instance->Media.LastBlock)); + Status =3D EFI_INVALID_PARAMETER; + } else { + // In this platform each NorFlash device has equal sized blocks. + *BlockSize =3D (UINTN) Instance->Media.BlockSize; + *NumberOfBlocks =3D (UINTN) (Instance->Media.LastBlock - Lba + 1); + + DEBUG ((DEBUG_BLKIO, "%a : *BlockSize=3D0x%x, *NumberOfBlocks=3D0x%x.\= n", + __FUNCTION__, *BlockSize, *NumberOfBlocks)); + + Status =3D EFI_SUCCESS; + } + + return Status; +} + +/** + Reads the specified number of bytes into a buffer from the specified bloc= k. + + 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_BLOCK2_PROT= OCOL instance. + + @param Lba The starting logical block index from which t= o read. + + @param Offset Offset into the block at which to begin readi= ng. + + @param NumBytes Pointer to a UINTN. + At entry, *NumBytes contains the total size o= f the buffer. + At exit, *NumBytes contains the total number = of bytes read. + + @param Buffer Pointer to a caller-allocated buffer that wil= l be used + to hold the data that is read. + + @retval EFI_SUCCESS The firmware volume was read successfully, a= nd 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 st= ate. + + @retval EFI_DEVICE_ERROR The block device is not functioning correctly= and could not be read. + + **/ +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +{ + UINTN BlockSize; + NOR_FLASH_INSTANCE *Instance; + + Instance =3D INSTANCE_FROM_FVB_THIS (This); + + DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=3D%ld, Offset=3D0x%x, " + "*NumBytes=3D0x%x, Buffer @ 0x%08x)\n", + Instance->StartLba + Lba, Offset, *NumBytes, Buffer)); + + if (!Instance->Initialized && Instance->Initialize) { + Instance->Initialize(Instance); + } + + // Cache the block size to avoid de-referencing pointers all the time + BlockSize =3D Instance->Media.BlockSize; + + DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=3D0x%x + NumBytes=3D0x%x= ) <=3D " + "BlockSize=3D0x%x\n", Offset, *NumBytes, BlockSize )); + + // The read must not span block boundaries. + while (Offset >=3D BlockSize) { + Offset -=3D BlockSize; + Lba++; + } + + if ((Instance->StartLba + Lba) > Instance->Media.LastBlock) { + DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%= ld)\n", + __FUNCTION__, Lba, Instance->Media.LastBlock)); + return EFI_INVALID_PARAMETER; + } + + if ((Offset + *NumBytes) > BlockSize) { + *NumBytes =3D BlockSize-Offset; + } + + return NorFlashPlatformRead (Instance, Instance->StartLba + Lba, + Offset, *NumBytes, Buffer); +} + +/** + 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_BLOCK2_PROT= OCOL instance. + + @param Lba The starting logical block index to write to. + + @param Offset Offset into the block at which to begin writi= ng. + + @param NumBytes The pointer to a UINTN. + At entry, *NumBytes contains the total size o= f 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 boundar= y. + On output, NumBytes contains the total number= of bytes + actually written. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled s= tate. + + @retval EFI_DEVICE_ERROR The block device is malfunctioning and could = not be written. + + + **/ +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + NOR_FLASH_INSTANCE *Instance; + UINTN BlockSize; + + Instance =3D INSTANCE_FROM_FVB_THIS (This); + // Cache the block size to avoid de-referencing pointers all the time + BlockSize =3D Instance->Media.BlockSize; + + if (!Instance->Initialized && Instance->Initialize) { + Instance->Initialize(Instance); + } + + // The write must not span block boundaries. + while(Offset >=3D BlockSize) { + Offset -=3D BlockSize; + Lba++; + } + + if ((Instance->StartLba + Lba) > Instance->Media.LastBlock) { + DEBUG ((DEBUG_ERROR, "%a : Parameter LBA %ld is beyond the last Lba (%= ld)\n", + __FUNCTION__, Lba, Instance->Media.LastBlock)); + return EFI_INVALID_PARAMETER; + } + + if ((Offset + *NumBytes) > BlockSize) { + *NumBytes =3D BlockSize-Offset; + } + + return NorFlashWrite (Instance, Instance->StartLba + Lba, + Offset, NumBytes, Buffer); +} + +/** + Erases and initialises 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_BLOCK2_= PROTOCOL + instance. + + @param ... The variable argument list is a list of t= uples. + Each tuple describes a range of LBAs to e= rase + and consists of the following: + - An EFI_LBA that indicates the starting = LBA + - A UINTN that indicates the number of bl= ocks to erase. + + The list is terminated with an EFI_LBA_LI= ST_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_L= IST_TERMINATOR); + + @retval EFI_SUCCESS The erase request successfully completed. + + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabl= ed state. + + @retval EFI_DEVICE_ERROR The block device is not functioning corre= ctly and could not be written. + The firmware device may have been partial= ly erased. + + @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the var= iable argument list do + not exist in the firmware volume. + + **/ +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ) +{ + EFI_STATUS Status; + VA_LIST Args; + UINTN BlockAddress; // Physical address of Lba to erase + EFI_LBA StartingLba; // Lba from which we start erasing + UINTN NumOfLba; // Number of Lba blocks to erase + NOR_FLASH_INSTANCE *Instance; + + Instance =3D INSTANCE_FROM_FVB_THIS (This); + + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n")); + + Status =3D EFI_SUCCESS; + + // Detect WriteDisabled state + if (Instance->Media.ReadOnly =3D=3D TRUE) { + // Firmware volume is in WriteDisabled state + DEBUG ((DEBUG_ERROR, "%a : Device is in WriteDisabled state\n")); + return EFI_ACCESS_DENIED; + } + + // Before erasing, check the entire list of parameters to + // ensure all specified blocks are valid + + VA_START (Args, This); + do { + // Get the Lba from which we start erasing + StartingLba =3D VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + //Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba =3D VA_ARG (Args, UINT32); + + // All blocks must be within range + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Check if: ( StartingLba=3D%ld + " + "NumOfLba=3D%d - 1 ) > LastBlock=3D%ld.\n", + Instance->StartLba + StartingLba, NumOfLba, + Instance->Media.LastBlock)); + if ((NumOfLba =3D=3D 0) || + ((Instance->StartLba + StartingLba + NumOfLba - 1) > + Instance->Media.LastBlock)) { + VA_END (Args); + DEBUG ((DEBUG_ERROR, "%a : Lba range goes past the last Lba\n")); + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + } while (TRUE); + VA_END (Args); + + // + // To get here, all must be ok, so start erasing + // + VA_START (Args, This); + do { + // Get the Lba from which we start erasing + StartingLba =3D VA_ARG (Args, EFI_LBA); + + // Have we reached the end of the list? + if (StartingLba =3D=3D EFI_LBA_LIST_TERMINATOR) { + // Exit the while loop + break; + } + + // How many Lba blocks are we requested to erase? + NumOfLba =3D VA_ARG (Args, UINT32); + + // Go through each one and erase it + while (NumOfLba > 0) { + + // Get the physical address of Lba to erase + BlockAddress =3D GET_NOR_BLOCK_ADDRESS ( + Instance->RegionBaseAddress, + Instance->StartLba + StartingLba, + Instance->Media.BlockSize + ); + + // Erase it + DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=3D%ld @ 0x%08x.\n", + Instance->StartLba + StartingLba, BlockAddress)); + Status =3D NorFlashPlatformEraseSector(Instance, BlockAddress); + if (EFI_ERROR (Status)) { + VA_END (Args); + Status =3D EFI_DEVICE_ERROR; + goto EXIT; + } + + // Move to the next Lba + StartingLba++; + NumOfLba--; + } + } while (TRUE); + VA_END (Args); + +EXIT: + return Status; +} + +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +FvbVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase); + return; +} + +EFI_STATUS +EFIAPI +NorFlashFvbInitialize ( + IN NOR_FLASH_INSTANCE* Instance + ) +{ + EFI_STATUS Status; + UINT32 FvbNumLba; + EFI_BOOT_MODE BootMode; + UINTN RuntimeMmioRegionSize; + + DEBUG ((DEBUG_BLKIO,"NorFlashFvbInitialize\n")); + + Instance->Initialized =3D TRUE; + mFlashNvStorageVariableBase =3D FixedPcdGet64 (PcdFlashNvStorageVariable= Base64); + + // Set the index of the first LBA for the FVB + Instance->StartLba =3D (PcdGet64 (PcdFlashNvStorageVariableBase64) - Ins= tance->RegionBaseAddress) / Instance->Media.BlockSize; + + BootMode =3D GetBootModeHob (); + if (BootMode =3D=3D BOOT_WITH_DEFAULT_SETTINGS) { + Status =3D EFI_INVALID_PARAMETER; + } + else { + // Determine if there is a valid header at the beginning of the NorFla= sh + Status =3D ValidateFvHeader (Instance); + } + + // Install the Default FVB header if required + 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__= )); + DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this volume.\n", + __FUNCTION__)); + + // Erase all the NorFlash that is reserved for variable storage + FvbNumLba =3D (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (Pc= dFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) = / Instance->Media.BlockSize; + + Status =3D FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumL= ba, EFI_LBA_LIST_TERMINATOR); + if (EFI_ERROR (Status)) + return Status; + + // Install all appropriate headers + Status =3D InitializeFvAndVariableStoreHeaders (Instance); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME + // + + // Note: all the NOR Flash region needs to be reserved into the UEFI Run= time memory; + // even if we only use the small block region at the top of the NO= R Flash. + // The reason is when the NOR Flash memory is set into program mod= e, the command + // is written as the base of the flash region (ie: Instance->Devic= eBaseAddress) + RuntimeMmioRegionSize =3D (Instance->RegionBaseAddress - Instance->Devic= eBaseAddress) + Instance->Size; + + Status =3D gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + Instance->DeviceBaseAddress, RuntimeMmioRegionSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status =3D gDS->SetMemorySpaceAttributes ( + Instance->DeviceBaseAddress, RuntimeMmioRegionSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + ASSERT_EFI_ERROR (Status); + + // + // Register for the virtual address change event + // + Status =3D gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FvbVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mFvbVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/Platform/NXP/Include/Library/NorFlash.h b/Platform/NXP/Include= /Library/NorFlash.h new file mode 100644 index 0000000..37099ff --- /dev/null +++ b/Platform/NXP/Include/Library/NorFlash.h @@ -0,0 +1,222 @@ +/** @NorFlash.h + + Based on NOR flash access APIs used in ArmPlatformPkg/Drivers/NorFlashDx= e/NorFlashDxe.h + + Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved. + Copyright 2017 NXP + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. + +**/ + +#ifndef __NOR_FLASH_H__ +#define __NOR_FLASH_H__ + +#include +#include + +#define NOR_FLASH_ERASE_RETRY 10 + +#define GET_NOR_BLOCK_ADDRESS(BaseAddr,Lba,LbaSize) ( BaseAddr + (UINTN)((= Lba) * LbaSize) ) + +#define NOR_FLASH_SIGNATURE SIGNATURE_32('n', 'o', '= r', '0') +#define INSTANCE_FROM_FVB_THIS(a) CR(a, NOR_FLASH_INSTANCE= , FvbProtocol, NOR_FLASH_SIGNATURE) +#define INSTANCE_FROM_BLKIO_THIS(a) CR(a, NOR_FLASH_INSTANCE= , BlockIoProtocol, NOR_FLASH_SIGNATURE) + +typedef struct _NOR_FLASH_INSTANCE NOR_FLASH_INSTANCE; + +typedef EFI_STATUS (*NOR_FLASH_INITIALIZE) (NOR_FLASH_INSTANCE* Ins= tance); + +typedef struct { + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL End; +} NOR_FLASH_DEVICE_PATH; + +struct _NOR_FLASH_INSTANCE { + UINT32 Signature; + EFI_HANDLE Handle; + BOOLEAN Initialized; + NOR_FLASH_INITIALIZE Initialize; + UINTN DeviceBaseAddress; + UINTN RegionBaseAddress; + UINTN Size; + EFI_LBA StartLba; + EFI_BLOCK_IO_PROTOCOL BlockIoProtocol; + EFI_BLOCK_IO_MEDIA Media; + BOOLEAN SupportFvb; + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + VOID* ShadowBuffer; + NOR_FLASH_DEVICE_PATH DevicePath; +}; + +// +// NorFlashLib.c related +// + +EFI_STATUS +NorFlashPlatformWriteBuffer ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +NorFlashPlatformEraseSector ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN SectorAddress + ); + +EFI_STATUS +NorFlashPlatformControllerInitialization ( + VOID + ); + +EFI_STATUS +NorFlashPlatformRead ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN BufferSizeInBytes, + OUT UINT8 *Buffer + ); + +EFI_STATUS +NorFlashPlatformReset ( + IN UINTN Instance + ); + +extern CONST EFI_GUID* CONST mNorFlashVariableGuid; + +// +// NorFlashFvbDxe.c +// + +EFI_STATUS +EFIAPI +NorFlashFvbInitialize ( + IN NOR_FLASH_INSTANCE* Instance + ); + +EFI_STATUS +EFIAPI +FvbGetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbSetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +EFI_STATUS +EFIAPI +FvbGetBlockSize( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ); + +EFI_STATUS +EFIAPI +FvbRead( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbWrite( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbEraseBlocks( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ); +// +// NorFlashBlockIoDxe.c +// + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset +// +EFI_STATUS +EFIAPI +NorFlashBlockIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.ReadBlocks +// +EFI_STATUS +EFIAPI +NorFlashBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + OUT VOID *Buffer +); + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.WriteBlocks +// +EFI_STATUS +EFIAPI +NorFlashBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSizeInBytes, + IN VOID *Buffer +); + +// +// BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.FlushBlocks +// +EFI_STATUS +EFIAPI +NorFlashBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This +); + +EFI_STATUS +NorFlashWrite ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer +); + +#endif /* __NOR_FLASH_DXE_H__ */ diff --git a/Silicon/NXP/Chassis/Chassis.c b/Silicon/NXP/Chassis/Chassis.c index a6a77c2..ab0076f 100644 --- a/Silicon/NXP/Chassis/Chassis.c +++ b/Silicon/NXP/Chassis/Chassis.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -411,3 +412,17 @@ CalculateI2cClockRate ( =20 return SocSysInfo.FreqSystemBus; } + +/** + Initialize IFC device timings +**/ +VOID +IfcInit ( + VOID + ) +{ + // NOR Init + if (FixedPcdGet64 (PcdIfcNorEnabled)) { + IfcNorInit (); + } +} diff --git a/Silicon/NXP/Chassis/Chassis.h b/Silicon/NXP/Chassis/Chassis.h index 4bdb4d0..c8057f0 100644 --- a/Silicon/NXP/Chassis/Chassis.h +++ b/Silicon/NXP/Chassis/Chassis.h @@ -141,4 +141,11 @@ CpuNumCores ( VOID ); =20 +/** + Initialize IFC Device timings + **/ +VOID +IfcInit ( + VOID + ); #endif /* __CHASSIS_H__ */ diff --git a/Silicon/NXP/Chassis/Chassis2/Soc.c b/Silicon/NXP/Chassis/Chass= is2/Soc.c index 2f57929..847bbc2 100644 --- a/Silicon/NXP/Chassis/Chassis2/Soc.c +++ b/Silicon/NXP/Chassis/Chassis2/Soc.c @@ -140,6 +140,7 @@ SocInit ( =20 PrintCpuInfo (); PrintRCW (); + IfcInit (); =20 return; } diff --git a/Silicon/NXP/Chassis/LS1043aSocLib.inf b/Silicon/NXP/Chassis/LS= 1043aSocLib.inf index e6e7ac4..b11fdc2 100644 --- a/Silicon/NXP/Chassis/LS1043aSocLib.inf +++ b/Silicon/NXP/Chassis/LS1043aSocLib.inf @@ -32,6 +32,7 @@ BeIoLib DebugLib SerialPortLib + NorFlashLib =20 [Sources.common] Chassis.c @@ -45,3 +46,4 @@ gNxpQoriqLsTokenSpaceGuid.PcdSerdes2Enabled gNxpQoriqLsTokenSpaceGuid.PcdGurBigEndian gNxpQoriqLsTokenSpaceGuid.PcdClkBaseAddr + gNxpQoriqLsTokenSpaceGuid.PcdIfcNorEnabled --=20 1.9.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel