From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:400e:c00::244; helo=mail-pf0-x244.google.com; envelope-from=kalyankumar.nagabhirava@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-pf0-x244.google.com (mail-pf0-x244.google.com [IPv6:2607:f8b0:400e:c00::244]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 51C742035A7AF for ; Tue, 21 Nov 2017 02:51:33 -0800 (PST) Received: by mail-pf0-x244.google.com with SMTP id r88so5629561pfi.2 for ; Tue, 21 Nov 2017 02:55:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=J5Owamx/LXAxgN+7bxx9gcTvlx/3pLcg4S8dRrKuR0k=; b=VMTf8q0KtY66k0PzQPpUat5uKYxyOsEGHPn6SEItIElYYNYxZRfbWeF2XiFbIA6pHt a5HXDuQHUruSTWDdWdviSMO182KA4y3s7djujWRqt9MfTopKRwfQIUbSwvXdgjEPJt9i XvRdJYinM9ByduEFmvhRLZplLGBmb7Ieki3IE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=J5Owamx/LXAxgN+7bxx9gcTvlx/3pLcg4S8dRrKuR0k=; b=X+jpcbrPdy7OAps42NH1NuCWerdBim86OQkvqm+IUvHeiNe8dz90d5T4jTs1eAtKAA Qb6Grt5RhnAcJ9hVmIbhOUrxVLJlnB4D1Pv0eU9+Ck2oEL7nIoGn0D7evq11ThrsOaJs f/2ff1olEDRGfTwke52bT4Yy+Bn+c4R4ori6ItPP7b0OIcUZLc6LNpVHqElAKNZ81BzP rOYKAyMbFBYmCmj+kDGAtsx6CAuykaZOJGHr/pSCei0w+tzVYlXfqprIG/vnNV/LMBAc rLEoShZFm1WtPTLpvVC5ra1CB25PZlM8vIg4yuL9KiKenmk9gYi/uNZ5Y5T+TL6XAu61 ycRg== X-Gm-Message-State: AJaThX7yui/HecLhPy3HwJelCBrVOpKwn7vDEHHVCMUs6jc5HosC9tS1 2y8ldkEri7o3ItoLXo7aGS/FgisfI6U= X-Google-Smtp-Source: AGs4zMajH0Th8lTgqWfnH8d3PDqAw9ORArVHqkFiTAOFdzMKvUhBjXplTuk9irbndLKKsGRDbfR5hw== X-Received: by 10.98.85.71 with SMTP id j68mr14826367pfb.222.1511261747748; Tue, 21 Nov 2017 02:55:47 -0800 (PST) Received: from localhost.localdomain ([220.225.120.129]) by smtp.gmail.com with ESMTPSA id 69sm24581795pft.11.2017.11.21.02.55.44 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 21 Nov 2017 02:55:46 -0800 (PST) From: kalyan-nagabhirava To: edk2-devel@lists.01.org, ard.biesheuvel@linaro.org Cc: leif.lindholm@linaro.org, mark.gregotski@linaro.org, kalyan-nagabhirava Date: Tue, 21 Nov 2017 16:23:36 +0530 Message-Id: <20171121105336.26699-1-kalyankumar.nagabhirava@linaro.org> X-Mailer: git-send-email 2.15.0 Subject: [PATCH] [edk2-platforms]:Enabling Secure boot feature support on hikey platfrom X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 21 Nov 2017 10:51:34 -0000 Added required library packages related to secure boot in hikey.dsc and Blockvariable driver[ from 96-board edk2 fork] to support the NV storage of the variables. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: kalyan-nagabhirava --- Platform/Hisilicon/HiKey/HiKey.dec | 10 + Platform/Hisilicon/HiKey/HiKey.dsc | 56 ++- Platform/Hisilicon/HiKey/HiKey.fdf | 13 +- Platform/Hisilicon/HiKey/VarStore.fdf.inc | 72 ++++ .../Drivers/BlockVariableDxe/BlockVariableDxe.c | 444 +++++++++++++++++++++ .../Drivers/BlockVariableDxe/BlockVariableDxe.h | 51 +++ .../Drivers/BlockVariableDxe/BlockVariableDxe.inf | 65 +++ 7 files changed, 706 insertions(+), 5 deletions(-) create mode 100644 Platform/Hisilicon/HiKey/VarStore.fdf.inc create mode 100644 Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.c create mode 100644 Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.h create mode 100644 Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.inf diff --git a/Platform/Hisilicon/HiKey/HiKey.dec b/Platform/Hisilicon/HiKey/HiKey.dec index 537138eb4..e27d70447 100644 --- a/Platform/Hisilicon/HiKey/HiKey.dec +++ b/Platform/Hisilicon/HiKey/HiKey.dec @@ -30,7 +30,17 @@ [Guids.common] gHiKeyTokenSpaceGuid = { 0x91148425, 0xcdd2, 0x4830, { 0x8b, 0xd0, 0xc6, 0x1c, 0x6d, 0xea, 0x36, 0x21 } } + gHwTokenSpaceGuid = { 0x99999999, 0x74c5, 0x4043, { 0xb4, 0x17, 0xa3, 0x22, 0x38, 0x14, 0xce, 0x76 } } [PcdsFixedAtBuild.common] gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001 gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit|L""|VOID*|0x00000002 + + # NV Block + gHwTokenSpaceGuid.PcdNvStorageVariableBlockLba|0|UINT32|0x01000012 + gHwTokenSpaceGuid.PcdNvStorageVariableBlockSize|0|UINT32|0x0100011 + gHwTokenSpaceGuid.PcdNvStorageVariableBlockCount|0|UINT32|0x0100010 + gHwTokenSpaceGuid.PcdNvStorageVariableBlockDevicePath|L""|VOID*|0x01000013 + + # UncachedAllocationLib + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000080000000|UINT64|0x00000002 diff --git a/Platform/Hisilicon/HiKey/HiKey.dsc b/Platform/Hisilicon/HiKey/HiKey.dsc index 2e3b1c879..a7288b125 100644 --- a/Platform/Hisilicon/HiKey/HiKey.dsc +++ b/Platform/Hisilicon/HiKey/HiKey.dsc @@ -26,6 +26,8 @@ SKUID_IDENTIFIER = DEFAULT FLASH_DEFINITION = Platform/Hisilicon/HiKey/HiKey.fdf + DEFINE SECURE_BOOT_ENABLE = FALSE + [LibraryClasses.common] !if $(TARGET) == RELEASE DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf @@ -125,6 +127,18 @@ # Add support for GCC stack protector NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf + BdsLib|ArmPkg/Library/BdsLib/BdsLib.inf + DmaLib|EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.inf +!endif + [LibraryClasses.common.SEC] PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf @@ -160,6 +174,7 @@ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf ReportStatusCodeLib|IntelFrameworkModulePkg/Library/DxeReportStatusCodeLibFramework/DxeReportStatusCodeLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf [BuildOptions] GCC:*_*_*_PLATFORM_FLAGS = -I$(WORKSPACE)/Silicon/Hisilicon/Hi6220/Include -I$(WORKSPACE)/Platform/Hisilicon/HiKey/Include @@ -337,6 +352,29 @@ gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbVendorId|0x18d1 gEmbeddedTokenSpaceGuid.PcdAndroidFastbootUsbProductId|0xd00d + # + # NV Storage PCDs. + # + gHwTokenSpaceGuid.PcdNvStorageVariableBlockCount|0x00001000 + gHwTokenSpaceGuid.PcdNvStorageVariableBlockSize|0x00000200 + gHwTokenSpaceGuid.PcdNvStorageVariableBlockLba|0x00006000 + gHwTokenSpaceGuid.PcdNvStorageVariableBlockDevicePath|L"VenHw(B549F005-4BD4-4020-A0CB-06F42BDA68C3)/HD(5,GPT,00354BCD-BBCB-4CB3-B5AE-CDEFCB5DAC43)" + + # + # ARM Pcds + # + gArmTokenSpaceGuid.PcdArmUncachedMemoryMask|0x0000000000000000 + + # Increase storage space of UEFI variable to 2KB so that it can store root certificate + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x800 + +!if $(SECURE_BOOT_ENABLE) == TRUE + # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot + gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04 + gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04 + gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04 +!endif + ################################################################################ # # Components Section - list of all EDK II Modules needed by this Platform @@ -362,7 +400,6 @@ # ArmPkg/Drivers/CpuDxe/CpuDxe.inf MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf - MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf EmbeddedPkg/EmbeddedMonotonicCounter/EmbeddedMonotonicCounter.inf MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf @@ -375,7 +412,6 @@ MdeModulePkg/Universal/SerialDxe/SerialDxe.inf MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf - MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf ArmPkg/Drivers/ArmGic/ArmGicDxe.inf ArmPkg/Drivers/TimerDxe/TimerDxe.inf @@ -478,3 +514,19 @@ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000 } + + # + # SecureBoot + # +!if $(SECURE_BOOT_ENABLE) == TRUE + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf + } +!else + MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +!endif diff --git a/Platform/Hisilicon/HiKey/HiKey.fdf b/Platform/Hisilicon/HiKey/HiKey.fdf index d277bd6ce..04f98c637 100644 --- a/Platform/Hisilicon/HiKey/HiKey.fdf +++ b/Platform/Hisilicon/HiKey/HiKey.fdf @@ -26,12 +26,12 @@ [FD.BL33_AP_UEFI] BaseAddress = 0x35000000|gArmTokenSpaceGuid.PcdFdBaseAddress # The base address of the Firmware in NOR Flash. -Size = 0x000F0000|gArmTokenSpaceGuid.PcdFdSize # The size in bytes of the FLASH Device +Size = 0x00200000|gArmTokenSpaceGuid.PcdFdSize # The size in bytes of the FLASH Device ErasePolarity = 1 # This one is tricky, it must be: BlockSize * NumBlocks = Size BlockSize = 0x00001000 -NumBlocks = 0xF0 +NumBlocks = 0x200 ################################################################################ # @@ -49,10 +49,11 @@ NumBlocks = 0xF0 # ################################################################################ -0x00000000|0x000F0000 +0x00000000|0x00140000 gArmTokenSpaceGuid.PcdFvBaseAddress|gArmTokenSpaceGuid.PcdFvSize FV = FVMAIN_COMPACT +!include VarStore.fdf.inc ################################################################################ # @@ -172,7 +173,13 @@ READ_LOCK_STATUS = TRUE INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + INF Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.inf +!else INF MdeModulePkg/Universal/Variable/EmuRuntimeDxe/EmuVariableRuntimeDxe.inf +!endif INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf diff --git a/Platform/Hisilicon/HiKey/VarStore.fdf.inc b/Platform/Hisilicon/HiKey/VarStore.fdf.inc new file mode 100644 index 000000000..492b06abc --- /dev/null +++ b/Platform/Hisilicon/HiKey/VarStore.fdf.inc @@ -0,0 +1,72 @@ +## @file +# FDF include file with Layout Regions that define an empty variable store. +# +# Copyright (C) 2014, Red Hat, Inc. +# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the BSD License which accompanies this +# distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR +# IMPLIED. +# +## + +0x00140000|0x00040000 +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize +#NV_VARIABLE_STORE +DATA = { + ## This is the EFI_FIRMWARE_VOLUME_HEADER + # ZeroVector [] + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + # FileSystemGuid: gEfiSystemNvDataFvGuid = + # { 0xFFF12B8D, 0x7696, 0x4C8B, + # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }} + 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C, + 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50, + # FvLength: 0xC0000 + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, + # Signature "_FVH" # Attributes + 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00, + # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision + 0x48, 0x00, 0x28, 0x09, 0x00, 0x00, 0x00, 0x02, + # Blockmap[0]: 0x3 Blocks * 0x40000 Bytes / Block + 0x3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, + # Blockmap[1]: End + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ## This is the VARIABLE_STORE_HEADER + # It is compatible with SECURE_BOOT_ENABLE == FALSE as well. + # Signature: gEfiAuthenticatedVariableGuid = + # { 0xaaf32c78, 0x947b, 0x439a, + # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }} + 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43, + 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92, + # Size: 0x40000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) - + # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x3ffb8 + # This can speed up the Variable Dispatch a bit. + 0xB8, 0xFF, 0x03, 0x00, + # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32 + 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +0x00180000|0x00040000 +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize +#NV_FTW_WORKING +DATA = { + # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid = + # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }} + 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49, + 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95, + # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved + 0x5b, 0xe7, 0xc6, 0x86, 0xFE, 0xFF, 0xFF, 0xFF, + # WriteQueueSize: UINT64 + 0xE0, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 +} + +0x001c0000|0x00040000 +gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize +#NV_FTW_SPARE diff --git a/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.c b/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.c new file mode 100644 index 000000000..fb4c08252 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.c @@ -0,0 +1,444 @@ +/** @file + This file implement the Variable Protocol for the block device. + + Copyright (c) 2015, Linaro Limited. All rights reserved. + Copyright (c) 2015, Hisilicon Limited. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "BlockVariableDxe.h" + + +STATIC EFI_PHYSICAL_ADDRESS mMapNvStorageVariableBase; + +EFI_STATUS +EFIAPI +FvbGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FVB_ATTRIBUTES_2 FvbAttributes; + FvbAttributes = (EFI_FVB_ATTRIBUTES_2) ( + + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY // After erasure all bits take this value (i.e. '1') + + ); + FvbAttributes |= EFI_FVB2_WRITE_STATUS | // Writes are currently enabled + EFI_FVB2_WRITE_ENABLED_CAP; // Writes may be enabled + + *Attributes = FvbAttributes; + + DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes)); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbSetAttributes( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n",*Attributes)); + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +FvbGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + *Address = mMapNvStorageVariableBase; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +{ + BLOCK_VARIABLE_INSTANCE *Instance; + + Instance = CR (This, BLOCK_VARIABLE_INSTANCE, FvbProtocol, BLOCK_VARIABLE_SIGNATURE); + *BlockSize = (UINTN) Instance->Media.BlockSize; + *NumberOfBlocks = PcdGet32 (PcdNvStorageVariableBlockCount); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN OUT UINT8 *Buffer + ) +{ + BLOCK_VARIABLE_INSTANCE *Instance; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status; + UINTN Bytes; + VOID *DataPtr; + + Instance = CR (This, BLOCK_VARIABLE_INSTANCE, FvbProtocol, BLOCK_VARIABLE_SIGNATURE); + BlockIo = Instance->BlockIoProtocol; + Bytes = (Offset + *NumBytes + Instance->Media.BlockSize - 1) / Instance->Media.BlockSize * Instance->Media.BlockSize; + DataPtr = AllocateZeroPool (Bytes); + if (DataPtr == NULL) { + DEBUG ((EFI_D_ERROR, "FvbWrite: failed to allocate buffer.\n")); + return EFI_BUFFER_TOO_SMALL; + } + WriteBackDataCacheRange (DataPtr, Bytes); + InvalidateDataCacheRange (Buffer, *NumBytes); + Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, + Bytes, DataPtr); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FvbRead StartLba:%x, Lba:%x, Offset:%x, Status:%x\n", + Instance->StartLba, Lba, Offset, Status)); + goto exit; + } + CopyMem (Buffer, DataPtr + Offset, *NumBytes); + WriteBackDataCacheRange (Buffer, *NumBytes); +exit: + FreePool (DataPtr); + return Status; +} + +EFI_STATUS +EFIAPI +FvbWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + BLOCK_VARIABLE_INSTANCE *Instance; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status; + UINTN Bytes; + VOID *DataPtr; + + Instance = CR (This, BLOCK_VARIABLE_INSTANCE, FvbProtocol, BLOCK_VARIABLE_SIGNATURE); + BlockIo = Instance->BlockIoProtocol; + Bytes = (Offset + *NumBytes + Instance->Media.BlockSize - 1) / Instance->Media.BlockSize * Instance->Media.BlockSize; + DataPtr = AllocateZeroPool (Bytes); + if (DataPtr == NULL) { + DEBUG ((EFI_D_ERROR, "FvbWrite: failed to allocate buffer.\n")); + return EFI_BUFFER_TOO_SMALL; + } + WriteBackDataCacheRange (DataPtr, Bytes); + Status = BlockIo->ReadBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, + Bytes, DataPtr); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FvbWrite: failed on reading blocks.\n")); + goto exit; + } + CopyMem (DataPtr + Offset, Buffer, *NumBytes); + WriteBackDataCacheRange (DataPtr, Bytes); + Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, + Bytes, DataPtr); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FvbWrite StartLba:%x, Lba:%x, Offset:%x, Status:%x\n", + Instance->StartLba, Lba, Offset, Status)); + } + // Sometimes the variable isn't flushed into block device if it's the last flush operation. + // So flush it again. + Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, Instance->StartLba + Lba, + Bytes, DataPtr); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FvbWrite StartLba:%x, Lba:%x, Offset:%x, Status:%x\n", + Instance->StartLba, Lba, Offset, Status)); + } +exit: + FreePool (DataPtr); + return Status; +} + +EFI_STATUS +EFIAPI +FvbEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, + ... + ) +{ + return EFI_SUCCESS; +} + +STATIC BLOCK_VARIABLE_INSTANCE mBlockVariableInstance = { + .Signature = BLOCK_VARIABLE_SIGNATURE, + .Media = { + .MediaId = 0, + .RemovableMedia = FALSE, + .MediaPresent = TRUE, + .LogicalPartition = TRUE, + .ReadOnly = FALSE, + .WriteCaching = FALSE, + .BlockSize = 0, + .IoAlign = 4, + .LastBlock = 0, + .LowestAlignedLba = 0, + .LogicalBlocksPerPhysicalBlock = 0, + }, + .FvbProtocol = { + .GetAttributes = FvbGetAttributes, + .SetAttributes = FvbSetAttributes, + .GetPhysicalAddress = FvbGetPhysicalAddress, + .GetBlockSize = FvbGetBlockSize, + .Read = FvbRead, + .Write = FvbWrite, + .EraseBlocks = FvbEraseBlocks, + } +}; + +EFI_STATUS +ValidateFvHeader ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +{ + UINT16 Checksum, TempChecksum; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINTN VariableStoreLength; + UINTN FvLength; + + FvLength = (UINTN) (PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize)); + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ( (FwVolHeader->Revision != EFI_FVH_REVISION) + || (FwVolHeader->Signature != EFI_FVH_SIGNATURE) + || (FwVolHeader->FvLength != FvLength) + ) + { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: No Firmware Volume header present\n")); + return EFI_NOT_FOUND; + } + + // Check the Firmware Volume Guid + if( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n")); + return EFI_NOT_FOUND; + } + + // Verify the header checksum + TempChecksum = FwVolHeader->Checksum; + FwVolHeader->Checksum = 0; + Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength); + if (Checksum != TempChecksum) { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n",Checksum)); + return EFI_NOT_FOUND; + } + FwVolHeader->Checksum = Checksum; + + VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + FwVolHeader->HeaderLength); + + // Check the Variable Store Guid + if( CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) == FALSE ) { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Guid non-compatible\n")); + return EFI_NOT_FOUND; + } + + VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength; + if (VariableStoreHeader->Size != VariableStoreLength) { + DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Length does not match\n")); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +InitNonVolatileVariableStore ( + IN BLOCK_VARIABLE_INSTANCE *Instance, + IN VOID *Headers, + IN UINTN HeadersLength + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; + EFI_STATUS Status; + VARIABLE_STORE_HEADER *VariableStoreHeader; + + // Check if the size of the area is at least one block size + ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && (PcdGet32(PcdFlashNvStorageVariableSize) / Instance->BlockIoProtocol->Media->BlockSize > 0)); + ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->BlockIoProtocol->Media->BlockSize > 0)); + ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && (PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->BlockIoProtocol->Media->BlockSize > 0)); + + // + // EFI_FIRMWARE_VOLUME_HEADER + // + FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers; + CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid); + FirmwareVolumeHeader->FvLength = + PcdGet32(PcdFlashNvStorageVariableSize) + + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + + PcdGet32(PcdFlashNvStorageFtwSpareSize); + FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE; + FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) ( + EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled + EFI_FVB2_READ_STATUS | // Reads are currently enabled + EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY + EFI_FVB2_MEMORY_MAPPED | // It is memory mapped + EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1') + EFI_FVB2_WRITE_STATUS | // Writes are currently enabled + EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled + ); + FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY); + FirmwareVolumeHeader->Revision = EFI_FVH_REVISION; + FirmwareVolumeHeader->BlockMap[0].NumBlocks = PcdGet32 (PcdNvStorageVariableBlockCount); + FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockIoProtocol->Media->BlockSize; + // BlockMap Terminator + FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0; + FirmwareVolumeHeader->BlockMap[1].Length = 0; + FirmwareVolumeHeader->Checksum = 0; + FirmwareVolumeHeader->Checksum = CalculateSum16 ((UINT16*)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength); + + // + // VARIABLE_STORE_HEADER + // + VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FirmwareVolumeHeader + FirmwareVolumeHeader->HeaderLength); + CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid); + VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength; + VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED; + VariableStoreHeader->State = VARIABLE_STORE_HEALTHY; + + Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers); + return Status; +} + +EFI_STATUS +BlockVariableDxeInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + BLOCK_VARIABLE_INSTANCE *Instance = &mBlockVariableInstance; + UINT32 Count; + EFI_LBA Lba; + UINTN NvStorageSize; + EFI_DEVICE_PATH_PROTOCOL *NvBlockDevicePath; + UINT8 *NvStorageData; + VOID *Headers; + UINTN HeadersLength; + + Instance->Signature = BLOCK_VARIABLE_SIGNATURE; + + HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER); + Headers = AllocateZeroPool(HeadersLength); + if (Headers == NULL) { + DEBUG ((EFI_D_ERROR, "%a: failed to allocate memory of Headers\n", __func__)); + return EFI_OUT_OF_RESOURCES; + } + + Lba = (EFI_LBA) PcdGet32 (PcdNvStorageVariableBlockLba); + Count = PcdGet32 (PcdNvStorageVariableBlockCount); + Instance->Media.BlockSize = PcdGet32 (PcdNvStorageVariableBlockSize); + NvStorageSize = Count * Instance->Media.BlockSize; + Instance->StartLba = Lba; + HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER); + if (NvStorageSize < HeadersLength) { + return EFI_BAD_BUFFER_SIZE; + } + NvStorageData = (UINT8 *) (UINTN) PcdGet32(PcdFlashNvStorageVariableBase); + mMapNvStorageVariableBase = PcdGet32(PcdFlashNvStorageVariableBase); + NvBlockDevicePath = &Instance->DevicePath; + NvBlockDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdNvStorageVariableBlockDevicePath)); + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &NvBlockDevicePath, + &Instance->Handle); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Warning: Couldn't locate NVM device (status: %r)\n", Status)); + return EFI_INVALID_PARAMETER; + } + Status = gBS->OpenProtocol ( + Instance->Handle, + &gEfiBlockIoProtocolGuid, + (VOID **) &Instance->BlockIoProtocol, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Warning: Couldn't open NVM device (status: %r)\n", Status)); + return EFI_DEVICE_ERROR; + } + WriteBackDataCacheRange (Instance, sizeof(BLOCK_VARIABLE_INSTANCE)); + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol, + NULL + ); + if (EFI_ERROR (Status)) { + goto exit; + } + + Status = FvbRead (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ValidateFvHeader (Headers); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a, Found invalid Fv Header\n", __func__)); + + // Erase all the block device that is reserved for variable storage + Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, Count, EFI_LBA_LIST_TERMINATOR); + if (EFI_ERROR (Status)) { + goto exit; + } + + Status = InitNonVolatileVariableStore (Instance, Headers, HeadersLength); + if (EFI_ERROR (Status)) { + goto exit; + } + } + + if (NvStorageSize > ((EFI_FIRMWARE_VOLUME_HEADER*)Headers)->FvLength) { + NvStorageSize = ((EFI_FIRMWARE_VOLUME_HEADER*)Headers)->FvLength; + NvStorageSize = ((NvStorageSize + Instance->Media.BlockSize - 1) / Instance->Media.BlockSize) * Instance->Media.BlockSize; + } + Status = FvbRead (&Instance->FvbProtocol, 0, 0, &NvStorageSize, NvStorageData); + +exit: + return Status; +} diff --git a/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.h b/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.h new file mode 100644 index 000000000..a8f95e8ca --- /dev/null +++ b/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.h @@ -0,0 +1,51 @@ +/** @file NorFlashDxe.h + + Copyright (c) 2015, Linaro Ltd. All rights reserved. + Copyright (c) 2015, Hisilicon Ltd. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __VARIABLE_DXE_H__ +#define __VARIABLE_DXE_H__ + +#include +#include +#include + +#define BLOCK_VARIABLE_SIGNATURE SIGNATURE_32('b', 'l', 'k', '0') + +typedef struct _BLOCK_VARIABLE_INSTANCE BLOCK_VARIABLE_INSTANCE; + +typedef struct { + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL End; +} BLOCK_DEVICE_PATH; + +struct _BLOCK_VARIABLE_INSTANCE { + UINT32 Signature; + EFI_HANDLE Handle; + + BOOLEAN Initialized; + + UINTN Size; + EFI_LBA StartLba; + + EFI_BLOCK_IO_MEDIA Media; + EFI_BLOCK_IO_PROTOCOL *BlockIoProtocol; + EFI_DISK_IO_PROTOCOL DiskIoProtocol; + EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; + EFI_DEVICE_PATH_PROTOCOL DevicePath; + + VOID* ShadowBuffer; +}; + + +#endif /* __VARIABLE_DXE_H__ */ diff --git a/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.inf b/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.inf new file mode 100644 index 000000000..9d25f3777 --- /dev/null +++ b/Silicon/Hisilicon/Drivers/BlockVariableDxe/BlockVariableDxe.inf @@ -0,0 +1,65 @@ +#/** @file +# INF file for the Variable Protocol implementation for the block device. +# +# Copyright (c) 2015, Linaro Limited. All rights reserved. +# Copyright (c) 2015, Hisilicon Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BlockVariableDxe + FILE_GUID = 522fc4a8-46d8-403e-a415-e2dbb1e0ebc0 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = BlockVariableDxeInitialize + +[Sources.common] + BlockVariableDxe.c + +[Packages] + Platform/Hisilicon/HiKey/HiKey.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + ArmLib + BaseLib + BaseMemoryLib + CacheMaintenanceLib + IoLib + UefiDriverEntryPoint + UefiLib + DmaLib + +[Guids] + gEfiSystemNvDataFvGuid + gEfiVariableGuid + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiBlockIoProtocolGuid ## CONSUMES + gEfiFirmwareVolumeBlockProtocolGuid + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES + gHwTokenSpaceGuid.PcdNvStorageVariableBlockCount ## CONSUMES + gHwTokenSpaceGuid.PcdNvStorageVariableBlockSize ## CONSUMES + gHwTokenSpaceGuid.PcdNvStorageVariableBlockLba ## CONSUMES + gHwTokenSpaceGuid.PcdNvStorageVariableBlockDevicePath ## CONSUMES + +[Depex] + TRUE -- 2.15.0