From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail05.groups.io (mail05.groups.io [45.79.224.7]) by spool.mail.gandi.net (Postfix) with ESMTPS id AC2DD74004D for ; Thu, 16 May 2024 15:18:59 +0000 (UTC) DKIM-Signature: a=rsa-sha256; bh=uNV+NxlSl8E+MK+lQk0hElHXSCd9ST6YJIAnaKqTCQs=; c=relaxed/simple; d=groups.io; h=Received-SPF:Authentication-Results-Original:Message-ID:Date:User-Agent:Subject:To:Cc:References:From:In-Reply-To:MIME-Version:NoDisclaimer:Original-Authentication-Results:Precedence:List-Subscribe:List-Help:Sender:List-Id:Mailing-List:Delivered-To:Resent-Date:Resent-From:Reply-To:List-Unsubscribe-Post:List-Unsubscribe:Content-Language:Content-Type:Content-Transfer-Encoding; s=20240206; t=1715872738; v=1; b=ZNbKh4Ypt+Muy361dnQs8IU3+NqAcUOJlO74bjPSJSrYUf3PkXs/z0IhBjh1TTt+4vP8zFa0 XC6WJWF40mOA5hjq3QySWGJMHjx4W9IjjOtpepT3ejm/+RHLj1sHiGZnnEaO/uYczrcsFlIYxXd 4fg3Ol0uMoBUs7402K2B697qXew9s0XZr+e0pDrVuoti5hmAO/gHT7f4KIdP29ictd/LLJJyHMy SEuKQE9cOeVxCb5WLuibcG49Ck0R6Atz51EXnrmdnAON3hbbgmJY/z6Z1Nre0BbEOf99mVJNHYr 5nNXA1KUorFnTiROIveyxm3BOxGNkhcpTZW5WXWfPcJHQ== X-Received: by 127.0.0.2 with SMTP id yO35YY7687511x8u225g0l25; Thu, 16 May 2024 08:18:58 -0700 X-Received: from EUR01-DB5-obe.outbound.protection.outlook.com (EUR01-DB5-obe.outbound.protection.outlook.com [40.107.15.41]) by mx.groups.io with SMTP id smtpd.web11.16892.1715872736886908725 for ; Thu, 16 May 2024 08:18:57 -0700 X-Received: from DUZPR01CA0141.eurprd01.prod.exchangelabs.com (2603:10a6:10:4bd::28) by GVXPR08MB11132.eurprd08.prod.outlook.com (2603:10a6:150:1fd::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7587.27; Thu, 16 May 2024 15:18:50 +0000 X-Received: from DB1PEPF000509F4.eurprd02.prod.outlook.com (2603:10a6:10:4bd:cafe::bc) by DUZPR01CA0141.outlook.office365.com (2603:10a6:10:4bd::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7587.27 via Frontend Transport; Thu, 16 May 2024 15:18:50 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=arm.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C X-Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DB1PEPF000509F4.mail.protection.outlook.com (10.167.242.150) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.7587.21 via Frontend Transport; Thu, 16 May 2024 15:18:49 +0000 X-Received: ("Tessian outbound 082664cc04c1:v315"); Thu, 16 May 2024 15:18:49 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: f1a3739a1ea54dcf X-CR-MTA-TID: 64aa7808 X-Received: from b9182417e637.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 03A3BD94-AB8B-448F-BFC4-4E9B3359602B.1; Thu, 16 May 2024 15:18:42 +0000 X-Received: from EUR05-DB8-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id b9182417e637.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Thu, 16 May 2024 15:18:42 +0000 Authentication-Results-Original: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-Received: from AS8PR08MB6806.eurprd08.prod.outlook.com (2603:10a6:20b:39b::12) by DBBPR08MB10604.eurprd08.prod.outlook.com (2603:10a6:10:536::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7587.27; Thu, 16 May 2024 15:18:41 +0000 X-Received: from AS8PR08MB6806.eurprd08.prod.outlook.com ([fe80::1e13:dc65:224e:219c]) by AS8PR08MB6806.eurprd08.prod.outlook.com ([fe80::1e13:dc65:224e:219c%5]) with mapi id 15.20.7587.028; Thu, 16 May 2024 15:18:41 +0000 Message-ID: <37c46a2a-9372-41cb-9e91-b883957cba7b@arm.com> Date: Thu, 16 May 2024 16:18:37 +0100 User-Agent: Mozilla Thunderbird Subject: Re: [edk2-devel] [PATCH RESEND edk2-platforms][PATCH V2 06/14] Platform/ARM: Add P30NorFlashDeviceLib Library To: Sahil Kaushal , devel@edk2.groups.io Cc: Ard Biesheuvel , Leif Lindholm , sahil , "nd@arm.com" References: <20240423055638.1271531-1-Sahil.Kaushal@arm.com> <20240423055638.1271531-7-Sahil.Kaushal@arm.com> From: "Sami Mujawar" In-Reply-To: <20240423055638.1271531-7-Sahil.Kaushal@arm.com> X-ClientProxiedBy: LO4P265CA0297.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:38f::6) To AS8PR08MB6806.eurprd08.prod.outlook.com (2603:10a6:20b:39b::12) MIME-Version: 1.0 X-MS-TrafficTypeDiagnostic: AS8PR08MB6806:EE_|DBBPR08MB10604:EE_|DB1PEPF000509F4:EE_|GVXPR08MB11132:EE_ X-MS-Office365-Filtering-Correlation-Id: 09d92ccb-8514-48cb-d4de-08dc75bb7d33 x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0;ARA:13230031|376005|1800799015|366007; X-Microsoft-Antispam-Message-Info-Original: =?utf-8?B?WWhhNTh4WnhFL0pYcFFPS0JYd3JWclRxL2pqQVlkbFZ0cmdXV2h5ck45SkRY?= =?utf-8?B?TkdTdEhhc0NZQUdvcUhha0M5alU2OTNhUVZQM3NkbTZQOHBUMDk5NjVhK0ZG?= =?utf-8?B?OTdGOFVKSzZ1cm1jNHBObFBLdmYwZGRHRHFOSys3Vk9wQzBySGVEMWlJQTdi?= =?utf-8?B?QjBaVXg3eXBycndVbGJPdzRZRVlmVGNqMjVmdGFmMHdHVkE0eTA1NkxyNXdk?= =?utf-8?B?b0VydUhNc2pYQXN6elF4MEh3SjZFdzdRNlU0bFZaYnJZYUZpSU1LV0FsQ0Vj?= =?utf-8?B?ZC9sWnVPZ09BTy9BODQ5WldCUENUcmVMYk9lZC9RWjlmV2VqZzJpdy8xaXRN?= =?utf-8?B?UWIzSVVTbU1sMytLVDZnYTVFUmxETVpvVWtaNG1WNksybXkzM0MrYlVkanh0?= =?utf-8?B?azFhTjM0L1lGQ1FYYzB2QUZ4SE45aXlsYS9NVFVXS3pUYXJDTWZNZDN5eGd3?= =?utf-8?B?UkVhdnl3dVNZb2t6M1AydXJVc2N6WkVSbXFteEhhTHpYcWQvUWo0bEdNeTlW?= =?utf-8?B?UXNDdkJHc3JhKzd5eVU0V0o3VFA3MmFhSnJiQ0NHdEJBbDRNZjcydHJ2VmpN?= =?utf-8?B?R3pwYVJ2YjgydDZkSERzZUp5OTdwenhucGIrWFNEWEhUMkg1ZE9LMGs5YnRI?= =?utf-8?B?WDZMTnFBQ0ZMZjR2M2dtbmdIL2lTU1lOQStoTHNPbjZpMEdPd3RnQ3FxVnRk?= =?utf-8?B?TnUvRkw3RFcxekQwRjFKMDVmMTFQb3dFNUJ5WTFLWUx5VzUzbkFKRzJQNW9R?= =?utf-8?B?d2lHcy9MUFlVM0U1K2pEaU9MZnZkRGc4YUxaRmxib2k5RGZ1eXJPOXdvc2xu?= =?utf-8?B?SWZZYkdWejNMK0Z6T2pDNkZnN2dVdlp6dUtLdmdNaWxwaWhyOUN2NUFVc0hP?= =?utf-8?B?SkI0SHE1ZUljM045VEhmZzRjeFJ6QW9XR0FWSkxWQzQxdHJPM3pIbGlaSnB6?= =?utf-8?B?d0hDcDZuY1FNRXQ1ZjRIaDBjZ0Z5bUtDOTdHR0Zua1Y4WTkyVzhYMm1YdnU2?= =?utf-8?B?U0ZzTHgzOThncFdvRmNmQXdRWjVVY0t5VEZTNjY3dXB2VmNsL1ZCSlBrUnlz?= =?utf-8?B?ZE96SWt3azRlRzRtZkduQTVYRUdXZFV4Q084NGMvLzBqY3BLSVYzc1Z3SUVr?= =?utf-8?B?MEZLazU5OVN1b25jdEMwdFdRVm1nNVhlNVJnc1dWUTJyZlE1SHVKVHVmelB6?= =?utf-8?B?RWk5MUplc2czRm11WCsrTmN4bDJSZFZDMzYrcThGVnJIK2dDNmxMTHJLdWpL?= =?utf-8?B?eVBBd0RvcERYQ0Z2Qk1WcWM0RjQwL3ZtLzQ4Uk8xWkV1UTJmeFIvTUhNME5Q?= =?utf-8?B?ZmN3YWpwKzdZbmltYUxUTTFGK28zTkhDOURpWUdRSDRnNVRmYWhJVWRmK2Ey?= =?utf-8?B?RzB2eXNRVUNWQVlwS1B5S1ZzM0lDRUllcmdtbFIveFhMT0c4WWtKaDJNNDhm?= =?utf-8?B?bkt3U01Eb0doZUVoQ0lhQUxobkIwdW85VUNBY3RhVHZ1VTlxNFJrcTFXcy9Z?= =?utf-8?B?dEJ5V1dRZ2FzbTRHU1FmUWpOUVQ1MDgxTHloM1NHSGEwazdtK01xcXAwc1V2?= =?utf-8?B?NEM0bWluakxON1lScHVIZFJ1V08vdlpnZ2FocFRSU1U4TmNOa2ZJbE4rOEZK?= =?utf-8?B?VXZuNTNDa2twcGx5STJXUWpJUndsRFBVcWVwQkJ3OENnbWVaSWQ2blRJQ20x?= =?utf-8?B?Q1E5MlJlRjhPU1oxRXd4dE9HZURXR0dnL1pzTGIybXlTWHFub1A4cDVnPT0=?= X-Forefront-Antispam-Report-Untrusted: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AS8PR08MB6806.eurprd08.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230031)(376005)(1800799015)(366007);DIR:OUT;SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: DBBPR08MB10604 Original-Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=arm.com; X-EOPAttributedMessage: 0 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DB1PEPF000509F4.eurprd02.prod.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 7ed012cd-66fd-46d0-bea2-08dc75bb77cc X-Microsoft-Antispam-Message-Info: =?utf-8?B?bjkxcGhNczVaUXFSclFHbEZaYXRYM0dwNEFMY21YTnV2cHhkUHY4QUdnWUdC?= =?utf-8?B?REtnYVNiZWlCMXBWRHJRL1dNWGZkWWhoM0dQNjRxeGVtRFZERWNkMFl5MWRF?= =?utf-8?B?UTFWTmkraWZzaWhZZjBHbzVSZUhzQmFLazIzVGxmK01aUDBIWHJsSnlXWGMv?= =?utf-8?B?a0NlZmZTMjJRZHZmN3c3U2tOSklIOUp4N2NIOGFVWmp0Q1JZd0tTaVRSOVZP?= =?utf-8?B?Y2lQeFU3RDZ6ZFVxQXh3dGNvSG1sS1dlUUxJelZ2U3NkczdtN2Fid0tyeFZB?= =?utf-8?B?VUlRYWJHSFMzUXBmSUxGNjNVZUZzOC9xdWw3Tk1jcytYYmRQYW5HU2YzZ2RW?= =?utf-8?B?cEo3TmQ0VU9KUlVObDJabmNGL0ROR3FvM3RLcHJLUk1YOXVNUUJZd2x1cXQ1?= =?utf-8?B?djcraURTTU90QjVrVkhVWkhHR01VclQrK3h2V3oxTHZyMCtGbmhEdkc2dU00?= =?utf-8?B?STI3L3ZLT1h6RGRNNzE2cFd3YzBaVmF1SzdxZjVCSkREVk1aQkFoY0RHMlNi?= =?utf-8?B?emQ1TjVSMng1VndGUVVETHhEaGloc1MyV2JNZWFiU0VsNnhUbUg5ZmdQWG1w?= =?utf-8?B?ektrY3V5TmgyaFhUNkFmM1Y5d2JGTUtjcUZsaHJycDJwTjJ6TmVYazZEazRu?= =?utf-8?B?dk05MjJSOERkTEdHREtram84S0ExTkVPanFkUVdEQWhvVGNWQldvbGFDWjln?= =?utf-8?B?Uk5RSU10UFB1d1U5SDZ1czFWZEQ0SWxmUW1TNHFNcnBFeXhYSnkvM2pPYzh1?= =?utf-8?B?U1FucElERHZtUEZmWmw3M3pQb0NVd2FxUGhwRnNhRHpWQVh1b3F2NXMvMzVS?= =?utf-8?B?SVhYRTBNcW1sam5tWmxKRGE2anBhNGdVdEwrdlhoZC9rSFdRUTdzQ3JlWjJs?= =?utf-8?B?cXZFR2RDZGZqanhiajRtVUJPaXpwMkh1b3EvUVhmR1Z6c05Cd3UxMy84YTdL?= =?utf-8?B?YTBrb3NyZ2dZZFhPUWdhNlI0R25jUFF1SmtCUHIvc1NjdlZLYmU3V2lCVENO?= =?utf-8?B?TkRRZytKUENaVVlsUkRQSEoyM2EyR3dhOUFZNjRSNjJ3dW1DRHh0cHpmb0VS?= =?utf-8?B?MmR5cnkrTGtxdnJod21adktmLzVuU1YzYkZSVWtRNDNnMzN1a0hQaERDejR2?= =?utf-8?B?cDNwbE5xNmZ1ZVF5MUxBQ2w4ejA5cnVycjhUak5Hcnl1Z2lsbmZDTG9IeDIw?= =?utf-8?B?V3dtVWxGN09mSVltc2h1Tk9sSWxuU3hhVDk1dWdQS2xNM3JjQzk4SjF3UDQy?= =?utf-8?B?V213Nlh1L0FtVDRxUGM5dXRwSFdNSHpvZWhZQThVRVZlWDJSYTBVWGVTSkJK?= =?utf-8?B?ZVBuTXpTSWdjdmFxMStybmpZaEFYOVRHMW53dGFoS215NDN0NzNWS1pJZ0VF?= =?utf-8?B?M2RoaTJoSEp1ZWNkUnV3MmJHYmo5SHptMDNaVkhOWk1kTVU3S1g0WUxsSU15?= =?utf-8?B?ak96TmlhUDVNWkJLeWQ2K1hqN3dzK2l6cVZCL0VlbWZUUnphQ3Bnek9qOXIz?= =?utf-8?B?RjlwSmEvQllTSElFZlJ1cmFwS1BJUXN1RElHcWZ3cUNqQzJMU1NNRnlzc08x?= =?utf-8?B?TWxPY1BvYlpQd0U0VkN0d0Q5QlBzZUF4Z29KdkJydlROR09vb2RQVkM4aXhI?= =?utf-8?B?TVpwYWg2ZG9RNFZ0RW8wUWVBMzZzZ2MwOXdLYXY5YWNmeXNCVFZlMG5VaGVG?= =?utf-8?B?ZEJ6M003WmtNQWdvVjRVc2RJY0U2bDBmQWRnWlllNFJWTnJrUndUbC9qWHZ5?= =?utf-8?B?R3ZSazFJeFhzazFUMi9aNldnOU5ueEZmTFlPenR2MlE5OHFsZUl3a3lVY3Rr?= =?utf-8?B?QVF4Z0NraldiOUNzd3lWZysrNWFpcHBBaFU3RHVlR1ZockxNemZPNmFJcmgy?= =?utf-8?Q?kE5yNomgsGOYN?= X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 16 May 2024 15:18:49.9338 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 09d92ccb-8514-48cb-d4de-08dc75bb7d33 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: DB1PEPF000509F4.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: GVXPR08MB11132 Precedence: Bulk List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Resent-Date: Thu, 16 May 2024 08:18:57 -0700 Resent-From: sami.mujawar@arm.com Reply-To: devel@edk2.groups.io,sami.mujawar@arm.com List-Unsubscribe-Post: List-Unsubscribe=One-Click List-Unsubscribe: X-Gm-Message-State: ZfyabnoFf3PKY52q5GLIId4Gx7686176AA= Content-Language: en-GB Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: quoted-printable X-GND-Status: LEGIT Authentication-Results: spool.mail.gandi.net; dkim=pass header.d=groups.io header.s=20240206 header.b=ZNbKh4Yp; dmarc=fail reason="SPF not aligned (relaxed), DKIM not aligned (relaxed)" header.from=arm.com (policy=none); spf=pass (spool.mail.gandi.net: domain of bounce@groups.io designates 45.79.224.7 as permitted sender) smtp.mailfrom=bounce@groups.io Hi Sahil, Thank you for this patch. Please find my response inline marked [SAMI]. With that fixed, Reviewed-by: Sami Mujawar Regards, Sami Mujawar On 23/04/2024 06:56 am, Sahil Kaushal wrote: > From: sahil > > This patch implements functions to interact with P30 NOR Flash. > The code is taken from Platform/ARM/Drivers/NorFlashDxe/NorFlash.c > file. > > Signed-off-by: sahil > --- > Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.inf | 3= 5 + > Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.h | 9= 8 ++ > Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.c | 94= 9 ++++++++++++++++++++ > 3 files changed, 1082 insertions(+) > > diff --git a/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceL= ib.inf b/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.inf > new file mode 100644 > index 000000000000..0707edb54442 > --- /dev/null > +++ b/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.inf > @@ -0,0 +1,35 @@ > +#/** @file > > +# > > +# Component description file for P30NorFlashDeviceLib library > > +# > > +# Copyright (c) 2011 - 2024, Arm Limited. All rights reserved.
> > +# Copyright (c) 2020, Linaro, Ltd. All rights reserved.
> > +# > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +#**/ > > + > > +[Defines] > > + INF_VERSION =3D 0x00010005 > > + BASE_NAME =3D P30NorFlashDeviceLib > > + FILE_GUID =3D ed172366-066b-4998-9b5e-ca7f385a1709 > > + MODULE_TYPE =3D DXE_DRIVER > > + VERSION_STRING =3D 1.0 > > + LIBRARY_CLASS =3D NorFlashDeviceLib > > + > > +[Sources.common] > > + P30NorFlashDeviceLib.c > > + P30NorFlashDeviceLib.h > > + > > +[Packages] > > + MdePkg/MdePkg.dec > > + Platform/ARM/ARM.dec > > + > > +[LibraryClasses] > > + BaseLib > > + BaseMemoryLib > > + DebugLib > > + IoLib > > + > > +[Pcd.common] > > + gPlatformArmTokenSpaceGuid.PcdNorFlashCheckBlockLocked > > diff --git a/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceL= ib.h b/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.h > new file mode 100644 > index 000000000000..c310b2310d62 > --- /dev/null > +++ b/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.h > @@ -0,0 +1,98 @@ > +/** @file P30NorFlashDeviceLib.h > > + > > + Copyright (c) 2011 - 2024, Arm Limited. All rights reserved.
> > + Copyright (c) 2020, Linaro, Ltd. All rights reserved.
> > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef P30_NOR_FLASH_DEVICE_LIB_H_ > > +#define P30_NOR_FLASH_DEVICE_LIB_H_ > > + > > +#define NOR_FLASH_ERASE_RETRY 10 > > + > > +// Device access macros > > +// These are necessary because we use 2 x 16bit parts to make up 32bit d= ata > > + > > +#define HIGH_16_BITS 0xFFFF0000 > > +#define LOW_16_BITS 0x0000FFFF > > +#define LOW_8_BITS 0x000000FF > > + > > +#define FOLD_32BIT_INTO_16BIT(value) ( ( value >> 16 ) | ( value & LOW_= 16_BITS ) ) > > + > > +#define GET_LOW_BYTE(value) ( value & LOW_8_BITS ) > > +#define GET_HIGH_BYTE(value) ( GET_LOW_BYTE( value >> 16 ) ) > > + > > +// Each command must be sent simultaneously to both chips, > > +// i.e. at the lower 16 bits AND at the higher 16 bits > > +#define CREATE_NOR_ADDRESS(BaseAddr, OffsetAddr) ((BaseAddr) + ((Offset= Addr) << 2)) > > +#define CREATE_DUAL_CMD(Cmd) ( ( Cmd << 16) | ( Cmd= & LOW_16_BITS) ) > > +#define SEND_NOR_COMMAND(BaseAddr, Offset, Cmd) MmioWrite32 (CREATE_NO= R_ADDRESS(BaseAddr,Offset), CREATE_DUAL_CMD(Cmd)) > > + > > +#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align= ) - 1)) =3D=3D 0) > > + > > +// Status Register Bits > > +#define P30_SR_BIT_WRITE (BIT7 << 16 | BIT7) > > +#define P30_SR_BIT_ERASE_SUSPEND (BIT6 << 16 | BIT6) > > +#define P30_SR_BIT_ERASE (BIT5 << 16 | BIT5) > > +#define P30_SR_BIT_PROGRAM (BIT4 << 16 | BIT4) > > +#define P30_SR_BIT_VPP (BIT3 << 16 | BIT3) > > +#define P30_SR_BIT_PROGRAM_SUSPEND (BIT2 << 16 | BIT2) > > +#define P30_SR_BIT_BLOCK_LOCKED (BIT1 << 16 | BIT1) > > +#define P30_SR_BIT_BEFP (BIT0 << 16 | BIT0) > > + > > +// Device Commands for Intel StrataFlash(R) Embedded Memory (P30) Family > > + > > +// On chip buffer size for buffered programming operations > > +// There are 2 chips, each chip can buffer up to 32 (16-bit)words, and e= ach word is 2 bytes. > > +// Therefore the total size of the buffer is 2 x 32 x 2 =3D 128 bytes > > +#define P30_MAX_BUFFER_SIZE_IN_BYTES ((UINTN)128) > > +#define P30_MAX_BUFFER_SIZE_IN_WORDS (P30_MAX_BUFFER_SIZE_IN_BYTES/((UI= NTN)4)) > > +#define MAX_BUFFERED_PROG_ITERATIONS 10000000 > > +#define BOUNDARY_OF_32_WORDS 0x7F > > + > > +// CFI Addresses > > +#define P30_CFI_ADDR_QUERY_UNIQUE_QRY 0x10 > > +#define P30_CFI_ADDR_VENDOR_ID 0x13 > > + > > +// CFI Data > > +#define CFI_QRY 0x00595251 > > + > > +// READ Commands > > +#define P30_CMD_READ_DEVICE_ID 0x0090 > > +#define P30_CMD_READ_STATUS_REGISTER 0x0070 > > +#define P30_CMD_CLEAR_STATUS_REGISTER 0x0050 > > +#define P30_CMD_READ_ARRAY 0x00FF > > +#define P30_CMD_READ_CFI_QUERY 0x0098 > > + > > +// WRITE Commands > > +#define P30_CMD_WORD_PROGRAM_SETUP 0x0040 > > +#define P30_CMD_ALTERNATE_WORD_PROGRAM_SETUP 0x0010 > > +#define P30_CMD_BUFFERED_PROGRAM_SETUP 0x00E8 > > +#define P30_CMD_BUFFERED_PROGRAM_CONFIRM 0x00D0 > > +#define P30_CMD_BEFP_SETUP 0x0080 > > +#define P30_CMD_BEFP_CONFIRM 0x00D0 > > + > > +// ERASE Commands > > +#define P30_CMD_BLOCK_ERASE_SETUP 0x0020 > > +#define P30_CMD_BLOCK_ERASE_CONFIRM 0x00D0 > > + > > +// SUSPEND Commands > > +#define P30_CMD_PROGRAM_OR_ERASE_SUSPEND 0x00B0 > > +#define P30_CMD_SUSPEND_RESUME 0x00D0 > > + > > +// BLOCK LOCKING / UNLOCKING Commands > > +#define P30_CMD_LOCK_BLOCK_SETUP 0x0060 > > +#define P30_CMD_LOCK_BLOCK 0x0001 > > +#define P30_CMD_UNLOCK_BLOCK 0x00D0 > > +#define P30_CMD_LOCK_DOWN_BLOCK 0x002F > > + > > +// PROTECTION Commands > > +#define P30_CMD_PROGRAM_PROTECTION_REGISTER_SETUP 0x00C0 > > + > > +// CONFIGURATION Commands > > +#define P30_CMD_READ_CONFIGURATION_REGISTER_SETUP 0x0060 > > +#define P30_CMD_READ_CONFIGURATION_REGISTER 0x0003 > > + > > +#endif /* P30_NOR_FLASH_DEVICE_LIB_H_ */ > > diff --git a/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceL= ib.c b/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.c > new file mode 100644 > index 000000000000..d68e237e2e26 > --- /dev/null > +++ b/Platform/ARM/Library/P30NorFlashDeviceLib/P30NorFlashDeviceLib.c > @@ -0,0 +1,949 @@ > +/** @file P30NorFlashDeviceLib.c > > + > > + Copyright (c) 2011 - 2024, Arm Limited. All rights reserved.
> > + Copyright (c) 2020, Linaro, Ltd. All rights reserved.
> > + > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "P30NorFlashDeviceLib.h" > > + > > +UINT32 > > +NorFlashReadStatusRegister ( [SAMI] I think this function can be made STATIC. > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN SR_Address > > + ) > > +{ > > + // Prepare to read the status register > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_= REGISTER); > > + return MmioRead32 (Instance->DeviceBaseAddress); > > +} > > + > > +STATIC > > +BOOLEAN > > +NorFlashBlockIsLocked ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + UINT32 LockStatus; > > + > > + // Send command for reading device id > > + SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID); > > + > > + // Read block lock status > > + LockStatus =3D MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2)); > > + > > + // Decode block lock status > > + LockStatus =3D FOLD_32BIT_INTO_16BIT (LockStatus); > > + > > + if ((LockStatus & 0x2) !=3D 0) { > > + DEBUG ((DEBUG_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED D= OWN\n")); > > + } > > + > > + return ((LockStatus & 0x1) !=3D 0); > > +} > > + > > +/** > > + * This function unlock and erase an entire NOR Flash block. > > + **/ > > +EFI_STATUS > > +NorFlashUnlockAndEraseSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN Index; > > + EFI_TPL OriginalTPL; > > + > > + NorFlashLock (&OriginalTPL); > > + > > + Index =3D 0; > > + // The block erase might fail a first time (SW bug ?). Retry it ... > > + do { > > + // Unlock the block if we have to > > + Status =3D NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddr= ess); > > + if (EFI_ERROR (Status)) { > > + break; > > + } > > + > > + Status =3D NorFlashEraseSingleBlock (Instance, BlockAddress); > > + Index++; > > + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status =3D=3D EFI_WRITE_P= ROTECTED)); > > + > > + if (Index =3D=3D NOR_FLASH_ERASE_RETRY) { > > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=3D0x%08x: Block = Locked Error (try to erase %d times)\n", BlockAddress, Index)); > > + } > > + > > + NorFlashUnlock (OriginalTPL); > > + > > + return Status; > > +} > > + > > +EFI_STATUS > > +NorFlashWriteFullBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINT32 *DataBuffer, > > + IN UINT32 BlockSizeInWords > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN WordAddress; > > + UINT32 WordIndex; > > + UINTN BufferIndex; > > + UINTN BlockAddress; > > + UINTN BuffersInBlock; > > + UINTN RemainingWords; > > + EFI_TPL OriginalTPL; > > + UINTN Cnt; > > + > > + Status =3D EFI_SUCCESS; > > + > > + // Get the physical address of the block > > + BlockAddress =3D GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, L= ba, BlockSizeInWords * 4); > > + > > + // Start writing from the first address at the start of the block > > + WordAddress =3D BlockAddress; > > + > > + NorFlashLock (&OriginalTPL); > > + > > + Status =3D NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and= Erase the single block at 0x%X\n", BlockAddress)); > > + goto EXIT; > > + } > > + > > + // To speed up the programming operation, NOR Flash is programmed usin= g the Buffered Programming method. > > + > > + // Check that the address starts at a 32-word boundary, i.e. last 7 bi= ts must be zero > > + if ((WordAddress & BOUNDARY_OF_32_WORDS) =3D=3D 0x00) { > > + // First, break the entire block into buffer-sized chunks. > > + BuffersInBlock =3D (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SI= ZE_IN_BYTES; > > + > > + // Then feed each buffer chunk to the NOR Flash > > + // If a buffer does not contain any data, don't write it. > > + for (BufferIndex =3D 0; > > + BufferIndex < BuffersInBlock; > > + BufferIndex++, WordAddress +=3D P30_MAX_BUFFER_SIZE_IN_BYTES, D= ataBuffer +=3D P30_MAX_BUFFER_SIZE_IN_WORDS > > + ) > > + { > > + // Check the buffer to see if it contains any data (not set all 1s= ). > > + for (Cnt =3D 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) { > > + if (~DataBuffer[Cnt] !=3D 0 ) { > > + // Some data found, write the buffer. > > + Status =3D NorFlashWriteBuffer ( > > + Instance, > > + WordAddress, > > + P30_MAX_BUFFER_SIZE_IN_BYTES, > > + DataBuffer > > + ); > > + if (EFI_ERROR (Status)) { > > + goto EXIT; > > + } > > + > > + break; > > + } > > + } > > + } > > + > > + // Finally, finish off any remaining words that are less than the ma= ximum size of the buffer > > + RemainingWords =3D BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS; > > + > > + if (RemainingWords !=3D 0) { > > + Status =3D NorFlashWriteBuffer (Instance, WordAddress, (RemainingW= ords * 4), DataBuffer); > > + if (EFI_ERROR (Status)) { > > + goto EXIT; > > + } > > + } > > + } else { > > + // For now, use the single word programming algorithm > > + // It is unlikely that the NOR Flash will exist in an address which = falls within a 32 word boundary range, > > + // i.e. which ends in the range 0x......01 - 0x......7F. > > + for (WordIndex =3D 0; WordIndex < BlockSizeInWords; WordIndex++, Dat= aBuffer++, WordAddress =3D WordAddress + 4) { > > + Status =3D NorFlashWriteSingleWord (Instance, WordAddress, *DataBu= ffer); > > + if (EFI_ERROR (Status)) { > > + goto EXIT; > > + } > > + } > > + } > > + > > +EXIT: > > + NorFlashUnlock (OriginalTPL); > > + > > + if (EFI_ERROR (Status)) { > > + DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] faile= d at address 0x%08x. Exit Status =3D \"%r\".\n", WordAddress, Status)); > > + } > > + > > + return Status; > > +} > > + > > +STATIC > > +EFI_STATUS > > +NorFlashUnlockSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + UINT32 LockStatus; > > + > > + // Raise the Task Priority Level to TPL_NOTIFY to serialise all its op= erations > > + // and to protect shared data structures. > > + > > + if (FeaturePcdGet (PcdNorFlashCheckBlockLocked) =3D=3D TRUE) { > > + do { > > + // Request a lock setup > > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP); > > + > > + // Request an unlock > > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK); > > + > > + // Send command for reading device id > > + SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID); > > + > > + // Read block lock status > > + LockStatus =3D MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2)); > > + > > + // Decode block lock status > > + LockStatus =3D FOLD_32BIT_INTO_16BIT (LockStatus); > > + } while ((LockStatus & 0x1) =3D=3D 1); > > + } else { > > + // Request a lock setup > > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP); > > + > > + // Request an unlock > > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK); > > + > > + // Wait until the status register gives us the all clear > > + do { > > + LockStatus =3D NorFlashReadStatusRegister (Instance, BlockAddress)= ; > > + } while ((LockStatus & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE); > > + } > > + > > + // Put device back into Read Array mode > > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY); > > + > > + DEBUG ((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=3D0x%08x\n", Blo= ckAddress)); > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +NorFlashUnlockSingleBlockIfNecessary ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + EFI_STATUS Status; > > + > > + Status =3D EFI_SUCCESS; > > + > > + if (NorFlashBlockIsLocked (Instance, BlockAddress)) { > > + Status =3D NorFlashUnlockSingleBlock (Instance, BlockAddress); > > + } > > + > > + return Status; > > +} > > + > > +/** > > + * The following function presumes that the block has already been unloc= ked. > > + **/ > > +EFI_STATUS > > +NorFlashEraseSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN BlockAddress > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 StatusRegister; > > + > > + Status =3D EFI_SUCCESS; > > + > > + // Request a block erase and then confirm it > > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP); > > + SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM); > > + > > + // Wait until the status register gives us the all clear > > + do { > > + StatusRegister =3D NorFlashReadStatusRegister (Instance, BlockAddres= s); > > + } while ((StatusRegister & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE); > > + > > + if (StatusRegister & P30_SR_BIT_VPP) { > > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=3D0x%08x: VPP Ra= nge Error\n", BlockAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) =3D=3D = (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) { > > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=3D0x%08x: Comman= d Sequence Error\n", BlockAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (StatusRegister & P30_SR_BIT_ERASE) { > > + DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=3D0x%08x: Block = Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { > > + // The debug level message has been reduced because a device lock mi= ght happen. In this case we just retry it ... > > + DEBUG ((DEBUG_INFO, "EraseSingleBlock(BlockAddress=3D0x%08x: Block L= ocked Error\n", BlockAddress)); > > + Status =3D EFI_WRITE_PROTECTED; > > + } > > + > > + if (EFI_ERROR (Status)) { > > + // Clear the Status Register > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STAT= US_REGISTER); > > + } > > + > > + // Put device back into Read Array mode > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); > > + > > + return Status; > > +} > > + > > +EFI_STATUS > > +NorFlashWriteSingleWord ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN WordAddress, > > + IN UINT32 WriteData > > + ) > > +{ > > + EFI_STATUS Status; > > + UINT32 StatusRegister; > > + > > + Status =3D EFI_SUCCESS; > > + > > + // Request a write single word command > > + SEND_NOR_COMMAND (WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP); > > + > > + // Store the word into NOR Flash; > > + MmioWrite32 (WordAddress, WriteData); > > + > > + // Wait for the write to complete and then check for any errors; i.e. = check the Status Register > > + do { > > + // Prepare to read the status register > > + StatusRegister =3D NorFlashReadStatusRegister (Instance, WordAddress= ); > > + // The chip is busy while the WRITE bit is not asserted > > + } while ((StatusRegister & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE); > > + > > + // Perform a full status check: > > + // Mask the relevant bits of Status Register. > > + // Everything should be zero, if not, we have a problem > > + > > + if (StatusRegister & P30_SR_BIT_VPP) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): VPP= Range Error\n", WordAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (StatusRegister & P30_SR_BIT_PROGRAM) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Pro= gram Error\n", WordAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleWord(WordAddress:0x%X): Dev= ice Protect Error\n", WordAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (!EFI_ERROR (Status)) { > > + // Clear the Status Register > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STAT= US_REGISTER); > > + } > > + > > + // Put device back into Read Array mode > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); > > + > > + return Status; > > +} > > + > > +/* > > + * Writes data to the NOR Flash using the Buffered Programming method. > > + * > > + * The maximum size of the on-chip buffer is 32-words, because of hardwa= re restrictions. > > + * Therefore this function will only handle buffers up to 32 words or 12= 8 bytes. > > + * To deal with larger buffers, call this function again. > > + * > > + * This function presumes that both the TargetAddress and the TargetAddr= ess+BufferSize > > + * exist entirely within the NOR Flash. Therefore these conditions will = not be checked here. > > + * > > + * In buffered programming, if the target address not at the beginning o= f a 32-bit word boundary, > > + * then programming time is doubled and power consumption is increased. > > + * Therefore, it is a requirement to align buffer writes to 32-bit word = boundaries. > > + * i.e. the last 4 bits of the target start address must be zero: 0x....= ..00 > > + */ > > +EFI_STATUS > > +NorFlashWriteBuffer ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN UINTN TargetAddress, > > + IN UINTN BufferSizeInBytes, > > + IN UINT32 *Buffer > > + ) [SAMI] This function can be made STATIC. > > +{ > > + EFI_STATUS Status; > > + UINTN BufferSizeInWords; > > + UINTN Count; > > + volatile UINT32 *Data; > > + UINTN WaitForBuffer; > > + BOOLEAN BufferAvailable; > > + UINT32 StatusRegister; > > + > > + WaitForBuffer =3D MAX_BUFFERED_PROG_ITERATIONS; > > + BufferAvailable =3D FALSE; > > + > > + // Check that the target address does not cross a 32-word boundary. > > + if ((TargetAddress & BOUNDARY_OF_32_WORDS) !=3D 0) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Check there are some data to program > > + if (BufferSizeInBytes =3D=3D 0) { > > + return EFI_BUFFER_TOO_SMALL; > > + } > > + > > + // Check that the buffer size does not exceed the maximum hardware buf= fer size on chip. > > + if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // Check that the buffer size is a multiple of 32-bit words > > + if ((BufferSizeInBytes % 4) !=3D 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // Pre-programming conditions checked, now start the algorithm. > > + > > + // Prepare the data destination address > > + Data =3D (UINT32 *)TargetAddress; > > + > > + // Check the availability of the buffer > > + do { > > + // Issue the Buffered Program Setup command > > + SEND_NOR_COMMAND (TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP); > > + > > + // Read back the status register bit#7 from the same address > > + if (((*Data) & P30_SR_BIT_WRITE) =3D=3D P30_SR_BIT_WRITE) { > > + BufferAvailable =3D TRUE; > > + } > > + > > + // Update the loop counter > > + WaitForBuffer--; > > + } while ((WaitForBuffer > 0) && (BufferAvailable =3D=3D FALSE)); > > + > > + // The buffer was not available for writing > > + if (WaitForBuffer =3D=3D 0) { > > + Status =3D EFI_DEVICE_ERROR; > > + goto EXIT; > > + } > > + > > + // From now on we work in 32-bit words > > + BufferSizeInWords =3D BufferSizeInBytes / (UINTN)4; > > + > > + // Write the word count, which is (buffer_size_in_words - 1), > > + // because word count 0 means one word. > > + SEND_NOR_COMMAND (TargetAddress, 0, (BufferSizeInWords - 1)); > > + > > + // Write the data to the NOR Flash, advancing each address by 4 bytes > > + for (Count =3D 0; Count < BufferSizeInWords; Count++, Data++, Buffer++= ) { > > + MmioWrite32 ((UINTN)Data, *Buffer); > > + } > > + > > + // Issue the Buffered Program Confirm command, to start the programmin= g operation > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PRO= GRAM_CONFIRM); > > + > > + // Wait for the write to complete and then check for any errors; i.e. = check the Status Register > > + do { > > + StatusRegister =3D NorFlashReadStatusRegister (Instance, TargetAddre= ss); > > + // The chip is busy while the WRITE bit is not asserted > > + } while ((StatusRegister & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE); > > + > > + // Perform a full status check: > > + // Mask the relevant bits of Status Register. > > + // Everything should be zero, if not, we have a problem > > + > > + Status =3D EFI_SUCCESS; > > + > > + if (StatusRegister & P30_SR_BIT_VPP) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): VPP R= ange Error\n", TargetAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (StatusRegister & P30_SR_BIT_PROGRAM) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Progr= am Error\n", TargetAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBuffer(TargetAddress:0x%X): Devic= e Protect Error\n", TargetAddress)); > > + Status =3D EFI_DEVICE_ERROR; > > + } > > + > > + if (!EFI_ERROR (Status)) { > > + // Clear the Status Register > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STAT= US_REGISTER); > > + } > > + > > +EXIT: > > + // Put device back into Read Array mode > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); > > + > > + return Status; > > +} > > + > > +EFI_STATUS > > +NorFlashWriteBlocks ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN BufferSizeInBytes, > > + IN VOID *Buffer > > + ) > > +{ > > + UINT32 *pWriteBuffer; > > + EFI_STATUS Status; > > + EFI_LBA CurrentBlock; > > + UINT32 BlockSizeInWords; > > + UINT32 NumBlocks; > > + UINT32 BlockCount; > > + > > + Status =3D EFI_SUCCESS; > > + > > + // The buffer must be valid > > + if (Buffer =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + if (Instance->Media.ReadOnly =3D=3D TRUE) { > > + return EFI_WRITE_PROTECTED; > > + } > > + > > + // We must have some bytes to read > > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BufferSizeInBytes=3D0x%x\n"= , BufferSizeInBytes)); > > + if (BufferSizeInBytes =3D=3D 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // The size of the buffer must be a multiple of the block size > > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: BlockSize in bytes =3D0x%x\= n", Instance->Media.BlockSize)); > > + if ((BufferSizeInBytes % Instance->Media.BlockSize) !=3D 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // All blocks must be within the device > > + NumBlocks =3D ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize; > > + > > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: NumBlocks=3D%d, LastBlock= =3D%ld, Lba=3D%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba)); > > + > > + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed= last block.\n")); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + BlockSizeInWords =3D Instance->Media.BlockSize / 4; > > + > > + // Because the target *Buffer is a pointer to VOID, we must put all th= e data into a pointer > > + // to a proper data type, so use *ReadBuffer > > + pWriteBuffer =3D (UINT32 *)Buffer; > > + > > + CurrentBlock =3D Lba; > > + for (BlockCount =3D 0; BlockCount < NumBlocks; BlockCount++, CurrentBl= ock++, pWriteBuffer =3D pWriteBuffer + BlockSizeInWords) { > > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UI= NTN)CurrentBlock)); > > + > > + Status =3D NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuf= fer, BlockSizeInWords); > > + > > + if (EFI_ERROR (Status)) { > > + break; > > + } > > + } > > + > > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status =3D \"%r\".\n",= Status)); > > + return Status; > > +} > > + > > +/** > > + Copy Length bytes from Source to Destination, using aligned accesses o= nly. > > + Note that this implementation uses memcpy() semantics rather then memm= ove() > > + semantics, i.e., SourceBuffer and DestinationBuffer should not overlap= . > > + > > + @param DestinationBuffer The target of the copy request. > > + @param SourceBuffer The place to copy from. > > + @param Length The number of bytes to copy. > > + > > + @return Destination > > + > > +**/ > > +STATIC > > +VOID * > > +AlignedCopyMem ( > > + OUT VOID *DestinationBuffer, > > + IN CONST VOID *SourceBuffer, > > + IN UINTN Length > > + ) > > +{ > > + UINT8 *Destination8; > > + CONST UINT8 *Source8; > > + UINT32 *Destination32; > > + CONST UINT32 *Source32; > > + UINT64 *Destination64; > > + CONST UINT64 *Source64; > > + > > + if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 8) && (Length >=3D = 8)) { > > + Destination64 =3D DestinationBuffer; > > + Source64 =3D SourceBuffer; > > + while (Length >=3D 8) { > > + *Destination64++ =3D *Source64++; > > + Length -=3D 8; > > + } > > + > > + Destination8 =3D (UINT8 *)Destination64; > > + Source8 =3D (CONST UINT8 *)Source64; > > + } else if (BOTH_ALIGNED (DestinationBuffer, SourceBuffer, 4) && (Lengt= h >=3D 4)) { > > + Destination32 =3D DestinationBuffer; > > + Source32 =3D SourceBuffer; > > + while (Length >=3D 4) { > > + *Destination32++ =3D *Source32++; > > + Length -=3D 4; > > + } > > + > > + Destination8 =3D (UINT8 *)Destination32; > > + Source8 =3D (CONST UINT8 *)Source32; > > + } else { > > + Destination8 =3D DestinationBuffer; > > + Source8 =3D SourceBuffer; > > + } > > + > > + while (Length-- !=3D 0) { > > + *Destination8++ =3D *Source8++; > > + } > > + > > + return DestinationBuffer; > > +} > > + > > +EFI_STATUS > > +NorFlashReadBlocks ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN BufferSizeInBytes, > > + OUT VOID *Buffer > > + ) > > +{ > > + UINT32 NumBlocks; > > + UINTN StartAddress; > > + > > + DEBUG (( > > + DEBUG_BLKIO, > > + "NorFlashReadBlocks: BufferSize=3D0x%xB BlockSize=3D0x%xB LastBlock= =3D%ld, Lba=3D%ld.\n", > > + BufferSizeInBytes, > > + Instance->Media.BlockSize, > > + Instance->Media.LastBlock, > > + Lba > > + )); > > + > > + // The buffer must be valid > > + if (Buffer =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Return if we have not any byte to read > > + if (BufferSizeInBytes =3D=3D 0) { > > + return EFI_SUCCESS; > > + } > > + > > + // The size of the buffer must be a multiple of the block size > > + if ((BufferSizeInBytes % Instance->Media.BlockSize) !=3D 0) { > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // All blocks must be within the device > > + NumBlocks =3D ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize; > > + > > + if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) { > > + DEBUG ((DEBUG_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed l= ast block\n")); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Get the address to start reading from > > + StartAddress =3D GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + Instance->Media.BlockSize > > + ); > > + > > + // Put the device into Read Array mode > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); > > + > > + // Readout the data > > + AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes); > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +NorFlashRead ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN Offset, > > + IN UINTN BufferSizeInBytes, > > + OUT VOID *Buffer > > + ) > > +{ > > + UINTN StartAddress; > > + > > + // The buffer must be valid > > + if (Buffer =3D=3D NULL) { > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Return if we have not any byte to read > > + if (BufferSizeInBytes =3D=3D 0) { > > + return EFI_SUCCESS; > > + } > > + > > + if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) >= Instance->Size) { > > + DEBUG ((DEBUG_ERROR, "NorFlashRead: ERROR - Read will exceed device = size.\n")); > > + return EFI_INVALID_PARAMETER; > > + } > > + > > + // Get the address to start reading from > > + StartAddress =3D GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + Instance->Media.BlockSize > > + ); > > + > > + // Put the device into Read Array mode > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); > > + > > + // Readout the data > > + AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInB= ytes); > > + > > + return EFI_SUCCESS; > > +} > > + > > +/* > > + Write a full or portion of a block. It must not span block boundaries;= that is, > > + Offset + *NumBytes <=3D Instance->Media.BlockSize. > > +*/ > > +EFI_STATUS > > +NorFlashWriteSingleBlock ( > > + IN NOR_FLASH_INSTANCE *Instance, > > + IN EFI_LBA Lba, > > + IN UINTN Offset, > > + IN OUT UINTN *NumBytes, > > + IN UINT8 *Buffer > > + ) > > +{ > > + EFI_STATUS TempStatus; > > + UINT32 Tmp; > > + UINT32 TmpBuf; > > + UINT32 WordToWrite; > > + UINT32 Mask; > > + BOOLEAN DoErase; > > + UINTN BytesToWrite; > > + UINTN CurOffset; > > + UINTN WordAddr; > > + UINTN BlockSize; > > + UINTN BlockAddress; > > + UINTN PrevBlockAddress; > > + > > + PrevBlockAddress =3D 0; > > + > > + DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=3D%ld, = Offset=3D0x%x, *NumBytes=3D0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumByte= s, Buffer)); > > + > > + // Detect WriteDisabled state > > + if (Instance->Media.ReadOnly =3D=3D TRUE) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - Can not writ= e: 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; > > + > > + // The write must not span block boundaries. > > + // We need to check each variable individually because adding two larg= e values together overflows. > > + if ((Offset >=3D BlockSize) || > > + (*NumBytes > BlockSize) || > > + ((Offset + *NumBytes) > BlockSize)) > > + { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFF= ER_SIZE: (Offset=3D0x%x + NumBytes=3D0x%x) > BlockSize=3D0x%x\n", Offset, *= NumBytes, BlockSize)); > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // We must have some bytes to write > > + if (*NumBytes =3D=3D 0) { > > + DEBUG ((DEBUG_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFF= ER_SIZE: (Offset=3D0x%x + NumBytes=3D0x%x) > BlockSize=3D0x%x\n", Offset, *= NumBytes, BlockSize)); > > + return EFI_BAD_BUFFER_SIZE; > > + } > > + > > + // Pick 128bytes as a good start for word operations as opposed to era= sing the > > + // block and writing the data regardless if an erase is really needed. > > + // It looks like most individual NV variable writes are smaller than 1= 28bytes. > > + if (*NumBytes <=3D 128) { > > + // Check to see if we need to erase before programming the data into= NOR. > > + // If the destination bits are only changing from 1s to 0s we can ju= st 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 FALSE; > > + BytesToWrite =3D *NumBytes; > > + CurOffset =3D Offset; > > + > > + while (BytesToWrite > 0) { > > + // Read full word from NOR, splice as required. A word is the smal= lest > > + // unit we can write. > > + TempStatus =3D NorFlashRead (Instance, Lba, CurOffset & ~(0x3), si= zeof (Tmp), &Tmp); > > + if (EFI_ERROR (TempStatus)) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + // Physical address of word in NOR to write. > > + WordAddr =3D (CurOffset & ~(0x3)) + GET_NOR_BLOCK_ADDRESS ( > > + Instance->RegionBaseAddress, > > + Lba, > > + BlockSize > > + ); > > + // The word of data that is to be written. > > + TmpBuf =3D *((UINT32 *)(Buffer + (*NumBytes - BytesToWrite))); > > + > > + // First do word aligned chunks. > > + if ((CurOffset & 0x3) =3D=3D 0) { > > + if (BytesToWrite >=3D 4) { > > + // Is the destination still in 'erased' state? > > + if (~Tmp !=3D 0) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase =3D TRUE; > > + break; > > + } > > + } > > + > > + // Write this word to NOR > > + WordToWrite =3D TmpBuf; > > + CurOffset +=3D sizeof (TmpBuf); > > + BytesToWrite -=3D sizeof (TmpBuf); > > + } else { > > + // BytesToWrite < 4. Do small writes and left-overs > > + Mask =3D ~((~0) << (BytesToWrite * 8)); > > + // Mask out the bytes we want. > > + TmpBuf &=3D Mask; > > + // Is the destination still in 'erased' state? > > + if ((Tmp & Mask) !=3D Mask) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase =3D TRUE; > > + break; > > + } > > + } > > + > > + // Merge old and new data. Write merged word to NOR > > + WordToWrite =3D (Tmp & ~Mask) | TmpBuf; > > + CurOffset +=3D BytesToWrite; > > + BytesToWrite =3D 0; > > + } > > + } else { > > + // Do multiple words, but starting unaligned. > > + if (BytesToWrite > (4 - (CurOffset & 0x3))) { > > + Mask =3D ((~0) << ((CurOffset & 0x3) * 8)); > > + // Mask out the bytes we want. > > + TmpBuf &=3D Mask; > > + // Is the destination still in 'erased' state? > > + if ((Tmp & Mask) !=3D Mask) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase =3D TRUE; > > + break; > > + } > > + } > > + > > + // Merge old and new data. Write merged word to NOR > > + WordToWrite =3D (Tmp & ~Mask) | TmpBuf; > > + BytesToWrite -=3D (4 - (CurOffset & 0x3)); > > + CurOffset +=3D (4 - (CurOffset & 0x3)); > > + } else { > > + // Unaligned and fits in one word. > > + Mask =3D (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3)= * 8); > > + // Mask out the bytes we want. > > + TmpBuf =3D (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask; > > + // Is the destination still in 'erased' state? > > + if ((Tmp & Mask) !=3D Mask) { > > + // Check to see if we are only changing bits to zero. > > + if ((Tmp ^ TmpBuf) & TmpBuf) { > > + DoErase =3D TRUE; > > + break; > > + } > > + } > > + > > + // Merge old and new data. Write merged word to NOR > > + WordToWrite =3D (Tmp & ~Mask) | TmpBuf; > > + CurOffset +=3D BytesToWrite; > > + BytesToWrite =3D 0; > > + } > > + } > > + > > + // > > + // Write the word to NOR. > > + // > > + > > + BlockAddress =3D GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddres= s, Lba, BlockSize); > > + if (BlockAddress !=3D PrevBlockAddress) { > > + TempStatus =3D NorFlashUnlockSingleBlockIfNecessary (Instance, B= lockAddress); > > + if (EFI_ERROR (TempStatus)) { > > + return EFI_DEVICE_ERROR; > > + } > > + > > + PrevBlockAddress =3D BlockAddress; > > + } > > + > > + TempStatus =3D NorFlashWriteSingleWord (Instance, WordAddr, WordTo= Write); > > + if (EFI_ERROR (TempStatus)) { > > + return EFI_DEVICE_ERROR; > > + } > > + } > > + > > + // Exit if we got here and could write all the data. Otherwise do th= e > > + // Erase-Write cycle. > > + if (!DoErase) { > > + return EFI_SUCCESS; > > + } > > + } > > + > > + // 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; > > + } > > + > > + // Read NOR Flash data into shadow buffer > > + TempStatus =3D NorFlashReadBlocks (Instance, Lba, BlockSize, Instance-= >ShadowBuffer); > > + if (EFI_ERROR (TempStatus)) { > > + // 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); > > + > > + // Write the modified buffer back to the NorFlash > > + TempStatus =3D NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance= ->ShadowBuffer); > > + if (EFI_ERROR (TempStatus)) { > > + // Return one of the pre-approved error statuses > > + return EFI_DEVICE_ERROR; > > + } > > + > > + return EFI_SUCCESS; > > +} > > + > > +EFI_STATUS > > +NorFlashReset ( > > + IN NOR_FLASH_INSTANCE *Instance > > + ) > > +{ > > + // As there is no specific RESET to perform, ensure that the devices i= s in the default Read Array mode > > + SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); > > + return EFI_SUCCESS; > > +} > -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#118962): https://edk2.groups.io/g/devel/message/118962 Mute This Topic: https://groups.io/mt/105690941/7686176 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-