From nobody Sun Apr 28 20:02:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+69178+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+69178+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1608285864; cv=none; d=zohomail.com; s=zohoarc; b=LU8oh3nAQO3xtot+esg+oc3jWEM0lxnO6auwYf0X8cvBnh5MaNxIsgOl8h+RE7h+b1AOx00UNF4sFldrSniqzpA0fcK2DDBN2tKreBLmtQh4UVzLHbkbYMXPnWBd0v3mGKNKOOUOtRoruL/ppcU2/szbto9NcLXNOEwt80Kcki4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1608285864; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=ceMs4N+11kEHPDMNFm/RKg3mDQ9hD8thdhcRtCqxDks=; b=L0XETvTACpIqcQE4dNyM/BzKAN9NcPzWBjImocZc2xZR3sudO6CTDQv2V4qKRn4R2ZvvtOUwCilxlCA6z1BiwnVU+EZ5u5mOX7H9cZ1fuhp5OAw1xt1pYvgEVergu5x7vLv2OHcFlQJPh6cmg6MLWUEhX4z4qtOUhKqJsp/Wf1o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+69178+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1608285864061822.209947504701; Fri, 18 Dec 2020 02:04:24 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 70XJYY1788612xZDtrrTq7zS; Fri, 18 Dec 2020 02:04:23 -0800 X-Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) by mx.groups.io with SMTP id smtpd.web08.7840.1608285858195215755 for ; Fri, 18 Dec 2020 02:04:18 -0800 X-Received: by mail-pf1-f177.google.com with SMTP id c79so1263813pfc.2 for ; Fri, 18 Dec 2020 02:04:18 -0800 (PST) X-Gm-Message-State: BDttJ3RV0GDxyzAqtfGiuABFx1787277AA= X-Google-Smtp-Source: ABdhPJwdSAOYfccdSxai1uTn1cC273m1LNFgo4UW0sFpx10ZhEruDK33GXNa3CQzE6iUwcbpW5YYYw== X-Received: by 2002:a63:db57:: with SMTP id x23mr3384950pgi.131.1608285856922; Fri, 18 Dec 2020 02:04:16 -0800 (PST) X-Received: from localhost ([121.95.100.191]) by smtp.gmail.com with ESMTPSA id s29sm8922583pgn.65.2020.12.18.02.04.14 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Fri, 18 Dec 2020 02:04:15 -0800 (PST) From: "Masahisa Kojima" To: devel@edk2.groups.io Cc: Masahisa Kojima , Leif Lindholm , Ard Biesheuvel , Sami Mujawar , Jiewen Yao , Supreeth Venkatesh Subject: [edk2-devel] [PATCH 1/2] ArmPlatformPkg/NorFlashDxe: factor out DXE specific pieces Date: Fri, 18 Dec 2020 19:05:15 +0900 Message-Id: <20201218100516.14149-2-masahisa.kojima@linaro.org> In-Reply-To: <20201218100516.14149-1-masahisa.kojima@linaro.org> References: <20201218100516.14149-1-masahisa.kojima@linaro.org> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,masahisa.kojima@linaro.org Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1608285863; bh=BjI72LNdZZCYEcJV9QSzSIdHrQ/hUNg2Fi2Xnh7KG0c=; h=Cc:Date:From:Reply-To:Subject:To; b=OvKdShxixnJrLaICokyJq5NKSUvEFV5UVIQ5FrskVJ3jKLrFQsykfkrQLghpqCEyULz 2bHs+a9/ONYBbjdKA9WCwyvuF1HSPcr8Ern1iZd16MJoFJT6DQRlh8thBtwpSvaLIBGIq YpgmSa2LwPFpHS+M1HUywy4JUX9BXSgjCrs= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" In preparation of creating a standalone MM version of the NOR Flash driver, refactor the existing pieces into a core driver. NorFlashDxe.c has the DXE instantiation code, FVB initialization code and some common functions. Signed-off-by: Masahisa Kojima Cc: Leif Lindholm Cc: Ard Biesheuvel Cc: Sami Mujawar Cc: Jiewen Yao Cc: Supreeth Venkatesh Reviewed-by: Ard Biesheuvel --- ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf | = 5 +- ArmPlatformPkg/Drivers/NorFlashDxe/{NorFlashDxe.h =3D> NorFlash.h} |= 86 +- ArmPlatformPkg/Drivers/NorFlashDxe/{NorFlashDxe.c =3D> NorFlash.c} |= 372 +------ ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c | = 2 +- ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c | 1= 066 ++------------------ ArmPlatformPkg/Drivers/NorFlashDxe/{NorFlashFvbDxe.c =3D> NorFlashFvb.c} |= 107 +- 6 files changed, 191 insertions(+), 1447 deletions(-) diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf b/ArmPlatfo= rmPkg/Drivers/NorFlashDxe/NorFlashDxe.inf index a647c016878d..8b5078497fff 100644 --- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.inf @@ -17,9 +17,10 @@ [Defines] ENTRY_POINT =3D NorFlashInitialise =20 [Sources.common] - NorFlashDxe.h + NorFlash.c + NorFlash.h NorFlashDxe.c - NorFlashFvbDxe.c + NorFlashFvb.c NorFlashBlockIoDxe.c =20 [Packages] diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h b/ArmPlatform= Pkg/Drivers/NorFlashDxe/NorFlash.h similarity index 85% rename from ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h rename to ArmPlatformPkg/Drivers/NorFlashDxe/NorFlash.h index a583e36c7988..f24dd936f8c3 100644 --- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.h +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlash.h @@ -1,4 +1,4 @@ -/** @file NorFlashDxe.h +/** @file NorFlash.h =20 Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.
=20 @@ -6,8 +6,8 @@ =20 **/ =20 -#ifndef __NOR_FLASH_DXE_H__ -#define __NOR_FLASH_DXE_H__ +#ifndef __NOR_FLASH_H__ +#define __NOR_FLASH_H__ =20 =20 #include @@ -234,12 +234,6 @@ NorFlashDiskIoWriteDisk ( // NorFlashFvbDxe.c // =20 -EFI_STATUS -EFIAPI -NorFlashFvbInitialize ( - IN NOR_FLASH_INSTANCE* Instance - ); - EFI_STATUS EFIAPI FvbGetAttributes( @@ -297,16 +291,62 @@ FvbEraseBlocks( ... ); =20 +EFI_STATUS +ValidateFvHeader ( + IN NOR_FLASH_INSTANCE *Instance + ); + +EFI_STATUS +InitializeFvAndVariableStoreHeaders ( + IN NOR_FLASH_INSTANCE *Instance + ); + +VOID +EFIAPI +FvbVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + // // NorFlashDxe.c // =20 +EFI_STATUS +NorFlashWriteFullBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN EFI_LBA Lba, + IN UINT32 *DataBuffer, + IN UINT32 BlockSizeInWords + ); + EFI_STATUS NorFlashUnlockAndEraseSingleBlock ( IN NOR_FLASH_INSTANCE *Instance, IN UINTN BlockAddress ); =20 +EFI_STATUS +NorFlashCreateInstance ( + IN UINTN NorFlashDeviceBase, + IN UINTN NorFlashRegionBase, + IN UINTN NorFlashSize, + IN UINT32 Index, + IN UINT32 BlockSize, + IN BOOLEAN SupportFvb, + OUT NOR_FLASH_INSTANCE** NorFlashInstance + ); + +EFI_STATUS +EFIAPI +NorFlashFvbInitialize ( + IN NOR_FLASH_INSTANCE* Instance + ); + + +// +// NorFlash.c +// EFI_STATUS NorFlashWriteSingleBlock ( IN NOR_FLASH_INSTANCE *Instance, @@ -355,4 +395,30 @@ NorFlashReset ( IN NOR_FLASH_INSTANCE *Instance ); =20 -#endif /* __NOR_FLASH_DXE_H__ */ +EFI_STATUS +NorFlashEraseSingleBlock ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ); + +EFI_STATUS +NorFlashUnlockSingleBlockIfNecessary ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN BlockAddress + ); + +EFI_STATUS +NorFlashWriteSingleWord ( + IN NOR_FLASH_INSTANCE *Instance, + IN UINTN WordAddress, + IN UINT32 WriteData + ); + +VOID +EFIAPI +NorFlashVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +#endif /* __NOR_FLASH_H__ */ diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/ArmPlatform= Pkg/Drivers/NorFlashDxe/NorFlash.c similarity index 71% copy from ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c copy to ArmPlatformPkg/Drivers/NorFlashDxe/NorFlash.c index 20134094badc..fcc0878fd1d9 100644 --- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlash.c @@ -1,166 +1,21 @@ -/** @file NorFlashDxe.c +/** @file NorFlash.c =20 Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.
+ Copyright (c) 2020, Linaro, Ltd. All rights reserved.
=20 SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ =20 -#include #include -#include -#include -#include =20 -#include "NorFlashDxe.h" - -STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent; +#include "NorFlash.h" =20 // // Global variable declarations // -NOR_FLASH_INSTANCE **mNorFlashInstances; -UINT32 mNorFlashDeviceCount; - -NOR_FLASH_INSTANCE mNorFlashInstanceTemplate =3D { - NOR_FLASH_SIGNATURE, // Signature - NULL, // Handle ... NEED TO BE FILLED - - 0, // DeviceBaseAddress ... NEED TO BE FILLED - 0, // RegionBaseAddress ... NEED TO BE FILLED - 0, // Size ... NEED TO BE FILLED - 0, // StartLba - - { - EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision - NULL, // Media ... NEED TO BE FILLED - NorFlashBlockIoReset, // Reset; - NorFlashBlockIoReadBlocks, // ReadBlocks - NorFlashBlockIoWriteBlocks, // WriteBlocks - NorFlashBlockIoFlushBlocks // FlushBlocks - }, // BlockIoProtocol - - { - 0, // MediaId ... NEED TO BE FILLED - FALSE, // RemovableMedia - TRUE, // MediaPresent - FALSE, // LogicalPartition - FALSE, // ReadOnly - FALSE, // WriteCaching; - 0, // BlockSize ... NEED TO BE FILLED - 4, // IoAlign - 0, // LastBlock ... NEED TO BE FILLED - 0, // LowestAlignedLba - 1, // LogicalBlocksPerPhysicalBlock - }, //Media; - - { - EFI_DISK_IO_PROTOCOL_REVISION, // Revision - NorFlashDiskIoReadDisk, // ReadDisk - NorFlashDiskIoWriteDisk // WriteDisk - }, - - { - FvbGetAttributes, // GetAttributes - FvbSetAttributes, // SetAttributes - FvbGetPhysicalAddress, // GetPhysicalAddress - FvbGetBlockSize, // GetBlockSize - FvbRead, // Read - FvbWrite, // Write - FvbEraseBlocks, // EraseBlocks - NULL, //ParentHandle - }, // FvbProtoccol; - NULL, // ShadowBuffer - { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)), - (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8) - } - }, - { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, // GU= ID ... NEED TO BE FILLED - }, - 0, // Index - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } - } - } // DevicePath -}; - -EFI_STATUS -NorFlashCreateInstance ( - IN UINTN NorFlashDeviceBase, - IN UINTN NorFlashRegionBase, - IN UINTN NorFlashSize, - IN UINT32 Index, - 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),&mNorFl= ashInstanceTemplate); - 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 Index; - Instance->Media.BlockSize =3D BlockSize; - Instance->Media.LastBlock =3D (NorFlashSize / BlockSize)-1; - - CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); - Instance->DevicePath.Index =3D (UINT8)Index; - - Instance->ShadowBuffer =3D AllocateRuntimePool (BlockSize);; - if (Instance->ShadowBuffer =3D=3D NULL) { - return EFI_OUT_OF_RESOURCES; - } - - if (SupportFvb) { - NorFlashFvbInitialize (Instance); - - Status =3D gBS->InstallMultipleProtocolInterfaces ( - &Instance->Handle, - &gEfiDevicePathProtocolGuid, &Instance->DevicePath, - &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol, - &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProt= ocol, - NULL - ); - if (EFI_ERROR(Status)) { - FreePool (Instance); - return Status; - } - } else { - Status =3D gBS->InstallMultipleProtocolInterfaces ( - &Instance->Handle, - &gEfiDevicePathProtocolGuid, &Instance->DevicePath, - &gEfiBlockIoProtocolGuid, &Instance->BlockIoProtocol, - &gEfiDiskIoProtocolGuid, &Instance->DiskIoProtocol, - NULL - ); - if (EFI_ERROR(Status)) { - FreePool (Instance); - return Status; - } - } - - *NorFlashInstance =3D Instance; - return Status; -} +extern NOR_FLASH_INSTANCE **mNorFlashInstances; +extern UINT32 mNorFlashDeviceCount; =20 UINT32 NorFlashReadStatusRegister ( @@ -248,7 +103,6 @@ NorFlashUnlockSingleBlock ( return EFI_SUCCESS; } =20 -STATIC EFI_STATUS NorFlashUnlockSingleBlockIfNecessary ( IN NOR_FLASH_INSTANCE *Instance, @@ -270,7 +124,6 @@ NorFlashUnlockSingleBlockIfNecessary ( /** * The following function presumes that the block has already been unlocke= d. **/ -STATIC EFI_STATUS NorFlashEraseSingleBlock ( IN NOR_FLASH_INSTANCE *Instance, @@ -323,54 +176,6 @@ NorFlashEraseSingleBlock ( return Status; } =20 -/** - * 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; - - if (!EfiAtRuntime ()) { - // Raise TPL to TPL_HIGH to stop anyone from interrupting us. - OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); - } else { - // This initialization is only to prevent the compiler to complain abo= ut the - // use of uninitialized variables - OriginalTPL =3D TPL_HIGH_LEVEL; - } - - 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, BlockAddres= s); - if (EFI_ERROR (Status)) { - break; - } - Status =3D NorFlashEraseSingleBlock (Instance, BlockAddress); - Index++; - } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status =3D=3D EFI_WRITE_PRO= TECTED)); - - if (Index =3D=3D NOR_FLASH_ERASE_RETRY) { - DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=3D0x%08x: Block Lock= ed Error (try to erase %d times)\n", BlockAddress,Index)); - } - - if (!EfiAtRuntime ()) { - // Interruptions can resume. - gBS->RestoreTPL (OriginalTPL); - } - - return Status; -} - - -STATIC EFI_STATUS NorFlashWriteSingleWord ( IN NOR_FLASH_INSTANCE *Instance, @@ -562,111 +367,6 @@ NorFlashWriteBuffer ( return Status; } =20 -STATIC -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, Lba= , BlockSizeInWords * 4); - - // Start writing from the first address at the start of the block - WordAddress =3D BlockAddress; - - if (!EfiAtRuntime ()) { - // Raise TPL to TPL_HIGH to stop anyone from interrupting us. - OriginalTPL =3D gBS->RaiseTPL (TPL_HIGH_LEVEL); - } else { - // This initialization is only to prevent the compiler to complain abo= ut the - // use of uninitialized variables - OriginalTPL =3D TPL_HIGH_LEVEL; - } - - Status =3D NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Er= ase the single block at 0x%X\n", BlockAddress)); - goto EXIT; - } - - // To speed up the programming operation, NOR Flash is programmed using = the Buffered Programming method. - - // Check that the address starts at a 32-word boundary, i.e. last 7 bits= 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_SIZE= _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=3D0; - BufferIndex < BuffersInBlock; - BufferIndex++, WordAddress +=3D P30_MAX_BUFFER_SIZE_IN_BYTES, Dat= aBuffer +=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_B= UFFER_SIZE_IN_BYTES, - DataBuffer); - if (EFI_ERROR(Status)) { - goto EXIT; - } - break; - } - } - } - - // Finally, finish off any remaining words that are less than the maxi= mum size of the buffer - RemainingWords =3D BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS; - - if(RemainingWords !=3D 0) { - Status =3D NorFlashWriteBuffer (Instance, WordAddress, (RemainingWor= ds * 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 fa= lls within a 32 word boundary range, - // i.e. which ends in the range 0x......01 - 0x......7F. - for(WordIndex=3D0; WordIndexRestoreTPL (OriginalTPL); - } - - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed a= t address 0x%08x. Exit Status =3D \"%r\".\n", WordAddress, Status)); - } - return Status; -} - - EFI_STATUS NorFlashWriteBlocks ( IN NOR_FLASH_INSTANCE *Instance, @@ -1271,65 +971,3 @@ NorFlashVirtualNotifyEvent ( =20 return; } - -EFI_STATUS -EFIAPI -NorFlashInitialise ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - UINT32 Index; - NOR_FLASH_DESCRIPTION* NorFlashDevices; - BOOLEAN ContainVariableStorage; - - Status =3D NorFlashPlatformInitialization (); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to initialize Nor Flash d= evices\n")); - return Status; - } - - Status =3D NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDevic= eCount); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to get Nor Flash devices\= n")); - return Status; - } - - mNorFlashInstances =3D AllocateRuntimePool (sizeof(NOR_FLASH_INSTANCE*) = * mNorFlashDeviceCount); - - for (Index =3D 0; Index < mNorFlashDeviceCount; Index++) { - // Check if this NOR Flash device contain the variable storage region - ContainVariableStorage =3D - (NorFlashDevices[Index].RegionBaseAddress <=3D PcdGet32 (PcdFlashN= vStorageVariableBase)) && - (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvSt= orageVariableSize) <=3D NorFlashDevices[Index].RegionBaseAddress + NorFlash= Devices[Index].Size); - - Status =3D NorFlashCreateInstance ( - NorFlashDevices[Index].DeviceBaseAddress, - NorFlashDevices[Index].RegionBaseAddress, - NorFlashDevices[Index].Size, - Index, - NorFlashDevices[Index].BlockSize, - ContainVariableStorage, - &mNorFlashInstances[Index] - ); - if (EFI_ERROR(Status)) { - DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to create instance for = NorFlash[%d]\n",Index)); - } - } - - // - // Register for the virtual address change event - // - Status =3D gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - NorFlashVirtualNotifyEvent, - NULL, - &gEfiEventVirtualAddressChangeGuid, - &mNorFlashVirtualAddrChangeEvent - ); - ASSERT_EFI_ERROR (Status); - - return Status; -} diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c b/ArmP= latformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c index 689d6522389b..793f26c4df68 100644 --- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashBlockIoDxe.c @@ -9,7 +9,7 @@ #include #include =20 -#include "NorFlashDxe.h" +#include "NorFlash.h" =20 // // BlockIO Protocol function EFI_BLOCK_IO_PROTOCOL.Reset diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c b/ArmPlatform= Pkg/Drivers/NorFlashDxe/NorFlashDxe.c index 20134094badc..41cdd1cbd397 100644 --- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c @@ -11,8 +11,10 @@ #include #include #include +#include +#include =20 -#include "NorFlashDxe.h" +#include "NorFlash.h" =20 STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent; =20 @@ -21,6 +23,8 @@ STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent; // NOR_FLASH_INSTANCE **mNorFlashInstances; UINT32 mNorFlashDeviceCount; +UINTN mFlashNvStorageVariableBase; +EFI_EVENT mFvbVirtualAddrChangeEvent; =20 NOR_FLASH_INSTANCE mNorFlashInstanceTemplate =3D { NOR_FLASH_SIGNATURE, // Signature @@ -162,167 +166,6 @@ NorFlashCreateInstance ( return Status; } =20 -UINT32 -NorFlashReadStatusRegister ( - 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_RE= GISTER); - 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((EFI_D_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN= \n")); - } - - return ((LockStatus & 0x1) !=3D 0); -} - -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 oper= ations - // 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", BlockA= ddress)); - - return EFI_SUCCESS; -} - -STATIC -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 unlocke= d. - **/ -STATIC -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, BlockAddress); - } while ((StatusRegister & P30_SR_BIT_WRITE) !=3D P30_SR_BIT_WRITE); - - if (StatusRegister & P30_SR_BIT_VPP) { - DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=3D0x%08x: VPP Range = Error\n", BlockAddress)); - Status =3D EFI_DEVICE_ERROR; - } - - if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) =3D=3D (P= 30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) { - DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=3D0x%08x: Command Se= quence Error\n", BlockAddress)); - Status =3D EFI_DEVICE_ERROR; - } - - if (StatusRegister & P30_SR_BIT_ERASE) { - DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=3D0x%08x: Block Eras= e 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 migh= t happen. In this case we just retry it ... - DEBUG((EFI_D_INFO,"EraseSingleBlock(BlockAddress=3D0x%08x: Block Locke= d 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_STATUS= _REGISTER); - } - - // Put device back into Read Array mode - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); - - return Status; -} - /** * This function unlock and erase an entire NOR Flash block. **/ @@ -369,200 +212,6 @@ NorFlashUnlockAndEraseSingleBlock ( return Status; } =20 - -STATIC -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. ch= eck 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((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): VPP Ran= ge Error\n",WordAddress)); - Status =3D EFI_DEVICE_ERROR; - } - - if (StatusRegister & P30_SR_BIT_PROGRAM) { - DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Program= Error\n",WordAddress)); - Status =3D EFI_DEVICE_ERROR; - } - - if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { - DEBUG((EFI_D_ERROR,"NorFlashWriteSingleWord(WordAddress:0x%X): Device = 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_STATUS= _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 hardware= restrictions. - * Therefore this function will only handle buffers up to 32 words or 128 = bytes. - * To deal with larger buffers, call this function again. - * - * This function presumes that both the TargetAddress and the TargetAddres= s+BufferSize - * exist entirely within the NOR Flash. Therefore these conditions will no= t be checked here. - * - * In buffered programming, if the target address not at the beginning of = 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 bo= undaries. - * 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 - ) -{ - 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 buffe= r 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=3D0; Count < BufferSizeInWords; Count++, Data++, Buffer++) { - MmioWrite32 ((UINTN)Data, *Buffer); - } - - // Issue the Buffered Program Confirm command, to start the programming = operation - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGR= AM_CONFIRM); - - // Wait for the write to complete and then check for any errors; i.e. ch= eck the Status Register - do { - StatusRegister =3D NorFlashReadStatusRegister (Instance, TargetAddress= ); - // 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((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range= Error\n", TargetAddress)); - Status =3D EFI_DEVICE_ERROR; - } - - if (StatusRegister & P30_SR_BIT_PROGRAM) { - DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): Program E= rror\n", TargetAddress)); - Status =3D EFI_DEVICE_ERROR; - } - - if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) { - DEBUG((EFI_D_ERROR,"NorFlashWriteBuffer(TargetAddress:0x%X): Device Pr= otect 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_STATUS= _REGISTER); - } - -EXIT: - // Put device back into Read Array mode - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); - - return Status; -} - -STATIC EFI_STATUS NorFlashWriteFullBlock ( IN NOR_FLASH_INSTANCE *Instance, @@ -666,612 +315,6 @@ NorFlashWriteFullBlock ( return Status; } =20 - -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", B= ufferSizeInBytes)); - 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%l= d, Lba=3D%ld.\n", NumBlocks, Instance->Media.LastBlock, Lba)); - - if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) { - DEBUG((EFI_D_ERROR, "NorFlashWriteBlocks: ERROR - Write will exceed la= st 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 the = data into a pointer - // to a proper data type, so use *ReadBuffer - pWriteBuffer =3D (UINT32 *)Buffer; - - CurrentBlock =3D Lba; - for (BlockCount=3D0; BlockCount < NumBlocks; BlockCount++, CurrentBlock+= +, pWriteBuffer =3D pWriteBuffer + BlockSizeInWords) { - - DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN= )CurrentBlock)); - - Status =3D NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffe= r, BlockSizeInWords); - - if (EFI_ERROR(Status)) { - break; - } - } - - DEBUG((DEBUG_BLKIO, "NorFlashWriteBlocks: Exit Status =3D \"%r\".\n", St= atus)); - return Status; -} - -#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) -= 1)) =3D=3D 0) - -/** - Copy Length bytes from Source to Destination, using aligned accesses onl= y. - Note that this implementation uses memcpy() semantics rather then memmov= e() - 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) && Length >= =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=3D= 0x%xB LastBlock=3D%ld, Lba=3D%ld.\n", - BufferSizeInBytes, Instance->Media.BlockSize, Instance->Media.LastBl= ock, 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((EFI_D_ERROR, "NorFlashReadBlocks: ERROR - Read will exceed last= 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) > I= nstance->Size) { - DEBUG ((EFI_D_ERROR, "NorFlashRead: ERROR - Read will exceed device si= ze.\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), BufferSizeInByt= es); - - return EFI_SUCCESS; -} - -/* - Write a full or portion of a block. It must not span block boundaries; t= hat 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, Of= fset=3D0x%x, *NumBytes=3D0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes,= Buffer)); - - // Detect WriteDisabled state - if (Instance->Media.ReadOnly =3D=3D TRUE) { - DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: 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; - - // The write must not span block boundaries. - // We need to check each variable individually because adding two large = values together overflows. - if ( ( Offset >=3D BlockSize ) || - ( *NumBytes > BlockSize ) || - ( (Offset + *NumBytes) > BlockSize ) ) { - DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER= _SIZE: (Offset=3D0x%x + NumBytes=3D0x%x) > BlockSize=3D0x%x\n", Offset, *Nu= mBytes, BlockSize )); - return EFI_BAD_BUFFER_SIZE; - } - - // We must have some bytes to write - if (*NumBytes =3D=3D 0) { - DEBUG ((EFI_D_ERROR, "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER= _SIZE: (Offset=3D0x%x + NumBytes=3D0x%x) > BlockSize=3D0x%x\n", Offset, *Nu= mBytes, BlockSize )); - return EFI_BAD_BUFFER_SIZE; - } - - // 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) { - // Check to see if we need to erase before programming the data into N= OR. - // 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 FALSE; - BytesToWrite =3D *NumBytes; - CurOffset =3D Offset; - - while (BytesToWrite > 0) { - // Read full word from NOR, splice as required. A word is the smalle= st - // unit we can write. - TempStatus =3D NorFlashRead (Instance, Lba, CurOffset & ~(0x3), size= of(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, BlockS= ize); - // 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->RegionBaseAddress,= Lba, BlockSize); - if (BlockAddress !=3D PrevBlockAddress) { - TempStatus =3D NorFlashUnlockSingleBlockIfNecessary (Instance, Blo= ckAddress); - if (EFI_ERROR (TempStatus)) { - return EFI_DEVICE_ERROR; - } - PrevBlockAddress =3D BlockAddress; - } - TempStatus =3D NorFlashWriteSingleWord (Instance, WordAddr, WordToWr= ite); - if (EFI_ERROR (TempStatus)) { - return EFI_DEVICE_ERROR; - } - } - // Exit if we got here and could write all the data. Otherwise do the - // Erase-Write cycle. - if (!DoErase) { - return EFI_SUCCESS; - } - } - - // Check we did get some memory. Buffer is BlockSize. - if (Instance->ShadowBuffer =3D=3D NULL) { - DEBUG ((EFI_D_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->S= hadowBuffer); - 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, *NumBy= tes); - - // 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; -} - -/* - Although DiskIoDxe will automatically install the DiskIO protocol whenev= er - we install the BlockIO protocol, its implementation is sub-optimal as it= reads - and writes entire blocks using the BlockIO protocol. In fact we can acce= ss - NOR flash with a finer granularity than that, so we can improve performa= nce - by directly producing the DiskIO protocol. -*/ - -/** - Read BufferSize bytes from Offset into Buffer. - - @param This Protocol instance pointer. - @param MediaId Id of the media, changes every time the me= dia is replaced. - @param Offset The starting byte offset to read from - @param BufferSize Size of Buffer - @param Buffer Buffer containing read data - - @retval EFI_SUCCESS The data was read correctly from the devic= e. - @retval EFI_DEVICE_ERROR The device reported an error while perform= ing the read. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId does not match the current dev= ice. - @retval EFI_INVALID_PARAMETER The read request contains device addresses= that are not - valid for the device. - -**/ -EFI_STATUS -EFIAPI -NorFlashDiskIoReadDisk ( - IN EFI_DISK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN UINT64 DiskOffset, - IN UINTN BufferSize, - OUT VOID *Buffer - ) -{ - NOR_FLASH_INSTANCE *Instance; - UINT32 BlockSize; - UINT32 BlockOffset; - EFI_LBA Lba; - - Instance =3D INSTANCE_FROM_DISKIO_THIS(This); - - if (MediaId !=3D Instance->Media.MediaId) { - return EFI_MEDIA_CHANGED; - } - - BlockSize =3D Instance->Media.BlockSize; - Lba =3D (EFI_LBA) DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffse= t); - - return NorFlashRead (Instance, Lba, BlockOffset, BufferSize, Buffer); -} - -/** - Writes a specified number of bytes to a device. - - @param This Indicates a pointer to the calling context. - @param MediaId ID of the medium to be written. - @param Offset The starting byte offset on the logical block I/O dev= ice to write. - @param BufferSize The size in bytes of Buffer. The number of bytes to w= rite to the device. - @param Buffer A pointer to the buffer containing the data to be wri= tten. - - @retval EFI_SUCCESS The data was written correctly to the devi= ce. - @retval EFI_WRITE_PROTECTED The device can not be written to. - @retval EFI_DEVICE_ERROR The device reported an error while perform= ing the write. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId does not match the current dev= ice. - @retval EFI_INVALID_PARAMETER The write request contains device addresse= s that are not - valid for the device. - -**/ -EFI_STATUS -EFIAPI -NorFlashDiskIoWriteDisk ( - IN EFI_DISK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN UINT64 DiskOffset, - IN UINTN BufferSize, - IN VOID *Buffer - ) -{ - NOR_FLASH_INSTANCE *Instance; - UINT32 BlockSize; - UINT32 BlockOffset; - EFI_LBA Lba; - UINTN RemainingBytes; - UINTN WriteSize; - EFI_STATUS Status; - - Instance =3D INSTANCE_FROM_DISKIO_THIS(This); - - if (MediaId !=3D Instance->Media.MediaId) { - return EFI_MEDIA_CHANGED; - } - - BlockSize =3D Instance->Media.BlockSize; - Lba =3D (EFI_LBA) DivU64x32Remainder (DiskOffset, BlockSize, &BlockOffse= t); - - RemainingBytes =3D BufferSize; - - // Write either all the remaining bytes, or the number of bytes that bri= ng - // us up to a block boundary, whichever is less. - // (DiskOffset | (BlockSize - 1)) + 1) rounds DiskOffset up to the next - // block boundary (even if it is already on one). - WriteSize =3D MIN (RemainingBytes, ((DiskOffset | (BlockSize - 1)) + 1) = - DiskOffset); - - do { - if (WriteSize =3D=3D BlockSize) { - // Write a full block - Status =3D NorFlashWriteFullBlock (Instance, Lba, Buffer, BlockSize = / sizeof (UINT32)); - } else { - // Write a partial block - Status =3D NorFlashWriteSingleBlock (Instance, Lba, BlockOffset, &Wr= iteSize, Buffer); - } - if (EFI_ERROR (Status)) { - return Status; - } - // Now continue writing either all the remaining bytes or single block= s. - RemainingBytes -=3D WriteSize; - Buffer =3D (UINT8 *) Buffer + WriteSize; - Lba++; - BlockOffset =3D 0; - WriteSize =3D MIN (RemainingBytes, BlockSize); - } while (RemainingBytes); - - return Status; -} - -EFI_STATUS -NorFlashReset ( - IN NOR_FLASH_INSTANCE *Instance - ) -{ - // As there is no specific RESET to perform, ensure that the devices is = in the default Read Array mode - SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY); - 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]->ShadowBu= ffer); - } - } - - return; -} - EFI_STATUS EFIAPI NorFlashInitialise ( @@ -1333,3 +376,102 @@ NorFlashInitialise ( =20 return Status; } + +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")); + ASSERT((Instance !=3D NULL)); + + // + // 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); + + mFlashNvStorageVariableBase =3D PcdGet32 (PcdFlashNvStorageVariableBase); + + // Set the index of the first LBA for the FVB + Instance->StartLba =3D (PcdGet32 (PcdFlashNvStorageVariableBase) - Insta= nce->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(PcdF= lashNvStorageFtwWorkingSize) + PcdGet32(PcdFlashNvStorageFtwSpareSize)) / I= nstance->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; + } + } + + // + // The driver implementing the variable read service can now be dispatch= ed; + // the varstore headers are in place. + // + Status =3D gBS->InstallProtocolInterface ( + &gImageHandle, + &gEdkiiNvVarStoreFormattedGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + 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/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/ArmPlatf= ormPkg/Drivers/NorFlashDxe/NorFlashFvb.c similarity index 85% rename from ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c rename to ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c index 9cdd85096a46..a332b5e98be7 100644 --- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvb.c @@ -10,22 +10,17 @@ =20 #include #include -#include #include #include #include -#include -#include =20 #include #include #include =20 -#include "NorFlashDxe.h" - -STATIC EFI_EVENT mFvbVirtualAddrChangeEvent; -STATIC UINTN mFlashNvStorageVariableBase; +#include "NorFlash.h" =20 +extern UINTN mFlashNvStorageVariableBase; /// /// The Firmware Volume Block Protocol is the low-level interface /// to a firmware volume. File-level access to a firmware volume @@ -700,101 +695,3 @@ FvbVirtualNotifyEvent ( return; } =20 -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")); - ASSERT((Instance !=3D NULL)); - - // - // 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); - - mFlashNvStorageVariableBase =3D PcdGet32 (PcdFlashNvStorageVariableBase); - - // Set the index of the first LBA for the FVB - Instance->StartLba =3D (PcdGet32 (PcdFlashNvStorageVariableBase) - Insta= nce->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 ((EFI_D_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__= )); - DEBUG ((EFI_D_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(PcdF= lashNvStorageFtwWorkingSize) + PcdGet32(PcdFlashNvStorageFtwSpareSize)) / I= nstance->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; - } - } - - // - // The driver implementing the variable read service can now be dispatch= ed; - // the varstore headers are in place. - // - Status =3D gBS->InstallProtocolInterface ( - &gImageHandle, - &gEdkiiNvVarStoreFormattedGuid, - EFI_NATIVE_INTERFACE, - NULL - ); - 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; -} --=20 2.17.1 -=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 (#69178): https://edk2.groups.io/g/devel/message/69178 Mute This Topic: https://groups.io/mt/79058287/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Sun Apr 28 20:02:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+69179+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+69179+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1608285872; cv=none; d=zohomail.com; s=zohoarc; b=GQeagWGYtaTRaxLHMGm7Ru4IR/lAFkDdupd8J1/pxN9P1YasLs5G4OYZp4zBwvzkzsPUnxiEHyDmC167KvI3vkXNF+ZN3nLzIpov7q56ybHaXf2rYuOecj9Y+sITeqYo3sSTWIu+7Tmsz+fUnUn2FPA4BhPWARRNaHO+dGdxCwk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1608285872; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=VGOZT+IMsIM57UR6d6QMQwyPPkJajWMVTRXmTxsNewk=; b=HMnmuqEf3ZQzr9nPlAYeo6USdE82Fi4l3Xuy6kdv+cranZ9+Hv1FicBKXmlflDap1cd6T6r0f/8cZj5HbiDdt/kBj2D2Co3cTyGyKj+iQRHHIzxEqYQeaYzQjhjFEnozdcrbI3QXclyVjGG6qOmsZLhhOShxH8Hg8FokszhJziA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+69179+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1608285872622949.6734644327163; Fri, 18 Dec 2020 02:04:32 -0800 (PST) Return-Path: X-Received: by 127.0.0.2 with SMTP id 5dP7YY1788612xcrTsGl2K9R; Fri, 18 Dec 2020 02:04:31 -0800 X-Received: from mail-pg1-f170.google.com (mail-pg1-f170.google.com [209.85.215.170]) by mx.groups.io with SMTP id smtpd.web10.7866.1608285866064200125 for ; Fri, 18 Dec 2020 02:04:26 -0800 X-Received: by mail-pg1-f170.google.com with SMTP id w5so1031483pgj.3 for ; Fri, 18 Dec 2020 02:04:26 -0800 (PST) X-Gm-Message-State: nXvm2OdtdMOVP5qUGLmrk4fgx1787277AA= X-Google-Smtp-Source: ABdhPJwZzw5o73z+5pSh71mH2UcOXNDZrrZAJMK074Q5I1hyJ7m1LxjF5NQdDG7kVMVUD/xi0NaYSw== X-Received: by 2002:aa7:83cd:0:b029:1a5:fb23:ad7f with SMTP id j13-20020aa783cd0000b02901a5fb23ad7fmr3546486pfn.46.1608285865083; Fri, 18 Dec 2020 02:04:25 -0800 (PST) X-Received: from localhost ([121.95.100.191]) by smtp.gmail.com with ESMTPSA id a8sm8142136pfo.209.2020.12.18.02.04.23 (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Fri, 18 Dec 2020 02:04:24 -0800 (PST) From: "Masahisa Kojima" To: devel@edk2.groups.io Cc: Masahisa Kojima , Leif Lindholm , Ard Biesheuvel , Sami Mujawar , Jiewen Yao , Supreeth Venkatesh Subject: [edk2-devel] [PATCH 2/2] ArmPlatformPkg/NorFlashDxe: implement standalone MM version Date: Fri, 18 Dec 2020 19:05:16 +0900 Message-Id: <20201218100516.14149-3-masahisa.kojima@linaro.org> In-Reply-To: <20201218100516.14149-1-masahisa.kojima@linaro.org> References: <20201218100516.14149-1-masahisa.kojima@linaro.org> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,masahisa.kojima@linaro.org Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1608285871; bh=nPCrhwE0UY/ht6IpHxJzYmbIRTrnkKsaOKs8grhfuTc=; h=Cc:Date:From:Reply-To:Subject:To; b=pOoVFB/ChyOHvFf0Xls77YztY15312Oxbg8KgzCzon56+WDVnJ/bn6C625d36ph70C1 kaQgP8lxFsRUF8Oa8Ralu6+YptyJEoa4kuTMBCAqMX1S8W6dUq9hL6n6bKOyt1gVWnvvI Tl+TIsh5kWQ+yTQMXX49SDtllVfh36DTFpA= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Type: text/plain; charset="utf-8" Implement a version of the NOR Flash driver that can execute in standalone MM context. This is used to access the secure variable storage, it only supports EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL. Signed-off-by: Masahisa Kojima Cc: Leif Lindholm Cc: Ard Biesheuvel Cc: Sami Mujawar Cc: Jiewen Yao Cc: Supreeth Venkatesh Reviewed-by: Ard Biesheuvel --- ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf | 63 ++++ ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c | 364 ++++++++= ++++++++++++ 2 files changed, 427 insertions(+) diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf b/= ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf new file mode 100644 index 000000000000..f788472406b7 --- /dev/null +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.inf @@ -0,0 +1,63 @@ +#/** @file +# +# Component description file for NorFlashStandaloneMm module +# +# Copyright (c) 2011 - 2014, ARM Ltd. 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 ArmVeNorFlashStandaloneMm + FILE_GUID =3D e67d82ad-cd56-4071-9151-95ee44990bb0 + MODULE_TYPE =3D MM_STANDALONE + VERSION_STRING =3D 1.0 + PI_SPECIFICATION_VERSION =3D 0x00010032 + ENTRY_POINT =3D NorFlashInitialise + +[Sources.common] + NorFlash.h + NorFlash.c + NorFlashStandaloneMm.c + NorFlashFvb.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + IoLib + MemoryAllocationLib + MmServicesTableLib + NorFlashPlatformLib + StandaloneMmDriverEntryPoint + +[Guids] + gEfiSystemNvDataFvGuid + gEfiVariableGuid + gEfiAuthenticatedVariableGuid + +[Protocols] + gEfiSmmFirmwareVolumeBlockProtocolGuid + +[Pcd.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + + gArmPlatformTokenSpaceGuid.PcdNorFlashCheckBlockLocked + +[Depex] + TRUE diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c b/Ar= mPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c new file mode 100644 index 000000000000..1ebf6d6ba70b --- /dev/null +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashStandaloneMm.c @@ -0,0 +1,364 @@ +/** @file NorFlashStandaloneMm.c + + Copyright (c) 2011 - 2020, Arm Limited. All rights reserved.
+ Copyright (c) 2020, Linaro, Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include "NorFlash.h" + +// +// Global variable declarations +// +NOR_FLASH_INSTANCE **mNorFlashInstances; +UINT32 mNorFlashDeviceCount; +UINTN mFlashNvStorageVariableBase; + +NOR_FLASH_INSTANCE mNorFlashInstanceTemplate =3D { + NOR_FLASH_SIGNATURE, // Signature + NULL, // Handle ... NEED TO BE FILLED + + 0, // DeviceBaseAddress ... NEED TO BE FILLED + 0, // RegionBaseAddress ... NEED TO BE FILLED + 0, // Size ... NEED TO BE FILLED + 0, // StartLba + + { + EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision + NULL, // Media ... NEED TO BE FILLED + NULL, // Reset; + NULL, // ReadBlocks + NULL, // WriteBlocks + NULL // FlushBlocks + }, // BlockIoProtocol + + { + 0, // MediaId ... NEED TO BE FILLED + FALSE, // RemovableMedia + TRUE, // MediaPresent + FALSE, // LogicalPartition + FALSE, // ReadOnly + FALSE, // WriteCaching; + 0, // BlockSize ... NEED TO BE FILLED + 4, // IoAlign + 0, // LastBlock ... NEED TO BE FILLED + 0, // LowestAlignedLba + 1, // LogicalBlocksPerPhysicalBlock + }, //Media; + + { + EFI_DISK_IO_PROTOCOL_REVISION, // Revision + NULL, // ReadDisk + NULL // WriteDisk + }, + + { + FvbGetAttributes, // GetAttributes + FvbSetAttributes, // SetAttributes + FvbGetPhysicalAddress, // GetPhysicalAddress + FvbGetBlockSize, // GetBlockSize + FvbRead, // Read + FvbWrite, // Write + FvbEraseBlocks, // EraseBlocks + NULL, //ParentHandle + }, // FvbProtoccol; + NULL, // ShadowBuffer + { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)), + (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8) + } + }, + { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, // GU= ID ... NEED TO BE FILLED + }, + 0, // Index + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } + } + } // DevicePath +}; + +EFI_STATUS +NorFlashCreateInstance ( + IN UINTN NorFlashDeviceBase, + IN UINTN NorFlashRegionBase, + IN UINTN NorFlashSize, + IN UINT32 Index, + 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),&mNorFl= ashInstanceTemplate); + 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 Index; + Instance->Media.BlockSize =3D BlockSize; + Instance->Media.LastBlock =3D (NorFlashSize / BlockSize)-1; + + CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid); + Instance->DevicePath.Index =3D (UINT8)Index; + + Instance->ShadowBuffer =3D AllocateRuntimePool (BlockSize);; + if (Instance->ShadowBuffer =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (SupportFvb) { + NorFlashFvbInitialize (Instance); + + Status =3D gMmst->MmInstallProtocolInterface ( + &Instance->Handle, + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + EFI_NATIVE_INTERFACE, + &Instance->FvbProtocol + ); + if (EFI_ERROR(Status)) { + FreePool (Instance); + return Status; + } + } else { + DEBUG((DEBUG_ERROR,"standalone MM NOR Flash driver only support FVB.\n= ")); + FreePool (Instance); + return EFI_UNSUPPORTED; + } + + *NorFlashInstance =3D Instance; + return Status; +} + +/** + * 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; + + 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, BlockAddres= s); + if (EFI_ERROR (Status)) { + break; + } + Status =3D NorFlashEraseSingleBlock (Instance, BlockAddress); + Index++; + } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status =3D=3D EFI_WRITE_PRO= TECTED)); + + if (Index =3D=3D NOR_FLASH_ERASE_RETRY) { + DEBUG((DEBUG_ERROR,"EraseSingleBlock(BlockAddress=3D0x%08x: Block Lock= ed Error (try to erase %d times)\n", BlockAddress,Index)); + } + + 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; + UINTN Cnt; + + Status =3D EFI_SUCCESS; + + // Get the physical address of the block + BlockAddress =3D GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba= , BlockSizeInWords * 4); + + // Start writing from the first address at the start of the block + WordAddress =3D BlockAddress; + + Status =3D NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); + if (EFI_ERROR(Status)) { + DEBUG((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Er= ase the single block at 0x%X\n", BlockAddress)); + goto EXIT; + } + + // To speed up the programming operation, NOR Flash is programmed using = the Buffered Programming method. + + // Check that the address starts at a 32-word boundary, i.e. last 7 bits= 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_SIZE= _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=3D0; + BufferIndex < BuffersInBlock; + BufferIndex++, WordAddress +=3D P30_MAX_BUFFER_SIZE_IN_BYTES, Dat= aBuffer +=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_B= UFFER_SIZE_IN_BYTES, + DataBuffer); + if (EFI_ERROR(Status)) { + goto EXIT; + } + break; + } + } + } + + // Finally, finish off any remaining words that are less than the maxi= mum size of the buffer + RemainingWords =3D BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS; + + if(RemainingWords !=3D 0) { + Status =3D NorFlashWriteBuffer (Instance, WordAddress, (RemainingWor= ds * 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 fa= lls within a 32 word boundary range, + // i.e. which ends in the range 0x......01 - 0x......7F. + for(WordIndex=3D0; WordIndexStartLba =3D (PcdGet32 (PcdFlashNvStorageVariableBase) - Insta= nce->RegionBaseAddress) / Instance->Media.BlockSize; + + // Determine if there is a valid header at the beginning of the NorFlash + 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(PcdF= lashNvStorageFtwWorkingSize) + PcdGet32(PcdFlashNvStorageFtwSpareSize)) / I= nstance->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; + } + } + + return Status; +} --=20 2.17.1 -=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 (#69179): https://edk2.groups.io/g/devel/message/69179 Mute This Topic: https://groups.io/mt/79058288/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-