From nobody Wed May 1 18:26:12 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1486955414641353.56158531151823; Sun, 12 Feb 2017 19:10:14 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id E95DD820DA; Sun, 12 Feb 2017 19:10:12 -0800 (PST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id AB5C2820D8 for ; Sun, 12 Feb 2017 19:10:11 -0800 (PST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Feb 2017 19:10:11 -0800 Received: from zwei4-mobl.ccr.corp.intel.com ([10.239.198.23]) by orsmga001.jf.intel.com with ESMTP; 12 Feb 2017 19:10:10 -0800 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.35,155,1484035200"; d="scan'208";a="1094006604" From: zwei4 To: edk2-devel@lists.01.org Date: Mon, 13 Feb 2017 11:10:05 +0800 Message-Id: <20170213031005.27728-1-david.wei@intel.com> X-Mailer: git-send-email 2.11.0.windows.1 Subject: [edk2] [Patch][edk2-platforms/devel-MinnowBoard3] Add FirmwareUpdate application X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Add FirmwareUpdate application for Minnnowboard 3, which is for updating 8M= B SPI NOR flash. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: zwei4 --- .../Application/FirmwareUpdate/FirmwareUpdate.c | 927 +++++++++++++++++= ++++ .../Application/FirmwareUpdate/FirmwareUpdate.h | 190 +++++ .../Application/FirmwareUpdate/FirmwareUpdate.inf | 83 ++ .../FirmwareUpdate/FirmwareUpdateStrings.uni | Bin 0 -> 7480 bytes 4 files changed, 1200 insertions(+) create mode 100644 Platform/BroxtonPlatformPkg/Common/Application/Firmware= Update/FirmwareUpdate.c create mode 100644 Platform/BroxtonPlatformPkg/Common/Application/Firmware= Update/FirmwareUpdate.h create mode 100644 Platform/BroxtonPlatformPkg/Common/Application/Firmware= Update/FirmwareUpdate.inf create mode 100644 Platform/BroxtonPlatformPkg/Common/Application/Firmware= Update/FirmwareUpdateStrings.uni diff --git a/Platform/BroxtonPlatformPkg/Common/Application/FirmwareUpdate/= FirmwareUpdate.c b/Platform/BroxtonPlatformPkg/Common/Application/FirmwareU= pdate/FirmwareUpdate.c new file mode 100644 index 000000000..b374b983d --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Application/FirmwareUpdate/Firmwar= eUpdate.c @@ -0,0 +1,927 @@ +/** @file + +Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
+ = =20 + This program and the accompanying materials are licensed and made availa= ble under + the terms and conditions of the BSD License that accompanies this distri= bution. =20 + The full text of the license may be found at = =20 + http://opensource.org/licenses/bsd-license.php. = =20 + = =20 + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, = =20 + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. =20 + = =20 + +**/ + +#include "FirmwareUpdate.h" + +EFI_HII_HANDLE HiiHandle; + + +/* + +MinnowBoard 3 Flash Layout + +Start (hex) End (hex) Length (hex) Area Name +----------- --------- ------------ --------- + +00000000 007FFFFF 00800000 Full Flash Image +00000014 00000017 00000004 FLMAP0 - Flash Map 0 Regis= ter +00000018 0000001B 00000004 FLMAP1 - Flash Map 1 Regis= ter +0000001C 0000001F 00000004 FLMAP2 - Flash Map 2 Regis= ter +00000030 0000003B 0000000C FCBA - Flash Component Reg= isters +00000040 00000043 00000004 FLREG0 - Flash Region 0 (F= lash Descriptor) Register +00000044 00000047 00000004 FLREG1 - Flash Region 1 (I= FWI) Register +00000048 0000004B 00000004 FLREG2 - Flash Region 2 (I= ntel(R) TXE) Register +00000050 00000053 00000004 FLREG4 - Flash Region 4 (P= latform Data) Register +00000054 00000057 00000004 FLREG5 - Flash Region 5 (D= evice Expansion) Register +00000060 00000063 00000004 FLREG8 - Flash Region 8 (E= mbedded Controller) Register +00000080 00000083 00000004 FLMSTR1 - Flash Master 1 (= Host CPU/BIOS) +00000084 00000087 00000004 FLMSTR2 - Flash Master 2 (= Intel(R) TXE) +00000100 000002FF 00000200 FPSBA - SoC Straps (Includ= ing Padding) +000003EC 0000046B 00000080 FPSBA - SoC Straps (Includ= ing Padding) +00000DF0 00000EFF 00000110 VSCC Table +00000DF0 00000DF7 00000008 VsccEntry0 +00001000 00241FFF 00241000 Boot Partition 1 +00001000 000F9FFF 000F9000 Primary Boot Partition +00001200 0000120F 00000010 IFP Overrides Partition +00001210 00001317 00000108 Unified Emulation Part= ition (UEP) +00002000 00005FFF 00004000 OEM SMIP Partition +00006000 0000FFFF 0000A000 CSE RBE Partition +00010000 0001FFFF 00010000 PMCP +00020000 0007BFFF 0005C000 CSE BUP Partition +0007C000 0007FFFF 00004000 uCode Partition +00080000 000F7FFF 00078000 IBB Partition +000F8000 000F9FFF 00002000 Debug Token Partition +000FA000 00241FFF 00148000 Secondary Boot Partition +000FB000 0013AFFF 00040000 ISHC Partition +0013B000 0023FFFF 00105000 CSE Main Partition +00240000 00241FFF 00002000 IUnit Partition +00242000 0065BFFF 0041A000 Secondary Boot Partition +00242000 0065BFFF 0041A000 Boot Partition 2 +00381000 0065BFFF 002DB000 OBB Partition +0065C000 006FF000 000A3001 TXE Data Region +*/ + +FV_REGION_INFO mRegionInfo[] =3D { + {0xFF800000, 0x00001000, TRUE}, + {0xFF801000, 0x0037F000, TRUE}, + {0xFFB80000, 0x0037F000, TRUE}, + {0xFFEFF000, 0x00100000, TRUE}, +}; + +UINTN mRegionInfoCount =3D sizeof (mRegionInfo) / sizeof (mRegionInfo[0]); + +FV_INPUT_DATA mInputData =3D {0}; + +SC_SPI_PROTOCOL *mSpiProtocol; + +EFI_STATUS +GetRegionIndex ( + IN EFI_PHYSICAL_ADDRESS Address, + OUT UINTN *RegionIndex + ) +{ + UINTN Index; + + for (Index =3D 0; Index < mRegionInfoCount; Index++) { + if (Address >=3D mRegionInfo[Index].Base && + Address < (mRegionInfo[Index].Base + mRegionInfo[Index].Size) + ) { + break; + } + } + + *RegionIndex =3D Index; + if (Index >=3D mRegionInfoCount) { + return EFI_NOT_FOUND; + } + return EFI_SUCCESS; +} + +BOOLEAN +UpdateBlock ( + IN EFI_PHYSICAL_ADDRESS Address + ) +{ + EFI_STATUS Status; + UINTN Index; + + if (mInputData.FullFlashUpdate) { + // + // Apollo Lake Workaround: 0xFFFFF000 - 0xFFFFFFFF region (Top 4KB bwl= ow 4G) could not be access by SPI protocol.=20 + // + if (Address >=3D 0xFFFFF000) { + return FALSE; + } + =20 + return TRUE; + } + + Status =3D GetRegionIndex (Address, &Index); + if ((!EFI_ERROR(Status)) && mRegionInfo[Index].Update) { + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +MarkRegionState ( + IN EFI_PHYSICAL_ADDRESS Address, + IN BOOLEAN Update + ) +{ + EFI_STATUS Status; + UINTN Index; + + Status =3D GetRegionIndex (Address, &Index); + if (!EFI_ERROR(Status)) { + mRegionInfo[Index].Update =3D Update; + } + + return Status; +} + +UINTN +InternalPrintToken ( + IN CONST CHAR16 *Format, + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Console, + IN VA_LIST Marker + ) +{ + EFI_STATUS Status; + UINTN Return; + CHAR16 *Buffer; + UINTN BufferSize; + + ASSERT (Format !=3D NULL); + ASSERT (((UINTN) Format & BIT0) =3D=3D 0); + ASSERT (Console !=3D NULL); + + BufferSize =3D (PcdGet32 (PcdUefiLibMaxPrintBufferSize) + 1) * sizeof (C= HAR16); + + Buffer =3D (CHAR16 *) AllocatePool(BufferSize); + ASSERT (Buffer !=3D NULL); + + Return =3D UnicodeVSPrint (Buffer, BufferSize, Format, Marker); + + if (Console !=3D NULL && Return > 0) { + // + // To be extra safe make sure Console has been initialized. + // + Status =3D Console->OutputString (Console, Buffer); + if (EFI_ERROR (Status)) { + Return =3D 0; + } + } + + FreePool (Buffer); + + return Return; +} + +UINTN +EFIAPI +PrintToken ( + IN UINT16 Token, + IN EFI_HII_HANDLE Handle, + ... + ) +{ + VA_LIST Marker; + UINTN Return; + CHAR16 *Format; + + VA_START (Marker, Handle); + + Format =3D HiiGetString (Handle, Token, NULL); + ASSERT (Format !=3D NULL); + + Return =3D InternalPrintToken (Format, gST->ConOut, Marker); + + FreePool (Format); + + VA_END (Marker); + + return Return; +} + +EFI_STATUS +ParseCommandLine ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_STATUS Status; + UINTN Index; + + // + // Check to make sure that the command line has enough arguments for min= imal + // operation. The minimum is just the file name. + // + if (Argc < 2 || Argc > 4) { + return EFI_INVALID_PARAMETER; + } + + // + // Loop through command line arguments. + // + for (Index =3D 1; Index < Argc; Index++) { + // + // Make sure the string is valid. + // + if (StrLen (Argv[Index]) =3D=3D 0) {; + PrintToken (STRING_TOKEN (STR_FWUPDATE_ZEROLENGTH_ARG), HiiHandle); + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if this is an option or the file name. + // + if ((Argv[Index])[0] =3D=3D L'-' || (Argv[Index])[0] =3D=3D L'/') { + // + // Parse the arguments. + // + if ((StrCmp (Argv[Index], L"-h") =3D=3D 0) || + (StrCmp (Argv[Index], L"--help") =3D=3D 0) || + (StrCmp (Argv[Index], L"/?") =3D=3D 0) || + (StrCmp (Argv[Index], L"/h") =3D=3D 0)) { + // + // Print Help Information. + // + return EFI_INVALID_PARAMETER; + } else if (StrCmp (Argv[Index], L"-m") =3D=3D 0) { + // + // Parse the MAC address here. + // + Status =3D ConvertMac(Argv[Index+1]); + if (EFI_ERROR(Status)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_INVAILD_MAC), HiiHandle); + return Status; + } + + // + // Save the MAC address to mInputData.MacValue. + // + mInputData.UpdateMac=3D TRUE; + Index++; + } else { + // + // Invalid option was provided. + // + return EFI_INVALID_PARAMETER; + } + } + if ((Index =3D=3D Argc - 1) && (StrCmp (Argv[Index - 1], L"-m") !=3D 0= )) { + // + // The only parameter that is not an option is the firmware image. = Check + // to make sure that the file exists. + // + Status =3D ShellIsFile (Argv[Index]); + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_FILE_NOT_FOUND_ERROR), HiiH= andle, Argv[Index]); + return EFI_INVALID_PARAMETER; + } + if (StrLen (Argv[Index]) > INPUT_STRING_LEN) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_PATH_ERROR), HiiHandle, Arg= v[Index]); + return EFI_INVALID_PARAMETER; + } + StrCpy (mInputData.FileName, Argv[Index]); + mInputData.UpdateFromFile =3D TRUE; + } + } + + return EFI_SUCCESS; +} + +INTN +EFIAPI +ShellAppMain ( + IN UINTN Argc, + IN CHAR16 **Argv + ) +{ + EFI_STATUS Status; + UINTN Index; + UINT32 FileSize; + UINT32 BufferSize; + UINT8 *FileBuffer; + UINT8 *Buffer; + EFI_PHYSICAL_ADDRESS Address; + UINTN CountOfBlocks; + EFI_TPL OldTpl; + BOOLEAN ResetRequired; + BOOLEAN FlashError; + + Index =3D 0; + FileSize =3D 0; + BufferSize =3D 0; + FileBuffer =3D NULL; + Buffer =3D NULL; + Address =3D 0; + CountOfBlocks =3D 0; + ResetRequired =3D FALSE; + FlashError =3D FALSE; + + Status =3D EFI_SUCCESS; + + mInputData.FullFlashUpdate =3D TRUE; + + // + // Publish our HII data. + // + HiiHandle =3D HiiAddPackages ( + &gEfiCallerIdGuid, + NULL, + FirmwareUpdateStrings, + NULL + ); + if (HiiHandle =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Locate the SPI protocol. + // + Status =3D gBS->LocateProtocol ( + &gScSpiProtocolGuid, + NULL, + (VOID **)&mSpiProtocol + ); + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_SPI_NOT_FOUND), HiiHandle); + return EFI_DEVICE_ERROR; + } + + // + // Parse the command line. + // + Status =3D ParseCommandLine (Argc, Argv); + if (EFI_ERROR (Status)) { + PrintHelpInfo (); + Status =3D EFI_SUCCESS; + goto Done; + } + + // + // Display sign-on information. + // + PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle); + + // + // Test to see if the firmware needs to be updated. + // + if (mInputData.UpdateFromFile) { + // + // Get the file to use in the update. + // + PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE), HiiHandle, mInputDa= ta.FileName); + Status =3D ReadFileData (mInputData.FileName, &FileBuffer, &FileSize); + if (EFI_ERROR (Status)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_READ_FILE_ERROR), HiiHandle, = mInputData.FileName); + goto Done; + } + + // + // Check that the file and flash sizes match. + // + if (FileSize !=3D PcdGet32 (PcdFlashAreaSize)) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_SIZE), HiiHandle); + Status =3D EFI_UNSUPPORTED; + goto Done; + } + + // + // Display flash update information. + // + PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATING_FIRMWARE), HiiHandle); + + // + // Update it. + // + Buffer =3D FileBuffer; + BufferSize =3D FileSize; + Address =3D PcdGet32 (PcdFlashAreaBaseAddress); + CountOfBlocks =3D (UINTN) (BufferSize / BLOCK_SIZE); + + // + // Raise TPL to TPL_NOTIFY to block any event handler, + // while still allowing RaiseTPL(TPL_NOTIFY) within + // output driver during Print(). + // + OldTpl =3D gBS->RaiseTPL (TPL_NOTIFY); + for (Index =3D 0; Index < CountOfBlocks; Index++) { + // + // Handle block based on address and contents. + // + if (!UpdateBlock (Address)) { + DEBUG((EFI_D_INFO, "Skipping block at 0x%lx\n", Address)); + } else if (!EFI_ERROR (InternalCompareBlock (Address, Buffer))) { + DEBUG((EFI_D_INFO, "Skipping block at 0x%lx (already programmed)\n= ", Address)); + } else { + // + // Display a dot for each block being updated. + // + Print (L"."); + + // + // Flag that the flash image will be changed and the system must b= e rebooted + // to use the change. + // + ResetRequired =3D TRUE; + + // + // Make updating process uninterruptable, + // so that the flash memory area is not accessed by other entities + // which may interfere with the updating process. + // + Status =3D InternalEraseBlock (Address); + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + FlashError =3D TRUE; + goto Done; + } + Status =3D InternalWriteBlock ( + Address, + Buffer, + (BufferSize > BLOCK_SIZE ? BLOCK_SIZE : BufferSize) + ); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (OldTpl); + FlashError =3D TRUE; + goto Done; + } + } + + // + // Move to next block to update. + // + Address +=3D BLOCK_SIZE; + Buffer +=3D BLOCK_SIZE; + if (BufferSize > BLOCK_SIZE) { + BufferSize -=3D BLOCK_SIZE; + } else { + BufferSize =3D 0; + } + } + gBS->RestoreTPL (OldTpl); + + // + // Print result of update. + // + if (!FlashError) { + if (ResetRequired) { + Print (L"\n"); + PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_SUCCESS), HiiHandle); + } else { + PrintToken (STRING_TOKEN (STR_FWUPDATE_NO_RESET), HiiHandle); + } + } else { + goto Done; + } + } + + // + // All flash updates are done so see if the system needs to be reset. + // + if (ResetRequired && !FlashError) { + // + // Update successful. + // + for (Index =3D 5; Index > 0; Index--) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_SHUTDOWN), HiiHandle, Index); + gBS->Stall (1000000); + } + + gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL); + PrintToken (STRING_TOKEN (STR_FWUPDATE_MANUAL_RESET), HiiHandle); + CpuDeadLoop (); + } + +Done: + // + // Print flash update failure message if error is detected. + // + if (FlashError) { + PrintToken (STRING_TOKEN (STR_FWUPDATE_UPDATE_FAILED), HiiHandle, Inde= x); + } + + // + // Do cleanup. + // + if (HiiHandle !=3D NULL) { + HiiRemovePackages (HiiHandle); + } + if (FileBuffer) { + gBS->FreePool (FileBuffer); + } + + return Status; +} + +/*++ + =20 + Erase the whole block. + + @param[in] BaseAddress Base address of the block to be erased. + + @retval EFI_SUCCESS The command completed successfully. + @retval Other Device error or wirte-locked, operation failed. + +--*/ +STATIC +EFI_STATUS +InternalEraseBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +{ + EFI_STATUS Status; + UINTN NumBytes; + + NumBytes =3D BLOCK_SIZE; + + Status =3D SpiFlashBlockErase ((UINTN) BaseAddress, &NumBytes); + + return Status; +} + +STATIC +EFI_STATUS +InternalCompareBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + VOID *CompareBuffer; + UINT32 NumBytes; + INTN CompareResult; + + NumBytes =3D BLOCK_SIZE; + CompareBuffer =3D AllocatePool (NumBytes); + if (CompareBuffer =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status =3D SpiFlashRead ((UINTN) BaseAddress, &NumBytes, CompareBuffer); + if (EFI_ERROR (Status)) { + goto Done; + } + CompareResult =3D CompareMem (CompareBuffer, Buffer, BLOCK_SIZE); + if (CompareResult !=3D 0) { + Status =3D EFI_VOLUME_CORRUPTED; + } + +Done: + if (CompareBuffer !=3D NULL) { + FreePool (CompareBuffer); + } + + return Status; +} + +/*++ + Write a block of data. + + @param[in] BaseAddress Base address of the block. + @param[in] Buffer Data buffer. + @param[in] BufferSize Size of the buffer. + + @retval EFI_SUCCESS The command completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter, can not proceed. + @retval Other Device error or wirte-locked, operation= failed. + +--*/ +STATIC +EFI_STATUS +InternalWriteBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer, + IN UINT32 BufferSize + ) +{ + EFI_STATUS Status; + + Status =3D SpiFlashWrite ((UINTN) BaseAddress, &BufferSize, Buffer); + + ASSERT_EFI_ERROR(Status); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "\nFlash write error.")); + return Status; + } + + //Workaround: WriteBackInvalidateDataCacheRange ((VOID *) (UINTN) BaseAd= dress, BLOCK_SIZE); + + Status =3D InternalCompareBlock (BaseAddress, Buffer); + if (EFI_ERROR (Status)) { + DEBUG((EFI_D_ERROR, "\nError when writing to BaseAddress %lx with diff= erent at offset %x.", BaseAddress, Status)); + } else { + DEBUG((EFI_D_INFO, "\nVerified data written to Block at %lx is correct= .", BaseAddress)); + } + + return Status; + +} + +STATIC +EFI_STATUS +ReadFileData ( + IN CHAR16 *FileName, + OUT UINT8 **Buffer, + OUT UINT32 *BufferSize + ) +{ + EFI_STATUS Status; + SHELL_FILE_HANDLE FileHandle; + UINT64 Size; + VOID *NewBuffer; + UINTN ReadSize; + + FileHandle =3D NULL; + NewBuffer =3D NULL; + Size =3D 0; + + Status =3D ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_REA= D, 0); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status =3D FileHandleIsDirectory (FileHandle); + if (!EFI_ERROR (Status)) { + Status =3D EFI_NOT_FOUND; + goto Done; + } + + Status =3D FileHandleGetSize (FileHandle, &Size); + if (EFI_ERROR (Status)) { + goto Done; + } + + NewBuffer =3D AllocatePool ((UINTN) Size); + + ReadSize =3D (UINTN) Size; + Status =3D FileHandleRead (FileHandle, &ReadSize, NewBuffer); + if (EFI_ERROR (Status)) { + goto Done; + } else if (ReadSize !=3D (UINTN) Size) { + Status =3D EFI_INVALID_PARAMETER; + goto Done; + } + +Done: + if (FileHandle !=3D NULL) { + ShellCloseFile (&FileHandle); + } + + if (EFI_ERROR (Status)) { + if (NewBuffer !=3D NULL) { + FreePool (NewBuffer); + } + } else { + *Buffer =3D NewBuffer; + *BufferSize =3D (UINT32) Size; + } + + return Status; +} + +STATIC +VOID +PrintHelpInfo ( + VOID + ) +{ + PrintToken (STRING_TOKEN (STR_FWUPDATE_FIRMWARE_VOL_UPDATE), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_VERSION), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_COPYRIGHT), HiiHandle); + + Print (L"\n"); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_1), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_2), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_3), HiiHandle); + PrintToken (STRING_TOKEN (STR_FWUPDATE_USAGE_4), HiiHandle); + + Print (L"\n"); +} + +/** + Read NumBytes bytes of data from the address specified by + PAddress into Buffer. + + @param[in] Address The starting physical address of the read. + @param[in,out] NumBytes On input, the number of bytes to read. On = output, the number + of bytes actually read. + @param[out] Buffer The destination data buffer for the read. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashRead ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status =3D EFI_SUCCESS; + UINT32 SectorSize; + UINT32 Offset; + UINT8 TempBuffer[SIZE_4KB]; + UINTN Count =3D 0; + UINT32 Length; + =20 + Offset =3D (UINT32)Address - PcdGet32 (PcdFlashAreaBaseAddress); + SectorSize =3D SIZE_4KB; + Length =3D *NumBytes; + =20 + while (Count < Length) { + Status =3D mSpiProtocol ->FlashRead ( + mSpiProtocol, + FlashRegionAll, + Offset, + SIZE_4KB, + TempBuffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Read SPI ROM Failed [%08x]\n", Offset)); + break; + } + + CopyMem ((Buffer + Count), (VOID *)TempBuffer, SectorSize); + Offset +=3D SectorSize; + Count +=3D SectorSize; + } + =20 + return Status; + +} + +/** + Write NumBytes bytes of data from Buffer to the address specified by + PAddresss. + + @param[in] Address The starting physical address of the wri= te. + @param[in,out] NumBytes On input, the number of bytes to write. = On output, + the actual number of bytes written. + @param[in] Buffer The source data buffer for the write. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashWrite ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINT32 Offset; + UINT32 Length; + UINT32 RemainingBytes; + + ASSERT ((NumBytes !=3D NULL) && (Buffer !=3D NULL)); + ASSERT (Address >=3D (UINTN)PcdGet32 (PcdFlashAreaBaseAddress)); + =20 + Offset =3D (UINT32)Address - PcdGet32 (PcdFlashAreaBaseAddress); + + ASSERT ((*NumBytes + Offset) <=3D (UINTN)PcdGet32 (PcdFlashAreaSize)); + + Status =3D EFI_SUCCESS; + RemainingBytes =3D *NumBytes; + + while (RemainingBytes > 0) { + + DEBUG ((EFI_D_ERROR, "SpiFlashWrite RemainingBytes 0x%x\n", RemainingB= ytes)); + =20 + if (RemainingBytes > SIZE_4KB) { + Length =3D SIZE_4KB; + } else { + Length =3D RemainingBytes; + } + + Status =3D mSpiProtocol->FlashWrite( + mSpiProtocol, + FlashRegionAll, + Offset, + Length, + Buffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SPI Wirte failed. Status: %r.\n", Status)); + break; + } + =20 + RemainingBytes -=3D Length; + Offset +=3D Length; + Buffer +=3D Length; + } + + // + // Actual number of bytes written. + // + *NumBytes -=3D RemainingBytes; + + return Status; +} + +/** + Erase the block starting at Address. + + @param[in] Address The starting physical address of the block t= o be erased. + This library assume that caller garantee tha= t the PAddress + is at the starting address of this block. + @param[in] NumBytes On input, the number of bytes of the logical= block to be erased. + On output, the actual number of bytes erased. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashBlockErase ( + IN UINTN Address, + IN UINTN *NumBytes + ) +{ + EFI_STATUS Status; + UINT32 Offset; + UINTN RemainingBytes; + + ASSERT (NumBytes !=3D NULL); + ASSERT (Address >=3D (UINTN)PcdGet32 (PcdFlashAreaBaseAddress)); + =20 + Offset =3D (UINT32)Address - PcdGet32 (PcdFlashAreaBaseAddress); + + ASSERT ((*NumBytes % SIZE_4KB) =3D=3D 0); + ASSERT ((*NumBytes + Offset) <=3D (UINTN)PcdGet32 (PcdFlashAreaSize)); + + Status =3D EFI_SUCCESS; + RemainingBytes =3D *NumBytes; + + while (RemainingBytes > 0) { + =20 + Status =3D mSpiProtocol->FlashErase ( + mSpiProtocol, + FlashRegionAll, + Offset, + SIZE_4KB + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Erase failed. Status: %r Offset =3D 0x%x\n", S= tatus, Offset)); + break; + } + =20 + RemainingBytes -=3D SIZE_4KB; + Offset +=3D SIZE_4KB; + } + + return Status; +} + +EFI_STATUS +EFIAPI +ConvertMac ( + CHAR16 *Str + ) +{ + UINTN Index; + UINT8 Temp[MAC_ADD_STR_LEN]; + + if (Str =3D=3D NULL) + return EFI_INVALID_PARAMETER; + + if (StrLen(Str) !=3D MAC_ADD_STR_LEN) + return EFI_INVALID_PARAMETER; + + for (Index =3D 0; Index < MAC_ADD_STR_LEN; Index++) { + if (Str[Index] >=3D 0x30 && Str[Index] <=3D 0x39) { + Temp[Index] =3D (UINT8)Str[Index] - 0x30; + } else if (Str[Index] >=3D 0x41 && Str[Index] <=3D 0x46) { + Temp[Index] =3D (UINT8)Str[Index] - 0x37; + } else if (Str[Index] >=3D 0x61 && Str[Index] <=3D 0x66) { + Temp[Index] =3D (UINT8)Str[Index] - 0x57; + } else { + return EFI_INVALID_PARAMETER; + } + } + + for (Index =3D 0; Index < MAC_ADD_BYTE_COUNT; Index++) { + mInputData.MacValue[Index] =3D (Temp[2 * Index] << 4) + Temp[2 * Index= + 1]; + } + + return EFI_SUCCESS; +} + diff --git a/Platform/BroxtonPlatformPkg/Common/Application/FirmwareUpdate/= FirmwareUpdate.h b/Platform/BroxtonPlatformPkg/Common/Application/FirmwareU= pdate/FirmwareUpdate.h new file mode 100644 index 000000000..61624b58b --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Application/FirmwareUpdate/Firmwar= eUpdate.h @@ -0,0 +1,190 @@ +/** @file + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.
+ = =20 + This program and the accompanying materials are licensed and made availa= ble under + the terms and conditions of the BSD License that accompanies this distri= bution. =20 + The full text of the license may be found at = =20 + http://opensource.org/licenses/bsd-license.php. = =20 + = =20 + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, = =20 + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. =20 + = =20 + +**/ + +#ifndef _FIRMWARE_UPDATE_H_ +#define _FIRMWARE_UPDATE_H_ + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Function Prototypes. +// +STATIC +EFI_STATUS +ReadFileData ( + IN CHAR16 *FileName, + OUT UINT8 **Buffer, + OUT UINT32 *BufferSize + ); + +STATIC +EFI_STATUS +InternalEraseBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ); + +#if 0 +STATIC +EFI_STATUS +InternalReadBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT VOID *ReadBuffer + ); +#endif + +STATIC +EFI_STATUS +InternalCompareBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer + ); + +STATIC +EFI_STATUS +InternalWriteBlock ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT8 *Buffer, + IN UINT32 BufferSize + ); + +STATIC +VOID +PrintHelpInfo ( + VOID + ); + +STATIC +EFI_STATUS +EFIAPI +SpiFlashRead ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + OUT UINT8 *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +SpiFlashWrite ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + IN UINT8 *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +SpiFlashBlockErase ( + IN UINTN Address, + IN UINTN *NumBytes + ); + +STATIC +EFI_STATUS +EFIAPI +ConvertMac ( + CHAR16 *Str + ); + +EFI_STATUS +InitializeFVUPDATE ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// Flash specific definitions. +// - Should we use a PCD for this information? +// +#define BLOCK_SIZE SIZE_4KB + +// +// Flash region layout and update information. +// +typedef struct { + EFI_PHYSICAL_ADDRESS Base; + UINTN Size; + BOOLEAN Update; +} FV_REGION_INFO; + +// +// MAC Address information. +// +#define MAC_ADD_STR_LEN 12 +#define MAC_ADD_STR_SIZE (MAC_ADD_STR_LEN + 1) +#define MAC_ADD_BYTE_COUNT 6 +#define MAC_ADD_TMP_STR_LEN 2 +#define MAC_ADD_TMP_STR_SIZE (MAC_ADD_TMP_STR_LEN + 1) + +// +// Command Line Data. +// +#define INPUT_STRING_LEN 255 +#define INPUT_STRING_SIZE (INPUT_STRING_LEN + 1) +typedef struct { + BOOLEAN UpdateFromFile; + CHAR16 FileName[INPUT_STRING_SIZE]; + BOOLEAN UpdateMac; + UINT8 MacValue[MAC_ADD_BYTE_COUNT]; + BOOLEAN FullFlashUpdate; +} FV_INPUT_DATA; + +// +// Prefix Opcode Index on the host SPI controller. +// +typedef enum { + SPI_WREN, // Prefix Opcode 0: Write Enable. + SPI_EWSR, // Prefix Opcode 1: Enable Write Status Register. +} PREFIX_OPCODE_INDEX; + +// +// Opcode Menu Index on the host SPI controller. +// +typedef enum { + SPI_READ_ID, // Opcode 0: READ ID, Read cycle with address. + SPI_READ, // Opcode 1: READ, Read cycle with address. + SPI_RDSR, // Opcode 2: Read Status Register, No address. + SPI_WRDI_SFDP, // Opcode 3: Write Disable or Discovery Parameters, = No address. + SPI_SERASE, // Opcode 4: Sector Erase (4KB), Write cycle with ad= dress. + SPI_BERASE, // Opcode 5: Block Erase (32KB), Write cycle with ad= dress. + SPI_PROG, // Opcode 6: Byte Program, Write cycle with address. + SPI_WRSR, // Opcode 7: Write Status Register, No address. +} SPI_OPCODE_INDEX; + +#endif diff --git a/Platform/BroxtonPlatformPkg/Common/Application/FirmwareUpdate/= FirmwareUpdate.inf b/Platform/BroxtonPlatformPkg/Common/Application/Firmwar= eUpdate/FirmwareUpdate.inf new file mode 100644 index 000000000..6215714f2 --- /dev/null +++ b/Platform/BroxtonPlatformPkg/Common/Application/FirmwareUpdate/Firmwar= eUpdate.inf @@ -0,0 +1,83 @@ +## @file +# Implements a Tunnel Mountain specific flash update program. This will a= llow +# users to update all regions of the flash as needed in a given update. +# +# Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+# = =20 +# This program and the accompanying materials are licensed and made availa= ble under +# the terms and conditions of the BSD License that accompanies this distri= bution. =20 +# The full text of the license may be found at = =20 +# http://opensource.org/licenses/bsd-license.php. = =20 +# = =20 +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, = =20 +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMP= LIED. =20 +# = =20 +# +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D FirmwareUpdate + FILE_GUID =3D AEFAF26C-FB6D-4fef-AF7A-9D78FF201FCA + MODULE_TYPE =3D UEFI_APPLICATION + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D ShellCEntryLib + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D X64 +# + +[Sources] + FirmwareUpdateStrings.uni + FirmwareUpdate.c + FirmwareUpdate.h + +[Packages] + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + ShellPkg/ShellPkg.dec + BroxtonPlatformPkg/PlatformPkg.dec + BroxtonSiPkg/BroxtonSiPkg.dec + =20 +[LibraryClasses] + BaseLib + BaseMemoryLib + CacheMaintenanceLib + DebugLib + FileHandleLib + #FlashDeviceLib + #SpiFlashCommonLib + MemoryAllocationLib + PcdLib + ShellCEntryLib + ShellLib + UefiApplicationEntryPoint + UefiBootServicesTableLib + UefiLib + UefiRuntimeServicesTableLib + +[Protocols] + gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiFirmwareVolumeBlockProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gScSpiProtocolGuid + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize ## CONSUMES + +[FixedPcd] +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize +# gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase + + gPlatformModuleTokenSpaceGuid.PcdFlashAreaBaseAddress + gPlatformModuleTokenSpaceGuid.PcdFlashAreaSize + +[BuildOptions] + MSFT:*_*_X64_CC_FLAGS =3D /Od=20 + INTEL:*_*_X64_CC_FLAGS =3D /Od=20 \ No newline at end of file diff --git a/Platform/BroxtonPlatformPkg/Common/Application/FirmwareUpdate/= FirmwareUpdateStrings.uni b/Platform/BroxtonPlatformPkg/Common/Application/= FirmwareUpdate/FirmwareUpdateStrings.uni new file mode 100644 index 0000000000000000000000000000000000000000..fdd254dea64e70d6021a660be1f= 861338ed910d0 GIT binary patch literal 7480 zcmc(kYfl?T6o%((EA>CDh$50SfsphXRh3L|h!qS7Z0IEw0*r}Uuv6PW(qEfzP5Plf zq3!$3@i4pVwX+zcYJ_KYcJ|DB?q`O7|5$%tNt?Rpv zJ9e+!P;2kFLw8sGlKa-T#68f{Bll19|~>H zooXfT-s-!q)+d?)4f}L7IuW(NJyiPs>l3{@)TrwbK{wFn>(*$8bB#Nqui@gSV zhU)|2OzR_Y$QAr;y)oT@`i)lQQDr4#(tN8`2cz$MBN>2cn360OG?Xr$css+kOuDS^ zds#1t|GqS|CWTi>@8Va_RWH*ywYEkNgOrYb5|9vOW1Gjal2Zz<&mvxz9y>B*zmh=3D=3D?U!2v1dbTS;MZj>Y3KE`;Y2h=3Dncs6!Rlxi_3Bce0yckJyp%?F&sICe)=3DiFr-!_2M$tCEBke)Ti!3G%RK`Wr;04;W@0w!;r;L zu?Nq>x?@xr-=3DVIxUA3NQ9_SakM4rd)rDlUP%gW=3DaxZjj*VBxE>xrQhew=3D(h=3D&jukE zL_Q`(e9I6I-B;Q_oi8F+#kj6FTf|k`>d^9v`yie5WN}37z!7$y$fA3SN*%2j>Mzll zTypAHGEe3}&z1|)QXn5r8YeLNO4!*n#d44(oanqTal*f8b1}?@m9oL-kPv@>K`H;Q7TZQI%)|g z=3Dm)Z}=3D;fcd@y6ceIUpNWJa(czb~ldQX3B5?vMu2RF_D+ru&t5#_3as@JdSbC`w3MD zRYh!NFgArNR+mF>EyxzkH-VPef*(gzlSXCGk`qmOL>as`krZDEHB}{utx8-{+^MTZ zincLn*Xzs|AmIV^6WWDIcS1+*ZqSQ-m+?W!aiy zAURU!n{QdI{{PFcE<8x^o&J9Hx~9&t^VvZCdoS0Bb5>bC8^tcG)UPf}5M<@qmLHkL za@vIArng_>Ew;;9@3)Z^b4p>3%tPPSO4gB|vU%u2E3qk7nG_fw`Wg0_MH1m0&=3DAe( zt&CN@6ha~&TyiQ4(Qlwim7H@V&f$tG;kNf%R)#YxxoE*Rt4XKhneA;67kS@>i#6dQ z#u)DRzIsU9@A8w5=3DFu4S1U#Dd-f8wkxs|GpO5M0bTUOCg&v6ogN8_A$##34XHj|b? zd7Iu=3DmBe{-MfqS?8F{jNie!+F56EC!HpqFtCEvU7It%hBug8352G!N7LGu5)IIBn} zd$KM&w-(uJIlj8y7m++(*cFFX-*J{gmu9CXP92>-ZkcBPkjSrzwO z=3DRPXJ%WEGs{`Qs^_~NzT|p zP_dx9Gs%D`O5Gby%TZsGP}WtakU^&zbitIK3m@7gQ6I7fl|VYM0b1 zYLC^ZYra&wt2H0jVDXI&HT<4*x}k{39S%2R++$^H<}w_TaOldz}2!lH@p=3D^-m0iiZ)MOo zrFFY`eIjakTZ-03ZTGX}h#uHGoce#6Dc(dL_7ugYaZ!ecSt4EAUB;bn|A$n4aeF@eOczT`7NYqZsg+{{S>RJMaJi literal 0 HcmV?d00001 --=20 2.11.0.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel