[Linaro-uefi,v3] Platforms/AMD/Styx: add experimental command line flash tool

Message ID 20170628140335.22690-1-ard.biesheuvel@linaro.org
State Accepted
Commit 3c4fa409b6b0ba729161fd4ce4d2ab0dfa036422
Headers show

Commit Message

Ard Biesheuvel June 28, 2017, 2:03 p.m.
This implements a standalone UEFI Shell application that updates the
EFI NOR partition with the contents of STYX_EFI.Fv. Note that this means
that
a) the ATF partition and EFI variables are preserved, *but*
b) this updater can only be used on systems that have already been flashed
   with a firmware build based on this open source branch (and not on systems
   still running AMI firmware)

NOTE: This tool performs no verification whatsoever whether the platform it
      is being executed on is compatible with the image it attempts to flash,
      nor does it check whether the flash completed successfully. This means
      you should only use it if you have a means of unbricking the board if
      needed, such as a Dediprog SPI flasher. You have been warned!

In order for the flasher to have access to the various PCDs that describe
where STYX_EFI.Fv lives in the NOR, it needs to be built as part of the
platform, but after STYX_EFI.Fv has been generated, which results in a
chicken-and-egg situation. Therefore, the recommended way of generating
the flasher is

1) delete the Build/<platform> directory entirely
2) build the platform
3) build the platform again, but append the following

  -m OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf \
  -D DO_FLASHER=TRUE

The flasher application is called 'StyxFlashUefi'

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Roy Franz <roy.franz@cavium.com>
---
v3: - broken out of the series, the remainder of which has already been merged
    - whitespace and coding style fixes (including INF_VERSION)
    - stress the experimental and unsupported nature in the commit log

 Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds | 86 ++++++++++++++++++
 Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S    | 25 +++++
 Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c     | 96 ++++++++++++++++++++
 Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf   | 53 +++++++++++
 Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc                      | 12 ++-
 Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc      |  8 ++
 Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc              |  8 ++
 7 files changed, 286 insertions(+), 2 deletions(-)

Comments

Leif Lindholm June 28, 2017, 2:33 p.m. | #1
On Wed, Jun 28, 2017 at 02:03:35PM +0000, Ard Biesheuvel wrote:
> This implements a standalone UEFI Shell application that updates the
> EFI NOR partition with the contents of STYX_EFI.Fv. Note that this means
> that
> a) the ATF partition and EFI variables are preserved, *but*
> b) this updater can only be used on systems that have already been flashed
>    with a firmware build based on this open source branch (and not on systems
>    still running AMI firmware)
> 
> NOTE: This tool performs no verification whatsoever whether the platform it
>       is being executed on is compatible with the image it attempts to flash,
>       nor does it check whether the flash completed successfully. This means
>       you should only use it if you have a means of unbricking the board if
>       needed, such as a Dediprog SPI flasher. You have been warned!
> 
> In order for the flasher to have access to the various PCDs that describe
> where STYX_EFI.Fv lives in the NOR, it needs to be built as part of the
> platform, but after STYX_EFI.Fv has been generated, which results in a
> chicken-and-egg situation. Therefore, the recommended way of generating
> the flasher is
> 
> 1) delete the Build/<platform> directory entirely
> 2) build the platform
> 3) build the platform again, but append the following
> 
>   -m OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf \
>   -D DO_FLASHER=TRUE
> 
> The flasher application is called 'StyxFlashUefi'
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Tested-by: Roy Franz <roy.franz@cavium.com>

LGTM
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>

> ---
> v3: - broken out of the series, the remainder of which has already been merged
>     - whitespace and coding style fixes (including INF_VERSION)
>     - stress the experimental and unsupported nature in the commit log
> 
>  Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds | 86 ++++++++++++++++++
>  Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S    | 25 +++++
>  Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c     | 96 ++++++++++++++++++++
>  Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf   | 53 +++++++++++
>  Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc                      | 12 ++-
>  Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc      |  8 ++
>  Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc              |  8 ++
>  7 files changed, 286 insertions(+), 2 deletions(-)
> 
> diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds b/Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds
> new file mode 100644
> index 000000000000..7a0c87c6e32b
> --- /dev/null
> +++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds
> @@ -0,0 +1,86 @@
> +/** @file
> +
> +  Unified linker script for GCC based builds
> +
> +  Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2015 - 2017, Linaro Ltd. All rights reserved.<BR>
> +  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
> +
> +  This program and the accompanying materials are licensed and made available under
> +  the terms and conditions of the BSD License that 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.
> +
> +**/
> +
> +SECTIONS {
> +
> +  /*
> +   * The PE/COFF binary consists of DOS and PE/COFF headers, and a sequence of
> +   * section headers adding up to PECOFF_HEADER_SIZE bytes (which differs
> +   * between 32-bit and 64-bit builds). The actual start of the .text section
> +   * will be rounded up based on its actual alignment.
> +   */
> +  . = PECOFF_HEADER_SIZE;
> +
> +  .text : ALIGN(CONSTANT(COMMONPAGESIZE)) {
> +    *(.text .text.* .stub .gnu.linkonce.t.*)
> +    *(.rodata .rodata.* .gnu.linkonce.r.*)
> +    *(.got .got.*)
> +
> +    /*
> +     * The contents of AutoGen.c files are mostly constant from the POV of the
> +     * program, but most of it ends up in .data or .bss by default since few of
> +     * the variable definitions that get emitted are declared as CONST.
> +     * Unfortunately, we cannot pull it into the .text section entirely, since
> +     * patchable PCDs are also emitted here, but we can at least move all of the
> +     * emitted GUIDs here.
> +     */
> +    *:AutoGen.obj(.data.g*Guid)
> +  }
> +
> +  /*
> +   * The alignment of the .data section should be less than or equal to the
> +   * alignment of the .text section. This ensures that the relative offset
> +   * between these sections is the same in the ELF and the PE/COFF versions of
> +   * this binary.
> +   */
> +  .data ALIGN(ALIGNOF(.text)) : ALIGN(CONSTANT(COMMONPAGESIZE)) {
> +    *(.data .data.* .gnu.linkonce.d.*)
> +    *(.bss .bss.*)
> +    *(.payload)
> +  }
> +
> +  .eh_frame ALIGN(CONSTANT(COMMONPAGESIZE)) : {
> +    KEEP (*(.eh_frame))
> +  }
> +
> +  .rela (INFO) : {
> +    *(.rela .rela.*)
> +  }
> +
> +  .hii : ALIGN(CONSTANT(COMMONPAGESIZE)) {
> +    KEEP (*(.hii))
> +  }
> +
> +  /*
> +   * Retain the GNU build id but in a non-allocatable section so GenFw
> +   * does not copy it into the PE/COFF image.
> +   */
> +  .build-id (INFO) : { *(.note.gnu.build-id) }
> +
> +  /DISCARD/ : {
> +    *(.note.GNU-stack)
> +    *(.gnu_debuglink)
> +    *(.interp)
> +    *(.dynsym)
> +    *(.dynstr)
> +    *(.dynamic)
> +    *(.hash .gnu.hash)
> +    *(.comment)
> +    *(COMMON)
> +  }
> +}
> diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S
> new file mode 100644
> index 000000000000..041339ee9b47
> --- /dev/null
> +++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S
> @@ -0,0 +1,25 @@
> +/** @file
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +
> +  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.
> +
> +**/
> +
> +  .section  ".payload"
> +  .align    12
> +
> +ASM_GLOBAL ASM_PFX(StyxFlashImageStart)
> +ASM_PFX(StyxFlashImageStart):
> +  .incbin   "STYX_EFI.Fv"
> +
> +  .align    2
> +ASM_GLOBAL ASM_PFX(StyxFlashImageSize)
> +ASM_PFX(StyxFlashImageSize):
> +  .long    . - ASM_PFX(StyxFlashImageStart)
> diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c
> new file mode 100644
> index 000000000000..8f181bc2a54d
> --- /dev/null
> +++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c
> @@ -0,0 +1,96 @@
> +/** @file
> +
> +  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +
> +  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 <Uefi.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/ShellCEntryLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +
> +#include <Protocol/AmdIscpDxeProtocol.h>
> +
> +#define UEFI_IMAGE_OFFSET     FixedPcdGet64 (PcdFvBaseAddress) - FixedPcdGet64 (PcdFdBaseAddress)
> +#define BLOCK_SIZE            SIZE_64KB
> +
> +STATIC AMD_ISCP_DXE_PROTOCOL  *mIscpDxeProtocol;
> +STATIC UINT8                  Buffer[BLOCK_SIZE];
> +
> +extern CONST UINT8            StyxFlashImageStart[];
> +extern CONST UINT32           StyxFlashImageSize;
> +
> +/***
> +  Main entrypoint
> +
> +  Establishes the main structure of the application.
> +
> +  @retval  0         The application exited normally.
> +  @retval  Other     An error occurred.
> +***/
> +INTN
> +EFIAPI
> +ShellAppMain (
> +  IN UINTN Argc,
> +  IN CHAR16 **Argv
> +  )
> +{
> +  EFI_STATUS      Status;
> +  UINTN           Index;
> +  INTN            Remaining;
> +
> +  Print (L"StyxFlashUefi: firmware updater for AMD Seattle based boards.\n");
> +
> +  Status = gBS->LocateProtocol (&gAmdIscpDxeProtocolGuid, NULL,
> +                  (VOID **)&mIscpDxeProtocol);
> +  if (EFI_ERROR (Status)) {
> +    Print (L"Failed to locate ISCP communication protocol, terminating...\n");
> +    return (INTN)Status;
> +  }
> +
> +  Index = 0;
> +  Remaining = StyxFlashImageSize;
> +  do {
> +    Status = mIscpDxeProtocol->AmdExecuteEraseFvBlockDxe (
> +                                 mIscpDxeProtocol,
> +                                 UEFI_IMAGE_OFFSET + Index * BLOCK_SIZE,
> +                                 BLOCK_SIZE);
> +    if (EFI_ERROR (Status)) {
> +      Print (L"Erase failed!\n");
> +      return (INTN)Status;
> +    }
> +
> +    CopyMem (Buffer, StyxFlashImageStart + Index * BLOCK_SIZE,
> +      MIN (Remaining, BLOCK_SIZE));
> +
> +    Status = mIscpDxeProtocol->AmdExecuteUpdateFvBlockDxe (
> +                                 mIscpDxeProtocol,
> +                                 UEFI_IMAGE_OFFSET + Index * BLOCK_SIZE,
> +                                 Buffer,
> +                                 MIN (Remaining, BLOCK_SIZE));
> +
> +    if (EFI_ERROR (Status)) {
> +      Print (L"Update failed!\n");
> +      return (INTN)Status;
> +    }
> +
> +    Remaining -= BLOCK_SIZE;
> +    Index++;
> +
> +    Print (L"Block %d of %d updated\n", Index, StyxFlashImageSize / BLOCK_SIZE);
> +
> +  } while (Remaining > 0);
> +
> +  Print (L"\nDone!\n");
> +
> +  return 0;
> +}
> diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf
> new file mode 100644
> index 000000000000..82ad96796680
> --- /dev/null
> +++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf
> @@ -0,0 +1,53 @@
> +#/** @file
> +#
> +#  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
> +#
> +#  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                    = 0x00010019
> +  BASE_NAME                      = StyxFlashUefi
> +  FILE_GUID                      = 07b65d9d-b1a2-416e-bd04-0b61b775f924
> +  MODULE_TYPE                    = UEFI_APPLICATION
> +  VERSION_STRING                 = 0.1
> +  ENTRY_POINT                    = ShellCEntryLib
> +
> +#
> +#  VALID_ARCHITECTURES           = AARCH64
> +#
> +
> +[Sources]
> +  StyxFlashImage.S
> +  StyxFlashUefi.c
> +
> +[Packages]
> +  AmdModulePkg/AmdModulePkg.dec
> +  ArmPkg/ArmPkg.dec
> +  MdePkg/MdePkg.dec
> +  ShellPkg/ShellPkg.dec
> +
> +[LibraryClasses]
> +  BaseMemoryLib
> +  ShellCEntryLib
> +  UefiBootServicesTableLib
> +  UefiLib
> +
> +[Protocols]
> +  gAmdIscpDxeProtocolGuid
> +
> +[FixedPcd]
> +  gArmTokenSpaceGuid.PcdFdBaseAddress
> +  gArmTokenSpaceGuid.PcdFvBaseAddress
> +
> +[BuildOptions]
> +  *_*_*_CC_FLAGS = -mcmodel=small
> +  *_*_*_DLINK_FLAGS = -z common-page-size=0x1000 -Wl,-T,$(MODULE_DIR)/Scripts/GccBase.lds
> +  *_*_*_PLATFORM_FLAGS = -I$(BIN_DIR)/../FV
> diff --git a/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc b/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc
> index 091914c047a3..90cda24ae49d 100644
> --- a/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc
> +++ b/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc
> @@ -17,8 +17,9 @@
>  ################################################################################
>  [Defines]
>  
> -DEFINE NUM_CORES = 4
> -DEFINE DO_KCS    = 0
> +DEFINE NUM_CORES    = 4
> +DEFINE DO_KCS       = 0
> +DEFINE DO_FLASHER   = FALSE
>  
>    PLATFORM_NAME                  = Cello
>    PLATFORM_GUID                  = 77861b3e-74b0-4ff3-8d18-c5ba5803e1bf
> @@ -690,3 +691,10 @@ DEFINE DO_KCS    = 0
>  !ifdef $(RENESAS_XHCI_FW_DIR)
>    OpenPlatformPkg/Drivers/Xhci/RenesasFirmwarePD720202/RenesasFirmwarePD720202.inf
>  !endif
> +
> +!if $(DO_FLASHER) == TRUE
> +  OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf {
> +    <LibraryClasses>
> +      ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
> +  }
> +!endif
> diff --git a/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc b/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc
> index 57d1425b2c8f..5b7d7f4a7b4a 100644
> --- a/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc
> +++ b/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc
> @@ -21,6 +21,7 @@ DEFINE NUM_CORES    = 4
>  DEFINE DO_PSCI      = 1
>  DEFINE DO_ISCP      = 1
>  DEFINE DO_KCS       = 1
> +DEFINE DO_FLASHER   = FALSE
>  
>    PLATFORM_NAME                  = Overdrive1000
>    PLATFORM_GUID                  = 36774DD7-20DE-4C5B-8722-f8861DFF1F16
> @@ -701,3 +702,10 @@ DEFINE DO_KCS       = 1
>        gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>        gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
>    }
> +
> +!if $(DO_FLASHER) == TRUE
> +  OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf {
> +    <LibraryClasses>
> +      ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
> +  }
> +!endif
> diff --git a/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc b/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc
> index 6c284fb3b7db..662a15a9ccea 100644
> --- a/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc
> +++ b/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc
> @@ -22,6 +22,7 @@ DEFINE NUM_CORES    = 8
>  DEFINE DO_PSCI      = 1
>  DEFINE DO_ISCP      = 1
>  DEFINE DO_KCS       = 1
> +DEFINE DO_FLASHER   = FALSE
>  
>    PLATFORM_NAME                  = Overdrive
>    PLATFORM_GUID                  = B2296C02-9DA1-4CD1-BD48-4D4F0F1276EB
> @@ -752,3 +753,10 @@ DEFINE DO_KCS       = 1
>        gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
>        gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
>    }
> +
> +!if $(DO_FLASHER) == TRUE
> +  OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf {
> +    <LibraryClasses>
> +      ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
> +  }
> +!endif
> -- 
> 2.9.3
>
Ard Biesheuvel June 28, 2017, 3:27 p.m. | #2
On 28 June 2017 at 14:33, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> On Wed, Jun 28, 2017 at 02:03:35PM +0000, Ard Biesheuvel wrote:
>> This implements a standalone UEFI Shell application that updates the
>> EFI NOR partition with the contents of STYX_EFI.Fv. Note that this means
>> that
>> a) the ATF partition and EFI variables are preserved, *but*
>> b) this updater can only be used on systems that have already been flashed
>>    with a firmware build based on this open source branch (and not on systems
>>    still running AMI firmware)
>>
>> NOTE: This tool performs no verification whatsoever whether the platform it
>>       is being executed on is compatible with the image it attempts to flash,
>>       nor does it check whether the flash completed successfully. This means
>>       you should only use it if you have a means of unbricking the board if
>>       needed, such as a Dediprog SPI flasher. You have been warned!
>>
>> In order for the flasher to have access to the various PCDs that describe
>> where STYX_EFI.Fv lives in the NOR, it needs to be built as part of the
>> platform, but after STYX_EFI.Fv has been generated, which results in a
>> chicken-and-egg situation. Therefore, the recommended way of generating
>> the flasher is
>>
>> 1) delete the Build/<platform> directory entirely
>> 2) build the platform
>> 3) build the platform again, but append the following
>>
>>   -m OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf \
>>   -D DO_FLASHER=TRUE
>>
>> The flasher application is called 'StyxFlashUefi'
>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> Tested-by: Roy Franz <roy.franz@cavium.com>
>
> LGTM
> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
>

Thanks

Pushed as 3c4fa409b6b0

Patch

diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds b/Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds
new file mode 100644
index 000000000000..7a0c87c6e32b
--- /dev/null
+++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/Scripts/GccBase.lds
@@ -0,0 +1,86 @@ 
+/** @file
+
+  Unified linker script for GCC based builds
+
+  Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2015 - 2017, Linaro Ltd. All rights reserved.<BR>
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+  This program and the accompanying materials are licensed and made available under
+  the terms and conditions of the BSD License that 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.
+
+**/
+
+SECTIONS {
+
+  /*
+   * The PE/COFF binary consists of DOS and PE/COFF headers, and a sequence of
+   * section headers adding up to PECOFF_HEADER_SIZE bytes (which differs
+   * between 32-bit and 64-bit builds). The actual start of the .text section
+   * will be rounded up based on its actual alignment.
+   */
+  . = PECOFF_HEADER_SIZE;
+
+  .text : ALIGN(CONSTANT(COMMONPAGESIZE)) {
+    *(.text .text.* .stub .gnu.linkonce.t.*)
+    *(.rodata .rodata.* .gnu.linkonce.r.*)
+    *(.got .got.*)
+
+    /*
+     * The contents of AutoGen.c files are mostly constant from the POV of the
+     * program, but most of it ends up in .data or .bss by default since few of
+     * the variable definitions that get emitted are declared as CONST.
+     * Unfortunately, we cannot pull it into the .text section entirely, since
+     * patchable PCDs are also emitted here, but we can at least move all of the
+     * emitted GUIDs here.
+     */
+    *:AutoGen.obj(.data.g*Guid)
+  }
+
+  /*
+   * The alignment of the .data section should be less than or equal to the
+   * alignment of the .text section. This ensures that the relative offset
+   * between these sections is the same in the ELF and the PE/COFF versions of
+   * this binary.
+   */
+  .data ALIGN(ALIGNOF(.text)) : ALIGN(CONSTANT(COMMONPAGESIZE)) {
+    *(.data .data.* .gnu.linkonce.d.*)
+    *(.bss .bss.*)
+    *(.payload)
+  }
+
+  .eh_frame ALIGN(CONSTANT(COMMONPAGESIZE)) : {
+    KEEP (*(.eh_frame))
+  }
+
+  .rela (INFO) : {
+    *(.rela .rela.*)
+  }
+
+  .hii : ALIGN(CONSTANT(COMMONPAGESIZE)) {
+    KEEP (*(.hii))
+  }
+
+  /*
+   * Retain the GNU build id but in a non-allocatable section so GenFw
+   * does not copy it into the PE/COFF image.
+   */
+  .build-id (INFO) : { *(.note.gnu.build-id) }
+
+  /DISCARD/ : {
+    *(.note.GNU-stack)
+    *(.gnu_debuglink)
+    *(.interp)
+    *(.dynsym)
+    *(.dynstr)
+    *(.dynamic)
+    *(.hash .gnu.hash)
+    *(.comment)
+    *(COMMON)
+  }
+}
diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S
new file mode 100644
index 000000000000..041339ee9b47
--- /dev/null
+++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashImage.S
@@ -0,0 +1,25 @@ 
+/** @file
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+
+  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.
+
+**/
+
+  .section  ".payload"
+  .align    12
+
+ASM_GLOBAL ASM_PFX(StyxFlashImageStart)
+ASM_PFX(StyxFlashImageStart):
+  .incbin   "STYX_EFI.Fv"
+
+  .align    2
+ASM_GLOBAL ASM_PFX(StyxFlashImageSize)
+ASM_PFX(StyxFlashImageSize):
+  .long    . - ASM_PFX(StyxFlashImageStart)
diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c
new file mode 100644
index 000000000000..8f181bc2a54d
--- /dev/null
+++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.c
@@ -0,0 +1,96 @@ 
+/** @file
+
+  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+
+  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 <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/ShellCEntryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include <Protocol/AmdIscpDxeProtocol.h>
+
+#define UEFI_IMAGE_OFFSET     FixedPcdGet64 (PcdFvBaseAddress) - FixedPcdGet64 (PcdFdBaseAddress)
+#define BLOCK_SIZE            SIZE_64KB
+
+STATIC AMD_ISCP_DXE_PROTOCOL  *mIscpDxeProtocol;
+STATIC UINT8                  Buffer[BLOCK_SIZE];
+
+extern CONST UINT8            StyxFlashImageStart[];
+extern CONST UINT32           StyxFlashImageSize;
+
+/***
+  Main entrypoint
+
+  Establishes the main structure of the application.
+
+  @retval  0         The application exited normally.
+  @retval  Other     An error occurred.
+***/
+INTN
+EFIAPI
+ShellAppMain (
+  IN UINTN Argc,
+  IN CHAR16 **Argv
+  )
+{
+  EFI_STATUS      Status;
+  UINTN           Index;
+  INTN            Remaining;
+
+  Print (L"StyxFlashUefi: firmware updater for AMD Seattle based boards.\n");
+
+  Status = gBS->LocateProtocol (&gAmdIscpDxeProtocolGuid, NULL,
+                  (VOID **)&mIscpDxeProtocol);
+  if (EFI_ERROR (Status)) {
+    Print (L"Failed to locate ISCP communication protocol, terminating...\n");
+    return (INTN)Status;
+  }
+
+  Index = 0;
+  Remaining = StyxFlashImageSize;
+  do {
+    Status = mIscpDxeProtocol->AmdExecuteEraseFvBlockDxe (
+                                 mIscpDxeProtocol,
+                                 UEFI_IMAGE_OFFSET + Index * BLOCK_SIZE,
+                                 BLOCK_SIZE);
+    if (EFI_ERROR (Status)) {
+      Print (L"Erase failed!\n");
+      return (INTN)Status;
+    }
+
+    CopyMem (Buffer, StyxFlashImageStart + Index * BLOCK_SIZE,
+      MIN (Remaining, BLOCK_SIZE));
+
+    Status = mIscpDxeProtocol->AmdExecuteUpdateFvBlockDxe (
+                                 mIscpDxeProtocol,
+                                 UEFI_IMAGE_OFFSET + Index * BLOCK_SIZE,
+                                 Buffer,
+                                 MIN (Remaining, BLOCK_SIZE));
+
+    if (EFI_ERROR (Status)) {
+      Print (L"Update failed!\n");
+      return (INTN)Status;
+    }
+
+    Remaining -= BLOCK_SIZE;
+    Index++;
+
+    Print (L"Block %d of %d updated\n", Index, StyxFlashImageSize / BLOCK_SIZE);
+
+  } while (Remaining > 0);
+
+  Print (L"\nDone!\n");
+
+  return 0;
+}
diff --git a/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf
new file mode 100644
index 000000000000..82ad96796680
--- /dev/null
+++ b/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf
@@ -0,0 +1,53 @@ 
+#/** @file
+#
+#  Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+#
+#  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                    = 0x00010019
+  BASE_NAME                      = StyxFlashUefi
+  FILE_GUID                      = 07b65d9d-b1a2-416e-bd04-0b61b775f924
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 0.1
+  ENTRY_POINT                    = ShellCEntryLib
+
+#
+#  VALID_ARCHITECTURES           = AARCH64
+#
+
+[Sources]
+  StyxFlashImage.S
+  StyxFlashUefi.c
+
+[Packages]
+  AmdModulePkg/AmdModulePkg.dec
+  ArmPkg/ArmPkg.dec
+  MdePkg/MdePkg.dec
+  ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  ShellCEntryLib
+  UefiBootServicesTableLib
+  UefiLib
+
+[Protocols]
+  gAmdIscpDxeProtocolGuid
+
+[FixedPcd]
+  gArmTokenSpaceGuid.PcdFdBaseAddress
+  gArmTokenSpaceGuid.PcdFvBaseAddress
+
+[BuildOptions]
+  *_*_*_CC_FLAGS = -mcmodel=small
+  *_*_*_DLINK_FLAGS = -z common-page-size=0x1000 -Wl,-T,$(MODULE_DIR)/Scripts/GccBase.lds
+  *_*_*_PLATFORM_FLAGS = -I$(BIN_DIR)/../FV
diff --git a/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc b/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc
index 091914c047a3..90cda24ae49d 100644
--- a/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc
+++ b/Platforms/AMD/Styx/CelloBoard/CelloBoard.dsc
@@ -17,8 +17,9 @@ 
 ################################################################################
 [Defines]
 
-DEFINE NUM_CORES = 4
-DEFINE DO_KCS    = 0
+DEFINE NUM_CORES    = 4
+DEFINE DO_KCS       = 0
+DEFINE DO_FLASHER   = FALSE
 
   PLATFORM_NAME                  = Cello
   PLATFORM_GUID                  = 77861b3e-74b0-4ff3-8d18-c5ba5803e1bf
@@ -690,3 +691,10 @@  DEFINE DO_KCS    = 0
 !ifdef $(RENESAS_XHCI_FW_DIR)
   OpenPlatformPkg/Drivers/Xhci/RenesasFirmwarePD720202/RenesasFirmwarePD720202.inf
 !endif
+
+!if $(DO_FLASHER) == TRUE
+  OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf {
+    <LibraryClasses>
+      ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+  }
+!endif
diff --git a/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc b/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc
index 57d1425b2c8f..5b7d7f4a7b4a 100644
--- a/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc
+++ b/Platforms/AMD/Styx/Overdrive1000Board/Overdrive1000Board.dsc
@@ -21,6 +21,7 @@  DEFINE NUM_CORES    = 4
 DEFINE DO_PSCI      = 1
 DEFINE DO_ISCP      = 1
 DEFINE DO_KCS       = 1
+DEFINE DO_FLASHER   = FALSE
 
   PLATFORM_NAME                  = Overdrive1000
   PLATFORM_GUID                  = 36774DD7-20DE-4C5B-8722-f8861DFF1F16
@@ -701,3 +702,10 @@  DEFINE DO_KCS       = 1
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
       gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
   }
+
+!if $(DO_FLASHER) == TRUE
+  OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf {
+    <LibraryClasses>
+      ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+  }
+!endif
diff --git a/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc b/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc
index 6c284fb3b7db..662a15a9ccea 100644
--- a/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc
+++ b/Platforms/AMD/Styx/OverdriveBoard/OverdriveBoard.dsc
@@ -22,6 +22,7 @@  DEFINE NUM_CORES    = 8
 DEFINE DO_PSCI      = 1
 DEFINE DO_ISCP      = 1
 DEFINE DO_KCS       = 1
+DEFINE DO_FLASHER   = FALSE
 
   PLATFORM_NAME                  = Overdrive
   PLATFORM_GUID                  = B2296C02-9DA1-4CD1-BD48-4D4F0F1276EB
@@ -752,3 +753,10 @@  DEFINE DO_KCS       = 1
       gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
       gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
   }
+
+!if $(DO_FLASHER) == TRUE
+  OpenPlatformPkg/Platforms/AMD/Styx/Applications/StyxFlashUefi/StyxFlashUefi.inf {
+    <LibraryClasses>
+      ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+  }
+!endif