subtree updates: raspberrypi security arm

meta-arm: eb9c47a4e1..9b6c8c95e4:
  Abdellatif El Khlifi (1):
        CI: append classes to INHERIT in the common fvp.yml

  Adam Johnston (1):
        arm-bsp/linux-yocto: Update N1SDP PCI quirk patch

  Jon Mason (10):
        CI: add yml files for defaults
        CI: add support for dev kernel, rt kernel, and poky-tiny
        arm-bsp/fvp-base: update to u-boot 2023.01
        arm-bsp/fvp-base-arm32: remove support
        ci: add external-toolchain to qemuarm-secureboot
        arm-bsp/optee: remove unused recipes
        arm/optee: optee-os include cleanup
        arm/optee-os: update to 3.20.0
        arm/edk2: update version and relocate edk2-basetools to be with edk2
        arm-bsp/fvp-base: Add edk2 build testing

  Ross Burton (7):
        arm-bsp/linux-arm64-ack: update Upstream-Status tags
        CI: add CI_CLEAN_REPOS variable to allow cleaning the repo reference cache
        arm/scp-firmware: fix up whitespace
        arm/scp-firmware: enable verbose builds
        arm/scp-firmware: remove textrel from INSANE_SKIP
        arm/scp-firmware: improve debug packaging
        CI: mask poky's llvm if we're using clang

  Rui Miguel Silva (1):
        arm-bsp/optee: bump corstone1000 to v3.20

  Satish Kumar (1):
        arm-bsp/corstone1000: new gpt based disk layout and fwu metadata

  Xueliang Zhong (1):
        arm-bsp/n1sdp: update to linux yocto kernel 6.1

meta-security: c06b9a18a6..a397a38ed9:
  Armin Kuster (16):
        openscap: update to 1.3.6
        openscap: update to 1.3.7
        openscap git: add DEFAULT_PREFERENCE
        python3-fail2ban: update to 1.0.2
        python3-privacyidea: update to 3.8.1
        libhtp: update to 0.5.42
        lkrg-modules: update to 0.9.6
        chkrootkit: update to 0.57
        fscrypt: update to 1.1.0
        libmspack: update to 1.11
        firejail: update 0.9.72
        suricata: update to 6.0.10
        apparmor: update to 3.1.3
        krill: update 0.12.3
        cryptmout: update to 6.2.0
        packagegroup-core-security: refactor the inclusion of krill

  Eero Aaltonen (1):
        dm-verity-img.bbclass: fix syntax warning

  Jose Quaresma (3):
        meta-hardening/layer: lower the priority from 10 to 6
        meta-security-compliance/layer: lower the priority from 10 to 6
        meta-tpm/layer: lower the priority from 10 to 6

  Kevin Hao (1):
        dm-verity-img.bbclass: Fix the hash offset alignment issue

  Mikko Rapeli (1):
        ima-evm-utils: disable documentation from build

  Paul Gortmaker (3):
        dm-verity: update beaglebone wic to match meta-yocto
        dm-verity: add basic non-arch/non-BSP yocto specific settings
        dm-verity: document board specifics for Beaglebone Black

  Peter Marko (1):
        tpm2-tss: correct CVE product

meta-raspberrypi: e15b876155..3afdbbf782:
  Carlos Alberto Lopez Perez (1):
        mesa-demos: enable build with userland graphics drivers.

  Khem Raj (6):
        linux-raspberrypi: Add recipes for 6.1 kernel
        psplash: Make psplash wait for the framebuffer to be ready
        rpi-default-versions: Use 6.1 kernel as default
        gstreamer1.0-plugins-bad: Drop gpl packageconfig
        rpidistro-ffmpeg: Pin to use gcc always
        rpidistro-vlc: Fix build with clang16

Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: Ie6e60085306d31972098b87738eb550e5140b92a
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-image.bb b/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-image.bb
index 3a1639e..714a57c 100644
--- a/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-image.bb
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/images/corstone1000-image.bb
@@ -6,16 +6,16 @@
 COMPATIBLE_MACHINE = "corstone1000"
 
 inherit image
-inherit wic_nopt tfm_sign_image
+inherit tfm_sign_image
 inherit  uefi_capsule
 
 PACKAGE_INSTALL = ""
 
-IMAGE_FSTYPES += "wic wic.nopt uefi_capsule"
+IMAGE_FSTYPES += "wic uefi_capsule"
 
 UEFI_FIRMWARE_BINARY = "${PN}-${MACHINE}.${CAPSULE_IMGTYPE}"
 UEFI_CAPSULE_CONFIG = "${THISDIR}/files/${PN}-capsule-update-image.json"
-CAPSULE_IMGTYPE = "wic.nopt"
+CAPSULE_IMGTYPE = "wic"
 
 do_sign_images() {
     # Sign TF-A BL2
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0002-feat-corstone1000-bl2-loads-fip-based-on-metadata.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0002-feat-corstone1000-bl2-loads-fip-based-on-metadata.patch
new file mode 100644
index 0000000..3afaa4b
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/files/corstone1000/0002-feat-corstone1000-bl2-loads-fip-based-on-metadata.patch
@@ -0,0 +1,167 @@
+From 360aa32846a97e775750e06865d462c6258179fa Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Mon, 9 Jan 2023 13:59:06 +0000
+Subject: [PATCH] feat(corstone1000): bl2 loads fip based on metadata
+
+Previously bl2 was reading the boot_index directly with a hard coded
+address and then set the fip image spec with fip offsets base based on
+the boot_index value.
+This commit removes this logic and rely on PSA_FWU_SUPPORT
+which reads the fip partition based on the active firmware bank written in
+metadata.
+
+Note: fip partition contains signature area at the begining. Hence, the fip
+image starts at fip partition + fip signature area size.
+
+Upstream-Status: Pending
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+
+%% original patch: 0002-feat-corstone1000-bl2-loads-fip-based-on-metadata.patch
+---
+ bl2/bl2_main.c                                |  4 +++
+ .../corstone1000/common/corstone1000_plat.c   | 32 ++++++-------------
+ .../common/include/platform_def.h             | 12 +++----
+ tools/cert_create/Makefile                    |  4 +--
+ tools/fiptool/Makefile                        |  4 +--
+ 5 files changed, 24 insertions(+), 32 deletions(-)
+
+diff --git a/bl2/bl2_main.c b/bl2/bl2_main.c
+index 5da803795..f25dc3029 100644
+--- a/bl2/bl2_main.c
++++ b/bl2/bl2_main.c
+@@ -86,6 +86,10 @@ void bl2_main(void)
+ 	/* Perform remaining generic architectural setup in S-EL1 */
+ 	bl2_arch_setup();
+ 
++#if ARM_GPT_SUPPORT
++	partition_init(GPT_IMAGE_ID);
++#endif
++
+ #if PSA_FWU_SUPPORT
+ 	fwu_init();
+ #endif /* PSA_FWU_SUPPORT */
+diff --git a/plat/arm/board/corstone1000/common/corstone1000_plat.c b/plat/arm/board/corstone1000/common/corstone1000_plat.c
+index 0235f8b84..7f9708a82 100644
+--- a/plat/arm/board/corstone1000/common/corstone1000_plat.c
++++ b/plat/arm/board/corstone1000/common/corstone1000_plat.c
+@@ -33,36 +33,17 @@ const mmap_region_t plat_arm_mmap[] = {
+ static void set_fip_image_source(void)
+ {
+ 	const struct plat_io_policy *policy;
+-	/*
+-	 * metadata for firmware update is written at 0x0000 offset of the flash.
+-	 * PLAT_ARM_BOOT_BANK_FLAG contains the boot bank that TF-M is booted.
+-	 * As per firmware update spec, at a given point of time, only one bank
+-	 * is active. This means, TF-A should boot from the same bank as TF-M.
+-	 */
+-	volatile uint32_t *boot_bank_flag = (uint32_t *)(PLAT_ARM_BOOT_BANK_FLAG);
+-
+-	if (*boot_bank_flag > 1) {
+-		VERBOSE("Boot_bank is set higher than possible values");
+-	}
+-
+-	VERBOSE("Boot bank flag = %u.\n\r", *boot_bank_flag);
+ 
+ 	policy = FCONF_GET_PROPERTY(arm, io_policies, FIP_IMAGE_ID);
+ 
+ 	assert(policy != NULL);
+ 	assert(policy->image_spec != 0UL);
+ 
++	/* FIP Partition contains Signature area at the begining which TF-A doesn't expect */
+ 	io_block_spec_t *spec = (io_block_spec_t *)policy->image_spec;
++	spec->offset += FIP_SIGNATURE_AREA_SIZE;
++	spec->length -= FIP_SIGNATURE_AREA_SIZE;
+ 
+-	if ((*boot_bank_flag) == 0) {
+-		VERBOSE("Booting from bank 0: fip offset = 0x%lx\n\r",
+-						PLAT_ARM_FIP_BASE_BANK0);
+-		spec->offset = PLAT_ARM_FIP_BASE_BANK0;
+-	} else {
+-		VERBOSE("Booting from bank 1: fip offset = 0x%lx\n\r",
+-						PLAT_ARM_FIP_BASE_BANK1);
+-		spec->offset = PLAT_ARM_FIP_BASE_BANK1;
+-	}
+ }
+ 
+ void bl2_platform_setup(void)
+@@ -75,6 +56,13 @@ void bl2_platform_setup(void)
+ 	set_fip_image_source();
+ }
+ 
++void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1,
++			       u_register_t arg2, u_register_t arg3)
++{
++	arm_bl2_early_platform_setup((uintptr_t)arg0, (meminfo_t *)arg1);
++	NOTICE("CS1k: early at bl2_platform_setup\n");
++}
++
+ /* corstone1000 only has one always-on power domain and there
+  * is no power control present
+  */
+diff --git a/plat/arm/board/corstone1000/common/include/platform_def.h b/plat/arm/board/corstone1000/common/include/platform_def.h
+index 584d485f3..0bfab05a4 100644
+--- a/plat/arm/board/corstone1000/common/include/platform_def.h
++++ b/plat/arm/board/corstone1000/common/include/platform_def.h
+@@ -173,16 +173,16 @@
+ 
+ /* NOR Flash */
+ 
+-#define PLAT_ARM_BOOT_BANK_FLAG		UL(0x08002000)
+-#define PLAT_ARM_FIP_BASE_BANK0		UL(0x081EF000)
+-#define PLAT_ARM_FIP_BASE_BANK1		UL(0x0916F000)
+-#define PLAT_ARM_FIP_MAX_SIZE		UL(0x1ff000)  /* 1.996 MB */
+-
+ #define PLAT_ARM_NVM_BASE		V2M_FLASH0_BASE
+ #define PLAT_ARM_NVM_SIZE		(SZ_32M)  /* 32 MB */
++#define PLAT_ARM_FIP_MAX_SIZE		UL(0x1ff000)  /* 1.996 MB */
+ 
+-#define PLAT_ARM_FLASH_IMAGE_BASE	PLAT_ARM_FIP_BASE_BANK0
++#define PLAT_ARM_FLASH_IMAGE_BASE	UL(0x08000000)
+ #define PLAT_ARM_FLASH_IMAGE_MAX_SIZE	PLAT_ARM_FIP_MAX_SIZE
++#define PLAT_ARM_FIP_OFFSET_IN_GPT	(0x86000)
++
++/* FIP Information */
++#define FIP_SIGNATURE_AREA_SIZE         (0x1000)      /* 4 KB */
+ 
+ /*
+  * Some data must be aligned on the biggest cache line size in the platform.
+diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
+index ca548b836..32b5486a0 100644
+--- a/tools/cert_create/Makefile
++++ b/tools/cert_create/Makefile
+@@ -69,8 +69,8 @@ INC_DIR += -I ./include -I ${PLAT_INCLUDE} -I ${OPENSSL_DIR}/include
+ # directory. However, for a local build of OpenSSL, the built binaries are
+ # located under the main project directory (i.e.: ${OPENSSL_DIR}, not
+ # ${OPENSSL_DIR}/lib/).
+-LIB_DIR := -L ${OPENSSL_DIR}/lib -L ${OPENSSL_DIR}
+-LIB := -lssl -lcrypto
++LIB_DIR := -L ${OPENSSL_DIR}/lib -L ${OPENSSL_DIR} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS}
++LIB := -lssl -lcrypto ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS}
+ 
+ HOSTCC ?= gcc
+ 
+diff --git a/tools/fiptool/Makefile b/tools/fiptool/Makefile
+index e6aeba95b..7c047479e 100644
+--- a/tools/fiptool/Makefile
++++ b/tools/fiptool/Makefile
+@@ -29,7 +29,7 @@ endif
+ # directory. However, for a local build of OpenSSL, the built binaries are
+ # located under the main project directory (i.e.: ${OPENSSL_DIR}, not
+ # ${OPENSSL_DIR}/lib/).
+-LDLIBS := -L${OPENSSL_DIR}/lib -L${OPENSSL_DIR} -lcrypto
++LDLIBS := -L${OPENSSL_DIR}/lib -L${OPENSSL_DIR} -lcrypto ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS} ${BUILD_LDFLAGS}
+ 
+ ifeq (${V},0)
+   Q := @
+@@ -37,7 +37,7 @@ else
+   Q :=
+ endif
+ 
+-INCLUDE_PATHS := -I../../include/tools_share  -I${OPENSSL_DIR}/include
++INCLUDE_PATHS := -I../../include/tools_share  -I${OPENSSL_DIR}/include ${BUILD_CFLAGS} ${BUILD_CFLAGS} ${BUILD_CFLAGS} ${BUILD_CFLAGS} ${BUILD_CFLAGS} ${BUILD_CFLAGS}
+ 
+ HOSTCC ?= gcc
+ 
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc
index 3034680..0081034 100644
--- a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-corstone1000.inc
@@ -6,7 +6,8 @@
 
 SRC_URI:append = " \ 
 	file://0001-Fix-FF-A-version-in-SPMC-manifest.patch \
-	"
+    file://0002-feat-corstone1000-bl2-loads-fip-based-on-metadata.patch \
+    "
 
 TFA_DEBUG = "1"
 TFA_UBOOT ?= "1"
@@ -31,6 +32,9 @@
                         CREATE_KEYS=1 \
                         GENERATE_COT=1 \
                         TRUSTED_BOARD_BOOT=1 \
+                        ARM_GPT_SUPPORT=1 \
+                        PSA_FWU_SUPPORT=1 \
+                        NR_OF_IMAGES_IN_FW_BANK=4 \
                         COT=tbbr \
                         ARM_ROTPK_LOCATION=devel_rsa  \
                         ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp-arm32.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp-arm32.inc
deleted file mode 100644
index fdaadb9..0000000
--- a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp-arm32.inc
+++ /dev/null
@@ -1,12 +0,0 @@
-# Armv7-A FVP specific TFA parameters
-
-COMPATIBLE_MACHINE = "fvp-base-arm32"
-TFA_PLATFORM = "fvp"
-TFA_UBOOT = "1"
-TFA_BUILD_TARGET = "dtbs bl1 bl32 fip"
-
-EXTRA_OEMAKE:append = " \
-    ARCH=aarch32 \
-    AARCH32_SP=sp_min \
-    "
-
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp.inc
index 43340cd..ca96b44 100644
--- a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp.inc
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-fvp.inc
@@ -8,5 +8,5 @@
 TFA_PLATFORM = "fvp"
 TFA_DEBUG = "1"
 TFA_MBEDTLS = "1"
-TFA_UBOOT = "1"
+TFA_UBOOT ?= "1"
 TFA_BUILD_TARGET = "bl1 bl2 bl31 dtbs fip"
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.8.%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.8.%.bbappend
index 09ed3f7..220dd6e 100644
--- a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.8.%.bbappend
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.8.%.bbappend
@@ -6,7 +6,6 @@
 MACHINE_TFA_REQUIRE:corstone500 = "trusted-firmware-a-corstone500.inc"
 MACHINE_TFA_REQUIRE:corstone1000 = "trusted-firmware-a-corstone1000.inc"
 MACHINE_TFA_REQUIRE:fvp-base = "trusted-firmware-a-fvp.inc"
-MACHINE_TFA_REQUIRE:fvp-base-arm32 = "trusted-firmware-a-fvp-arm32.inc"
 MACHINE_TFA_REQUIRE:juno = "trusted-firmware-a-juno.inc"
 MACHINE_TFA_REQUIRE:n1sdp = "trusted-firmware-a-n1sdp.inc"
 MACHINE_TFA_REQUIRE:sgi575 = "trusted-firmware-a-sgi575.inc"
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-corstone1000-Increase-number-of-assets.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-corstone1000-Increase-number-of-assets.patch
deleted file mode 100644
index f0368b8..0000000
--- a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-corstone1000-Increase-number-of-assets.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From decb355247c4ba4b876997f55c27ec3f55dbacd2 Mon Sep 17 00:00:00 2001
-From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
-Date: Mon, 23 Jan 2023 13:25:28 +0000
-Subject: [PATCH] Platform: corstone1000: Increase number of assets
-
-As Corstone1000 stores at boot time few efi variables.
-Therefore, number of assets is increased to compansate this early usage.
-
-Note: Adding platform customized configs to config_tfm.h
-      More information see:
-https://tf-m-user-guide.trustedfirmware.org/configuration/header_file_system.html
-
-Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
-Upstream-Status: Pending [Not submitted yet]
----
- platform/ext/target/arm/corstone1000/config_tfm_target.h | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/platform/ext/target/arm/corstone1000/config_tfm_target.h b/platform/ext/target/arm/corstone1000/config_tfm_target.h
-index bf8d2f95f7..e968366639 100644
---- a/platform/ext/target/arm/corstone1000/config_tfm_target.h
-+++ b/platform/ext/target/arm/corstone1000/config_tfm_target.h
-@@ -16,4 +16,12 @@
- #undef PLATFORM_SERVICE_OUTPUT_BUFFER_SIZE
- #define PLATFORM_SERVICE_OUTPUT_BUFFER_SIZE    256
- 
-+/* The maximum number of assets to be stored in the Internal Trusted Storage. */
-+#undef ITS_NUM_ASSETS
-+#define ITS_NUM_ASSETS       20
-+
-+/* The maximum number of assets to be stored in the Protected Storage area. */
-+#undef PS_NUM_ASSETS
-+#define PS_NUM_ASSETS        20
-+
- #endif /* __CONFIG_TFM_TARGET_H__ */
--- 
-2.25.1
-
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-corstone1000-Introduce-IO-framework.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-corstone1000-Introduce-IO-framework.patch
new file mode 100644
index 0000000..900fd54
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0001-Platform-corstone1000-Introduce-IO-framework.patch
@@ -0,0 +1,1354 @@
+From 1db9afdbf70eb9708640debe5d7d24558fe0f63a Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Mon, 7 Nov 2022 12:49:11 +0000
+Subject: [PATCH 01/10] Platform: corstone1000: Introduce IO framework
+
+- Introduce IO storage framework
+- Add IO flash to abstract flash implementation details from upper layer
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Accepted [TF-Mv1.8.0]
+---
+ .../target/arm/corstone1000/CMakeLists.txt    |   4 +
+ .../ext/target/arm/corstone1000/io/io_block.c | 527 ++++++++++++++++++
+ .../ext/target/arm/corstone1000/io/io_block.h |  40 ++
+ .../ext/target/arm/corstone1000/io/io_defs.h  |  27 +
+ .../target/arm/corstone1000/io/io_driver.h    |  54 ++
+ .../ext/target/arm/corstone1000/io/io_flash.c | 183 ++++++
+ .../ext/target/arm/corstone1000/io/io_flash.h |  37 ++
+ .../target/arm/corstone1000/io/io_storage.c   | 289 ++++++++++
+ .../target/arm/corstone1000/io/io_storage.h   |  92 +++
+ 9 files changed, 1253 insertions(+)
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_block.c
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_block.h
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_defs.h
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_driver.h
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_flash.c
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_flash.h
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_storage.c
+ create mode 100644 platform/ext/target/arm/corstone1000/io/io_storage.h
+
+diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+index cfbaffc995..7808efae68 100644
+--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
++++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+@@ -125,6 +125,9 @@ target_sources(platform_bl2
+         fw_update_agent/fwu_agent.c
+         bl2_security_cnt.c
+         $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_OTP}>>:${PLATFORM_DIR}/ext/accelerator/cc312/otp_cc312.c>
++        io/io_block.c
++        io/io_flash.c
++        io/io_storage.c
+ )
+ 
+ if (PLATFORM_IS_FVP)
+@@ -182,6 +185,7 @@ target_include_directories(platform_bl2
+         fip_parser
+         Native_Driver
+         fw_update_agent
++        io
+         .
+     INTERFACE
+         cc312
+diff --git a/platform/ext/target/arm/corstone1000/io/io_block.c b/platform/ext/target/arm/corstone1000/io/io_block.c
+new file mode 100644
+index 0000000000..f7eaf7444c
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_block.c
+@@ -0,0 +1,527 @@
++/*
++ * Copyright (c) 2022 Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#include "io_block.h"
++
++#include <assert.h>
++#include <errno.h>
++
++#include "io_defs.h"
++#include "io_driver.h"
++#include "io_storage.h"
++
++typedef struct {
++    io_block_dev_spec_t *dev_spec;
++    uintptr_t base;
++    uint32_t file_pos;
++    uint32_t size;
++} block_dev_state_t;
++
++#define is_power_of_2(x) (((x) != 0U) && (((x) & ((x)-1U)) == 0U))
++
++io_type_t device_type_block(void);
++
++static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
++                      io_entity_t *entity);
++static int block_seek(io_entity_t *entity, int mode, size_t offset);
++static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
++                      size_t *length_read);
++static int block_write(io_entity_t *entity, const uintptr_t buffer,
++                       size_t length, size_t *length_written);
++static int block_close(io_entity_t *entity);
++static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
++static int block_dev_close(io_dev_info_t *dev_info);
++
++static const io_dev_connector_t block_dev_connector = {.dev_open =
++                                                           block_dev_open};
++
++static const io_dev_funcs_t block_dev_funcs = {
++    .type = device_type_block,
++    .open = block_open,
++    .seek = block_seek,
++    .size = NULL,
++    .read = block_read,
++    .write = block_write,
++    .close = block_close,
++    .dev_init = NULL,
++    .dev_close = block_dev_close,
++};
++
++static block_dev_state_t state_pool[MAX_IO_BLOCK_DEVICES];
++static io_dev_info_t dev_info_pool[MAX_IO_BLOCK_DEVICES];
++
++/* Track number of allocated block state */
++static unsigned int block_dev_count;
++
++io_type_t device_type_block(void) { return IO_TYPE_BLOCK; }
++
++/* Locate a block state in the pool, specified by address */
++static int find_first_block_state(const io_block_dev_spec_t *dev_spec,
++                                  unsigned int *index_out) {
++    unsigned int index;
++    int result = -ENOENT;
++
++    for (index = 0U; index < MAX_IO_BLOCK_DEVICES; ++index) {
++        /* dev_spec is used as identifier since it's unique */
++        if (state_pool[index].dev_spec == dev_spec) {
++            result = 0;
++            *index_out = index;
++            break;
++        }
++    }
++    return result;
++}
++
++/* Allocate a device info from the pool and return a pointer to it */
++static int allocate_dev_info(io_dev_info_t **dev_info) {
++    int result = -ENOMEM;
++    assert(dev_info != NULL);
++
++    if (block_dev_count < MAX_IO_BLOCK_DEVICES) {
++        unsigned int index = 0;
++        result = find_first_block_state(NULL, &index);
++        assert(result == 0);
++        /* initialize dev_info */
++        dev_info_pool[index].funcs = &block_dev_funcs;
++        dev_info_pool[index].info = (uintptr_t)&state_pool[index];
++        *dev_info = &dev_info_pool[index];
++        ++block_dev_count;
++    }
++
++    return result;
++}
++
++/* Release a device info to the pool */
++static int free_dev_info(io_dev_info_t *dev_info) {
++    int result;
++    unsigned int index = 0;
++    block_dev_state_t *state;
++    assert(dev_info != NULL);
++
++    state = (block_dev_state_t *)dev_info->info;
++    result = find_first_block_state(state->dev_spec, &index);
++    if (result == 0) {
++        /* free if device info is valid */
++        memset(state, 0, sizeof(block_dev_state_t));
++        memset(dev_info, 0, sizeof(io_dev_info_t));
++        --block_dev_count;
++    }
++
++    return result;
++}
++
++static int block_open(io_dev_info_t *dev_info, const uintptr_t spec,
++                      io_entity_t *entity) {
++    block_dev_state_t *cur;
++    io_block_spec_t *region;
++
++    assert((dev_info->info != (uintptr_t)NULL) && (spec != (uintptr_t)NULL) &&
++           (entity->info == (uintptr_t)NULL));
++
++    region = (io_block_spec_t *)spec;
++    cur = (block_dev_state_t *)dev_info->info;
++    assert(((region->offset % cur->dev_spec->block_size) == 0) &&
++           ((region->length % cur->dev_spec->block_size) == 0));
++
++    cur->base = region->offset;
++    cur->size = region->length;
++    cur->file_pos = 0;
++
++    entity->info = (uintptr_t)cur;
++    return 0;
++}
++
++/* parameter offset is relative address at here */
++static int block_seek(io_entity_t *entity, int mode, size_t offset) {
++    block_dev_state_t *cur;
++
++    assert(entity->info != (uintptr_t)NULL);
++
++    cur = (block_dev_state_t *)entity->info;
++
++    assert((offset >= 0) && ((uint32_t)offset < cur->size));
++    switch (mode) {
++        case IO_SEEK_SET:
++            cur->file_pos = (uint32_t)offset;
++            break;
++        case IO_SEEK_CUR:
++            cur->file_pos += (uint32_t)offset;
++            break;
++        default:
++            return -EINVAL;
++    }
++    assert(cur->file_pos < cur->size);
++    return 0;
++}
++
++/*
++ * This function allows the caller to read any number of bytes
++ * from any position. It hides from the caller that the low level
++ * driver only can read aligned blocks of data. For this reason
++ * we need to handle the use case where the first byte to be read is not
++ * aligned to start of the block, the last byte to be read is also not
++ * aligned to the end of a block, and there are zero or more blocks-worth
++ * of data in between.
++ *
++ * In such a case we need to read more bytes than requested (i.e. full
++ * blocks) and strip-out the leading bytes (aka skip) and the trailing
++ * bytes (aka padding). See diagram below
++ *
++ * cur->file_pos ------------
++ *                          |
++ * cur->base                |
++ *  |                       |
++ *  v                       v<----  length   ---->
++ *  --------------------------------------------------------------
++ * |           |         block#1    |        |   block#n          |
++ * |  block#0  |            +       |   ...  |     +              |
++ * |           | <- skip -> +       |        |     + <- padding ->|
++ *  ------------------------+----------------------+--------------
++ *             ^                                                  ^
++ *             |                                                  |
++ *             v    iteration#1                iteration#n        v
++ *              --------------------------------------------------
++ *             |                    |        |                    |
++ *             |<----  request ---->|  ...   |<----- request ---->|
++ *             |                    |        |                    |
++ *              --------------------------------------------------
++ *            /                   /          |                    |
++ *           /                   /           |                    |
++ *          /                   /            |                    |
++ *         /                   /             |                    |
++ *        /                   /              |                    |
++ *       /                   /               |                    |
++ *      /                   /                |                    |
++ *     /                   /                 |                    |
++ *    /                   /                  |                    |
++ *   /                   /                   |                    |
++ *  <---- request ------>                    <------ request  ----->
++ *  ---------------------                    -----------------------
++ *  |        |          |                    |          |           |
++ *  |<-skip->|<-nbytes->|           -------->|<-nbytes->|<-padding->|
++ *  |        |          |           |        |          |           |
++ *  ---------------------           |        -----------------------
++ *  ^        \           \          |        |          |
++ *  |         \           \         |        |          |
++ *  |          \           \        |        |          |
++ *  buf->offset \           \   buf->offset  |          |
++ *               \           \               |          |
++ *                \           \              |          |
++ *                 \           \             |          |
++ *                  \           \            |          |
++ *                   \           \           |          |
++ *                    \           \          |          |
++ *                     \           \         |          |
++ *                      --------------------------------
++ *                      |           |        |         |
++ * buffer-------------->|           | ...    |         |
++ *                      |           |        |         |
++ *                      --------------------------------
++ *                      <-count#1->|                   |
++ *                      <----------  count#n   -------->
++ *                      <----------  length  ---------->
++ *
++ * Additionally, the IO driver has an underlying buffer that is at least
++ * one block-size and may be big enough to allow.
++ */
++static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length,
++                      size_t *length_read) {
++    block_dev_state_t *cur;
++    io_block_spec_t *buf;
++    io_block_ops_t *ops;
++    int lba;
++    size_t block_size, left;
++    size_t nbytes;  /* number of bytes read in one iteration */
++    size_t request; /* number of requested bytes in one iteration */
++    size_t count;   /* number of bytes already read */
++    /*
++     * number of leading bytes from start of the block
++     * to the first byte to be read
++     */
++    size_t skip;
++
++    /*
++     * number of trailing bytes between the last byte
++     * to be read and the end of the block
++     */
++    size_t padding;
++
++    assert(entity->info != (uintptr_t)NULL);
++    cur = (block_dev_state_t *)entity->info;
++    ops = &(cur->dev_spec->ops);
++    buf = &(cur->dev_spec->buffer);
++    block_size = cur->dev_spec->block_size;
++    assert((length <= cur->size) && (length > 0U) && (ops->read != 0));
++
++    /*
++     * We don't know the number of bytes that we are going
++     * to read in every iteration, because it will depend
++     * on the low level driver.
++     */
++    count = 0;
++    for (left = length; left > 0U; left -= nbytes) {
++        /*
++         * We must only request operations aligned to the block
++         * size. Therefore if file_pos is not block-aligned,
++         * we have to request the operation to start at the
++         * previous block boundary and skip the leading bytes. And
++         * similarly, the number of bytes requested must be a
++         * block size multiple
++         */
++        skip = cur->file_pos & (block_size - 1U);
++
++        /*
++         * Calculate the block number containing file_pos
++         * - e.g. block 3.
++         */
++        lba = (cur->file_pos + cur->base) / block_size;
++
++        if ((skip + left) > buf->length) {
++            /*
++             * The underlying read buffer is too small to
++             * read all the required data - limit to just
++             * fill the buffer, and then read again.
++             */
++            request = buf->length;
++        } else {
++            /*
++             * The underlying read buffer is big enough to
++             * read all the required data. Calculate the
++             * number of bytes to read to align with the
++             * block size.
++             */
++            request = skip + left;
++            request = (request + (block_size - 1U)) & ~(block_size - 1U);
++        }
++        request = ops->read(lba, buf->offset, request);
++
++        if (request <= skip) {
++            /*
++             * We couldn't read enough bytes to jump over
++             * the skip bytes, so we should have to read
++             * again the same block, thus generating
++             * the same error.
++             */
++            return -EIO;
++        }
++
++        /*
++         * Need to remove skip and padding bytes,if any, from
++         * the read data when copying to the user buffer.
++         */
++        nbytes = request - skip;
++        padding = (nbytes > left) ? nbytes - left : 0U;
++        nbytes -= padding;
++
++        memcpy((void *)(buffer + count), (void *)(buf->offset + skip), nbytes);
++
++        cur->file_pos += nbytes;
++        count += nbytes;
++    }
++    assert(count == length);
++    *length_read = count;
++
++    return 0;
++}
++
++/*
++ * This function allows the caller to write any number of bytes
++ * from any position. It hides from the caller that the low level
++ * driver only can write aligned blocks of data.
++ * See comments for block_read for more details.
++ */
++static int block_write(io_entity_t *entity, const uintptr_t buffer,
++                       size_t length, size_t *length_written) {
++    block_dev_state_t *cur;
++    io_block_spec_t *buf;
++    io_block_ops_t *ops;
++    int lba;
++    size_t block_size, left;
++    size_t nbytes;  /* number of bytes read in one iteration */
++    size_t request; /* number of requested bytes in one iteration */
++    size_t count;   /* number of bytes already read */
++    /*
++     * number of leading bytes from start of the block
++     * to the first byte to be read
++     */
++    size_t skip;
++
++    /*
++     * number of trailing bytes between the last byte
++     * to be read and the end of the block
++     */
++    size_t padding;
++    assert(entity->info != (uintptr_t)NULL);
++    cur = (block_dev_state_t *)entity->info;
++    ops = &(cur->dev_spec->ops);
++    buf = &(cur->dev_spec->buffer);
++    block_size = cur->dev_spec->block_size;
++    assert((length <= cur->size) && (length > 0U) && (ops->read != 0) &&
++           (ops->write != 0));
++
++    /*
++     * We don't know the number of bytes that we are going
++     * to write in every iteration, because it will depend
++     * on the low level driver.
++     */
++    count = 0;
++    for (left = length; left > 0U; left -= nbytes) {
++        /*
++         * We must only request operations aligned to the block
++         * size. Therefore if file_pos is not block-aligned,
++         * we have to request the operation to start at the
++         * previous block boundary and skip the leading bytes. And
++         * similarly, the number of bytes requested must be a
++         * block size multiple
++         */
++        skip = cur->file_pos & (block_size - 1U);
++
++        /*
++         * Calculate the block number containing file_pos
++         * - e.g. block 3.
++         */
++        lba = (cur->file_pos + cur->base) / block_size;
++
++        if ((skip + left) > buf->length) {
++            /*
++             * The underlying read buffer is too small to
++             * read all the required data - limit to just
++             * fill the buffer, and then read again.
++             */
++            request = buf->length;
++        } else {
++            /*
++             * The underlying read buffer is big enough to
++             * read all the required data. Calculate the
++             * number of bytes to read to align with the
++             * block size.
++             */
++            request = skip + left;
++            request = (request + (block_size - 1U)) & ~(block_size - 1U);
++        }
++
++        /*
++         * The number of bytes that we are going to write
++         * from the user buffer will depend of the size
++         * of the current request.
++         */
++        nbytes = request - skip;
++        padding = (nbytes > left) ? nbytes - left : 0U;
++        nbytes -= padding;
++
++        /*
++         * If we have skip or padding bytes then we have to preserve
++         * some content and it means that we have to read before
++         * writing
++         */
++        if ((skip > 0U) || (padding > 0U)) {
++            request = ops->read(lba, buf->offset, request);
++            /*
++             * The read may return size less than
++             * requested. Round down to the nearest block
++             * boundary
++             */
++            request &= ~(block_size - 1U);
++            if (request <= skip) {
++                /*
++                 * We couldn't read enough bytes to jump over
++                 * the skip bytes, so we should have to read
++                 * again the same block, thus generating
++                 * the same error.
++                 */
++                return -EIO;
++            }
++            nbytes = request - skip;
++            padding = (nbytes > left) ? nbytes - left : 0U;
++            nbytes -= padding;
++        }
++
++        memcpy((void *)(buf->offset + skip), (void *)(buffer + count), nbytes);
++
++        request = ops->write(lba, buf->offset, request);
++        if (request <= skip) return -EIO;
++
++        /*
++         * And the previous write operation may modify the size
++         * of the request, so again, we have to calculate the
++         * number of bytes that we consumed from the user
++         * buffer
++         */
++        nbytes = request - skip;
++        padding = (nbytes > left) ? nbytes - left : 0U;
++        nbytes -= padding;
++
++        cur->file_pos += nbytes;
++        count += nbytes;
++    }
++    assert(count == length);
++    *length_written = count;
++
++    return 0;
++}
++
++static int block_close(io_entity_t *entity) {
++    entity->info = (uintptr_t)NULL;
++    return 0;
++}
++
++static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) {
++    block_dev_state_t *cur;
++    io_block_spec_t *buffer;
++    io_dev_info_t *info;
++    size_t block_size;
++    int result;
++    assert(dev_info != NULL);
++    result = allocate_dev_info(&info);
++    if (result != 0) return -ENOENT;
++
++    cur = (block_dev_state_t *)info->info;
++    /* dev_spec is type of io_block_dev_spec_t. */
++    cur->dev_spec = (io_block_dev_spec_t *)dev_spec;
++    buffer = &(cur->dev_spec->buffer);
++    block_size = cur->dev_spec->block_size;
++
++    assert((block_size > 0U) && (is_power_of_2(block_size) != 0U) &&
++           ((buffer->length % block_size) == 0U));
++
++    *dev_info = info; /* cast away const */
++    (void)block_size;
++    (void)buffer;
++    return 0;
++}
++
++static int block_dev_close(io_dev_info_t *dev_info) {
++    return free_dev_info(dev_info);
++}
++
++/* Exported functions */
++
++/* Register the Block driver with the IO abstraction */
++int register_io_dev_block(const io_dev_connector_t **dev_con) {
++    int result;
++
++    assert(dev_con != NULL);
++
++    /*
++     * Since dev_info isn't really used in io_register_device, always
++     * use the same device info at here instead.
++     */
++    result = io_register_device(&dev_info_pool[0]);
++    if (result == 0) *dev_con = &block_dev_connector;
++    return result;
++}
+diff --git a/platform/ext/target/arm/corstone1000/io/io_block.h b/platform/ext/target/arm/corstone1000/io/io_block.h
+new file mode 100644
+index 0000000000..1603aa74c5
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_block.h
+@@ -0,0 +1,40 @@
++/*
++ * Copyright (c) 2022 Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#ifndef __IO_BLOCK_H__
++#define __IO_BLOCK_H__
++
++#include "io_storage.h"
++
++/* block devices ops */
++typedef struct io_block_ops {
++    size_t (*read)(int lba, uintptr_t buf, size_t size);
++    size_t (*write)(int lba, const uintptr_t buf, size_t size);
++} io_block_ops_t;
++
++typedef struct io_block_dev_spec {
++    io_block_spec_t buffer;
++    io_block_ops_t ops;
++    size_t block_size;
++} io_block_dev_spec_t;
++
++struct io_dev_connector;
++
++int register_io_dev_block(const struct io_dev_connector **dev_con);
++
++#endif /* __IO_BLOCK_H__ */
+\ No newline at end of file
+diff --git a/platform/ext/target/arm/corstone1000/io/io_defs.h b/platform/ext/target/arm/corstone1000/io/io_defs.h
+new file mode 100644
+index 0000000000..acba969ed6
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_defs.h
+@@ -0,0 +1,27 @@
++/*
++ * Copyright (c) 2022 Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#ifndef __IO_DEFS_H__
++#define __IO_DEFS_H__
++
++#define MAX_IO_DEVICES          (2)
++#define MAX_IO_HANDLES          (2)
++#define MAX_IO_BLOCK_DEVICES    (2)
++#define MAX_IO_FLASH_DEVICES    (2)
++
++#endif /* __IO_DEFS_H__ */
+\ No newline at end of file
+diff --git a/platform/ext/target/arm/corstone1000/io/io_driver.h b/platform/ext/target/arm/corstone1000/io/io_driver.h
+new file mode 100644
+index 0000000000..cf9e21a6d4
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_driver.h
+@@ -0,0 +1,54 @@
++/*
++ * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef __IO_DRIVER_H__
++#define __IO_DRIVER_H__
++
++#include <io_storage.h>
++#include <stdint.h>
++
++/* Generic IO entity structure,representing an accessible IO construct on the
++ * device, such as a file */
++typedef struct io_entity {
++    struct io_dev_info *dev_handle;
++    uintptr_t info;
++} io_entity_t;
++
++/* Device info structure, providing device-specific functions and a means of
++ * adding driver-specific state */
++typedef struct io_dev_info {
++    const struct io_dev_funcs *funcs;
++    uintptr_t info;
++} io_dev_info_t;
++
++/* Structure used to create a connection to a type of device */
++typedef struct io_dev_connector {
++    /* dev_open opens a connection to a particular device driver */
++    int (*dev_open)(const uintptr_t dev_spec, io_dev_info_t **dev_info);
++} io_dev_connector_t;
++
++/* Structure to hold device driver function pointers */
++typedef struct io_dev_funcs {
++    io_type_t (*type)(void);
++    int (*open)(io_dev_info_t *dev_info, const uintptr_t spec,
++                io_entity_t *entity);
++    int (*seek)(io_entity_t *entity, int mode, size_t offset);
++    int (*size)(io_entity_t *entity, size_t *length);
++    int (*read)(io_entity_t *entity, uintptr_t buffer, size_t length,
++                size_t *length_read);
++    int (*write)(io_entity_t *entity, const uintptr_t buffer, size_t length,
++                 size_t *length_written);
++    int (*close)(io_entity_t *entity);
++    int (*dev_init)(io_dev_info_t *dev_info, const uintptr_t init_params);
++    int (*dev_close)(io_dev_info_t *dev_info);
++} io_dev_funcs_t;
++
++/* Operations intended to be performed during platform initialisation */
++
++/* Register an IO device */
++int io_register_device(const io_dev_info_t *dev_info);
++
++#endif /* __IO_DRIVER_H__ */
+diff --git a/platform/ext/target/arm/corstone1000/io/io_flash.c b/platform/ext/target/arm/corstone1000/io/io_flash.c
+new file mode 100644
+index 0000000000..ff4524e9c5
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_flash.c
+@@ -0,0 +1,183 @@
++/*
++ * Copyright (c) 2022 Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#include "io_flash.h"
++
++#include <assert.h>
++#include <errno.h>
++
++#include "Driver_Flash.h"
++#include "io_block.h"
++#include "io_defs.h"
++#include "io_driver.h"
++#include "io_storage.h"
++
++#if MAX_IO_FLASH_DEVICES > MAX_IO_BLOCK_DEVICES
++#error \
++    "FLASH devices are BLOCK devices .. MAX_IO_FLASH_DEVICES should be less or equal to MAX_IO_BLOCK_DEVICES"
++#endif
++
++/* Private Prototypes */
++
++static int flash_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
++static size_t flash_read(int lba, uintptr_t buf, size_t size, size_t flash_id);
++static size_t flash_write(int lba, const uintptr_t buf, size_t size,
++                          size_t flash_id);
++static size_t flash0_read(int lba, uintptr_t buf, size_t size);
++static size_t flash0_write(int lba, uintptr_t buf, size_t size);
++static size_t flash1_read(int lba, uintptr_t buf, size_t size);
++static size_t flash1_write(int lba, uintptr_t buf, size_t size);
++
++/** Private Data **/
++
++/* Flash device data */
++static const io_dev_connector_t flash_dev_connector = {.dev_open =
++                                                           flash_dev_open};
++static size_t flash_dev_count = 0;
++static io_flash_dev_spec_t *flash_dev_specs[MAX_IO_FLASH_DEVICES];
++
++/* Block device data */
++static io_dev_connector_t block_dev_connectors[MAX_IO_FLASH_DEVICES];
++static io_block_dev_spec_t block_dev_spec[MAX_IO_FLASH_DEVICES];
++
++/* Flash devices read/write function pointers */
++static io_block_ops_t flashs_ops[MAX_IO_FLASH_DEVICES] = {
++    [0] = {.read = flash0_read, .write = flash0_write},
++    [1] = {.read = flash1_read, .write = flash1_write},
++};
++
++/* Flash ops functions */
++static size_t flash_read(int lba, uintptr_t buf, size_t size, size_t flash_id) {
++    ARM_DRIVER_FLASH *flash_driver =
++        ((ARM_DRIVER_FLASH *)flash_dev_specs[flash_id]->flash_driver);
++    ARM_FLASH_INFO *info = flash_driver->GetInfo();
++    uint32_t addr = info->sector_size * lba;
++    uint32_t offset = addr - flash_dev_specs[flash_id]->base_addr;
++    size_t rem = info->sector_count * info->sector_size - offset;
++    size_t cnt = size < rem ? size : rem;
++
++    return flash_driver->ReadData(offset, buf, cnt);
++}
++
++static size_t flash_write(int lba, const uintptr_t buf, size_t size,
++                          size_t flash_id) {
++    ARM_DRIVER_FLASH *flash_driver =
++        ((ARM_DRIVER_FLASH *)flash_dev_specs[flash_id]->flash_driver);
++    ARM_FLASH_INFO *info = flash_driver->GetInfo();
++    int32_t rc = 0;
++    uint32_t addr = info->sector_size * lba;
++    uint32_t offset = addr - flash_dev_specs[flash_id]->base_addr;
++    size_t rem = info->sector_count * info->sector_size - offset;
++    size_t cnt = size < rem ? size : rem;
++
++    flash_driver->EraseSector(offset);
++    rc = flash_driver->ProgramData(offset, buf, cnt);
++    return rc;
++}
++
++/* Flash ops functions wrapper for each device */
++
++static size_t flash0_read(int lba, uintptr_t buf, size_t size) {
++    return flash_read(lba, buf, size, 0);
++}
++
++static size_t flash0_write(int lba, uintptr_t buf, size_t size) {
++    return flash_write(lba, buf, size, 0);
++}
++
++static size_t flash1_read(int lba, uintptr_t buf, size_t size) {
++    return flash_read(lba, buf, size, 1);
++}
++
++static size_t flash1_write(int lba, uintptr_t buf, size_t size) {
++    return flash_write(lba, buf, size, 1);
++}
++
++/**
++ *  Helper function to find the index of stored flash_dev_specs or
++ *  return a free slot in case of a new dev_spec
++ */
++static int find_flash_dev_specs(const uintptr_t dev_spec) {
++    /* Search in the saved ones */
++    for (int i = 0; i < flash_dev_count; ++i) {
++        if (flash_dev_specs[i] != NULL &&
++            flash_dev_specs[i]->flash_driver ==
++                ((io_flash_dev_spec_t *)dev_spec)->flash_driver) {
++            return i;
++        }
++    }
++    /* Find the first empty flash_dev_specs to be used */
++    for (int i = 0; i < flash_dev_count; ++i) {
++        if (flash_dev_specs[i] == NULL) {
++            return i;
++        }
++    }
++    return -1;
++}
++
++/**
++ * This function should be called
++ */
++static int flash_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) {
++    ARM_DRIVER_FLASH *flash_driver;
++    assert(dev_info != NULL);
++    assert(dev_spec != NULL);
++
++    size_t index = find_flash_dev_specs(dev_spec);
++
++    /* Check if Flash ops functions are defined for this flash */
++    assert(flashs_ops[index].read && flashs_ops[index].write);
++
++    flash_dev_specs[index] = dev_spec;
++    flash_driver = flash_dev_specs[index]->flash_driver;
++
++    block_dev_spec[index].block_size = flash_driver->GetInfo()->sector_size;
++    block_dev_spec[index].buffer.offset = flash_dev_specs[index]->buffer;
++    block_dev_spec[index].buffer.length = flash_dev_specs[index]->bufferlen;
++    block_dev_spec[index].ops = flashs_ops[index];
++
++    flash_driver->Initialize(NULL);
++
++    block_dev_connectors[index].dev_open(&block_dev_spec[index], dev_info);
++
++    return 0;
++}
++
++/* Exported functions */
++
++/**
++ * Register the flash device.
++ * Internally it register a block device.
++ */
++int register_io_dev_flash(const io_dev_connector_t **dev_con) {
++    int result;
++
++    if (flash_dev_count >= MAX_IO_FLASH_DEVICES) {
++        return -ENOENT;
++    }
++    assert(dev_con != NULL);
++
++    result = register_io_dev_block(dev_con);
++    if (result == 0) {
++        /* Store the block dev connector */
++        block_dev_connectors[flash_dev_count++] = **dev_con;
++        /* Override dev_con with the flash dev connector */
++        *dev_con = &flash_dev_connector;
++    }
++    return result;
++}
+diff --git a/platform/ext/target/arm/corstone1000/io/io_flash.h b/platform/ext/target/arm/corstone1000/io/io_flash.h
+new file mode 100644
+index 0000000000..8bc38b5824
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_flash.h
+@@ -0,0 +1,37 @@
++/*
++ * Copyright (c) 2022 Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#ifndef __IO_FLASH_H__
++#define __IO_FLASH_H__
++
++#include "io_storage.h"
++
++typedef struct io_flash_dev_spec {
++    uintptr_t buffer;
++    size_t bufferlen;
++    uint32_t base_addr;
++    uintptr_t flash_driver;
++} io_flash_dev_spec_t;
++
++struct io_dev_connector;
++
++/* Register the flash driver with the IO abstraction internally it register a
++ * block device*/
++int register_io_dev_flash(const struct io_dev_connector **dev_con);
++
++#endif /* __IO_FLASH_H__ */
+diff --git a/platform/ext/target/arm/corstone1000/io/io_storage.c b/platform/ext/target/arm/corstone1000/io/io_storage.c
+new file mode 100644
+index 0000000000..f26f4980f0
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_storage.c
+@@ -0,0 +1,289 @@
++/*
++ * Copyright (c) 2022 Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++
++#include "io_defs.h"
++#include "io_driver.h"
++
++/* Storage for a fixed maximum number of IO entities, definable by platform */
++static io_entity_t entity_pool[MAX_IO_HANDLES];
++
++/* Simple way of tracking used storage - each entry is NULL or a pointer to an
++ * entity */
++static io_entity_t *entity_map[MAX_IO_HANDLES];
++
++/* Track number of allocated entities */
++static unsigned int entity_count;
++
++/* Array of fixed maximum of registered devices, definable by platform */
++static const io_dev_info_t *devices[MAX_IO_DEVICES];
++
++/* Number of currently registered devices */
++static unsigned int dev_count;
++
++/* Return a boolean value indicating whether a device connector is valid */
++static bool is_valid_dev_connector(const io_dev_connector_t *dev_con) {
++    return (dev_con != NULL) && (dev_con->dev_open != NULL);
++}
++
++/* Return a boolean value indicating whether a device handle is valid */
++static bool is_valid_dev(const uintptr_t dev_handle) {
++    const io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
++
++    return (dev != NULL) && (dev->funcs != NULL) &&
++           (dev->funcs->type != NULL) && (dev->funcs->type() < IO_TYPE_MAX);
++}
++
++/* Return a boolean value indicating whether an IO entity is valid */
++static bool is_valid_entity(const uintptr_t handle) {
++    const io_entity_t *entity = (io_entity_t *)handle;
++
++    return (entity != NULL) && (is_valid_dev((uintptr_t)entity->dev_handle));
++}
++
++/* Return a boolean value indicating whether a seek mode is valid */
++static bool is_valid_seek_mode(io_seek_mode_t mode) {
++    return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX));
++}
++
++/* Open a connection to a specific device */
++static int io_storage_dev_open(const io_dev_connector_t *dev_con,
++                               const uintptr_t dev_spec,
++                               io_dev_info_t **dev_info) {
++    assert(dev_info != NULL);
++    assert(is_valid_dev_connector(dev_con));
++
++    return dev_con->dev_open(dev_spec, dev_info);
++}
++
++/* Set a handle to track an entity */
++static void set_handle(uintptr_t *handle, io_entity_t *entity) {
++    assert(handle != NULL);
++    *handle = (uintptr_t)entity;
++}
++
++/* Locate an entity in the pool, specified by address */
++static int find_first_entity(const io_entity_t *entity,
++                             unsigned int *index_out) {
++    int result = -ENOENT;
++    for (unsigned int index = 0; index < MAX_IO_HANDLES; ++index) {
++        if (entity_map[index] == entity) {
++            result = 0;
++            *index_out = index;
++            break;
++        }
++    }
++    return result;
++}
++
++/* Allocate an entity from the pool and return a pointer to it */
++static int allocate_entity(io_entity_t **entity) {
++    int result = -ENOMEM;
++    assert(entity != NULL);
++
++    if (entity_count < MAX_IO_HANDLES) {
++        unsigned int index = 0;
++        result = find_first_entity(NULL, &index);
++        assert(result == 0);
++        *entity = &entity_pool[index];
++        entity_map[index] = &entity_pool[index];
++        ++entity_count;
++    }
++
++    return result;
++}
++
++/* Release an entity back to the pool */
++static int free_entity(const io_entity_t *entity) {
++    int result;
++    unsigned int index = 0;
++    assert(entity != NULL);
++
++    result = find_first_entity(entity, &index);
++    if (result == 0) {
++        entity_map[index] = NULL;
++        --entity_count;
++    }
++
++    return result;
++}
++
++/* Exported API */
++
++/* Register an io device */
++int io_register_device(const io_dev_info_t *dev_info) {
++    int result = -ENOMEM;
++    assert(dev_info != NULL);
++
++    if (dev_count < MAX_IO_DEVICES) {
++        devices[dev_count] = dev_info;
++        dev_count++;
++        result = 0;
++    }
++
++    return result;
++}
++
++/* Open a connection to an IO device */
++int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec,
++                uintptr_t *handle) {
++    assert(handle != NULL);
++    return io_storage_dev_open(dev_con, dev_spec, (io_dev_info_t **)handle);
++}
++
++/* Initialise an IO device explicitly - to permit lazy initialisation or
++ * re-initialisation */
++int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params) {
++    int result = 0;
++    assert(dev_handle != (uintptr_t)NULL);
++    assert(is_valid_dev(dev_handle));
++
++    io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
++
++    /* Absence of registered function implies NOP here */
++    if (dev->funcs->dev_init != NULL) {
++        result = dev->funcs->dev_init(dev, init_params);
++    }
++
++    return result;
++}
++
++/* Close a connection to a device */
++int io_dev_close(uintptr_t dev_handle) {
++    int result = 0;
++    assert(dev_handle != (uintptr_t)NULL);
++    assert(is_valid_dev(dev_handle));
++
++    io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
++
++    /* Absence of registered function implies NOP here */
++    if (dev->funcs->dev_close != NULL) {
++        result = dev->funcs->dev_close(dev);
++    }
++
++    return result;
++}
++
++/* Synchronous operations */
++
++/* Open an IO entity */
++int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle) {
++    int result;
++    assert((spec != (uintptr_t)NULL) && (handle != NULL));
++    assert(is_valid_dev(dev_handle));
++
++    io_dev_info_t *dev = (io_dev_info_t *)dev_handle;
++    io_entity_t *entity;
++
++    result = allocate_entity(&entity);
++
++    if (result == 0) {
++        assert(dev->funcs->open != NULL);
++        result = dev->funcs->open(dev, spec, entity);
++
++        if (result == 0) {
++            entity->dev_handle = dev;
++            set_handle(handle, entity);
++        } else
++            free_entity(entity);
++    }
++    return result;
++}
++
++/* Seek to a specific position in an IO entity */
++int io_seek(uintptr_t handle, io_seek_mode_t mode, int32_t offset) {
++    int result = -ENODEV;
++    assert(is_valid_entity(handle) && is_valid_seek_mode(mode));
++
++    io_entity_t *entity = (io_entity_t *)handle;
++
++    io_dev_info_t *dev = entity->dev_handle;
++
++    if (dev->funcs->seek != NULL)
++        result = dev->funcs->seek(entity, mode, offset);
++
++    return result;
++}
++
++/* Determine the length of an IO entity */
++int io_size(uintptr_t handle, size_t *length) {
++    int result = -ENODEV;
++    assert(is_valid_entity(handle) && (length != NULL));
++
++    io_entity_t *entity = (io_entity_t *)handle;
++
++    io_dev_info_t *dev = entity->dev_handle;
++
++    if (dev->funcs->size != NULL) result = dev->funcs->size(entity, length);
++
++    return result;
++}
++
++/* Read data from an IO entity */
++int io_read(uintptr_t handle, uintptr_t buffer, size_t length,
++            size_t *length_read) {
++    int result = -ENODEV;
++    assert(is_valid_entity(handle));
++
++    io_entity_t *entity = (io_entity_t *)handle;
++
++    io_dev_info_t *dev = entity->dev_handle;
++
++    if (dev->funcs->read != NULL)
++        result = dev->funcs->read(entity, buffer, length, length_read);
++
++    return result;
++}
++
++/* Write data to an IO entity */
++int io_write(uintptr_t handle, const uintptr_t buffer, size_t length,
++             size_t *length_written) {
++    int result = -ENODEV;
++    assert(is_valid_entity(handle));
++
++    io_entity_t *entity = (io_entity_t *)handle;
++
++    io_dev_info_t *dev = entity->dev_handle;
++
++    if (dev->funcs->write != NULL) {
++        result = dev->funcs->write(entity, buffer, length, length_written);
++    }
++
++    return result;
++}
++
++/* Close an IO entity */
++int io_close(uintptr_t handle) {
++    int result = 0;
++    assert(is_valid_entity(handle));
++
++    io_entity_t *entity = (io_entity_t *)handle;
++
++    io_dev_info_t *dev = entity->dev_handle;
++
++    /* Absence of registered function implies NOP here */
++    if (dev->funcs->close != NULL) result = dev->funcs->close(entity);
++
++    /* Ignore improbable free_entity failure */
++    (void)free_entity(entity);
++
++    return result;
++}
+diff --git a/platform/ext/target/arm/corstone1000/io/io_storage.h b/platform/ext/target/arm/corstone1000/io/io_storage.h
+new file mode 100644
+index 0000000000..0cdca5b269
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/io/io_storage.h
+@@ -0,0 +1,92 @@
++/*
++ * Copyright (c) 2022 Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#ifndef __IO_STORAGE_H__
++#define __IO_STORAGE_H__
++
++#include <stddef.h>
++#include <stdint.h>
++
++/* Access modes used when accessing data on a device */
++#define IO_MODE_INVALID (0)
++#define IO_MODE_RO (1 << 0)
++#define IO_MODE_RW (1 << 1)
++
++/* Device type which can be used to enable policy decisions about which device
++ * to access */
++typedef enum {
++    IO_TYPE_INVALID,
++    IO_TYPE_SEMIHOSTING,
++    IO_TYPE_MEMMAP,
++    IO_TYPE_DUMMY,
++    IO_TYPE_FIRMWARE_IMAGE_PACKAGE,
++    IO_TYPE_BLOCK,
++    IO_TYPE_MTD,
++    IO_TYPE_MMC,
++    IO_TYPE_STM32IMAGE,
++    IO_TYPE_ENCRYPTED,
++    IO_TYPE_MAX
++} io_type_t;
++
++/* Modes used when seeking data on a supported device */
++typedef enum {
++    IO_SEEK_INVALID,
++    IO_SEEK_SET,
++    IO_SEEK_END,
++    IO_SEEK_CUR,
++    IO_SEEK_MAX
++} io_seek_mode_t;
++
++/* Connector type, providing a means of identifying a device to open */
++struct io_dev_connector;
++
++/* Block specification - used to refer to data on a device supporting
++ * block-like entities */
++typedef struct io_block_spec {
++    size_t offset;
++    size_t length;
++} io_block_spec_t;
++
++
++/* Open a connection to a device */
++int io_dev_open(const struct io_dev_connector *dev_con,
++                const uintptr_t dev_spec, uintptr_t *handle);
++
++/* Initialise a device explicitly - to permit lazy initialisation or
++ * re-initialisation */
++int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params);
++
++/* Close a connection to a device */
++int io_dev_close(uintptr_t dev_handle);
++
++/* Synchronous operations */
++int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle);
++
++int io_seek(uintptr_t handle, io_seek_mode_t mode, int32_t offset);
++
++int io_size(uintptr_t handle, size_t *length);
++
++int io_read(uintptr_t handle, uintptr_t buffer, size_t length,
++            size_t *length_read);
++
++int io_write(uintptr_t handle, const uintptr_t buffer, size_t length,
++             size_t *length_written);
++
++int io_close(uintptr_t handle);
++
++#endif /* __IO_STORAGE_H__ */
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-corstone1000-Add-IO-test-in-ci_regressions.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-corstone1000-Add-IO-test-in-ci_regressions.patch
new file mode 100644
index 0000000..a4da13e
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0002-Platform-corstone1000-Add-IO-test-in-ci_regressions.patch
@@ -0,0 +1,646 @@
+From 3bca7e6bae9a5017fff83b0a7d2d0d78b422a741 Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Mon, 7 Nov 2022 12:51:58 +0000
+Subject: [PATCH 02/10] Platform: corstone1000: Add IO test in ci_regressions
+
+The test is simply writing data on the edge of a block
+then reading back again.
+this test is preformed on two flash devices:
+- Nor Flash
+- Flash emu in the SRAM for testing
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Change-Id: I4950086e9e3dcbde29ab5b4ed5fe61fec7ebec86
+Upstream-Status: Accepted [TF-Mv1.8.0]
+---
+ .../ci_regression_tests/CMakeLists.txt        |  10 +
+ .../Driver_Flash_SRAM_Emu.c                   | 327 ++++++++++++++++++
+ .../ci_regression_tests/s_io_storage_test.c   | 147 ++++++++
+ .../ci_regression_tests/s_io_storage_test.h   |  15 +
+ .../corstone1000/ci_regression_tests/s_test.c |   5 +
+ .../ci_regression_tests/s_test_config.cmake   |   5 +
+ .../ci_regression_tests/test_flash.h          |  25 ++
+ 7 files changed, 534 insertions(+)
+ create mode 100644 platform/ext/target/arm/corstone1000/ci_regression_tests/Driver_Flash_SRAM_Emu.c
+ create mode 100644 platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.c
+ create mode 100644 platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.h
+ create mode 100644 platform/ext/target/arm/corstone1000/ci_regression_tests/test_flash.h
+
+diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt b/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt
+index 9543e29e55..405b2b3702 100644
+--- a/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt
++++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/CMakeLists.txt
+@@ -17,12 +17,18 @@ target_sources(tfm_test_suite_extra_s
+     PRIVATE
+         ${CMAKE_CURRENT_SOURCE_DIR}/s_test.c
+         ../Native_Driver/firewall.c
++        ../io/io_storage.c
++        ../io/io_block.c
++        ../io/io_flash.c
++        Driver_Flash_SRAM_Emu.c
++        s_io_storage_test.c
+ )
+ 
+ target_include_directories(tfm_test_suite_extra_s
+     PRIVATE
+         ../Device/Include
+         ../Native_Driver
++        ../io
+ )
+ 
+ target_link_libraries(tfm_test_suite_extra_s
+@@ -33,4 +39,8 @@ target_link_libraries(tfm_test_suite_extra_s
+ target_compile_definitions(tfm_test_suite_extra_s
+     PRIVATE
+         $<$<BOOL:${PLATFORM_IS_FVP}>:PLATFORM_IS_FVP>
++        TEST_FLASH_SIZE_IN_BYTES=${TEST_FLASH_SIZE_IN_BYTES}
++        TEST_FLASH_SECTOR_SIZE_IN_BYTES=${TEST_FLASH_SECTOR_SIZE_IN_BYTES}
++        TEST_FLASH_PAGE_SIZE=${TEST_FLASH_PAGE_SIZE}
++        TEST_FLASH_PROGRAM_UNIT=${TEST_FLASH_PROGRAM_UNIT}
+ )
+diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/Driver_Flash_SRAM_Emu.c b/platform/ext/target/arm/corstone1000/ci_regression_tests/Driver_Flash_SRAM_Emu.c
+new file mode 100644
+index 0000000000..06b6b51c09
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/Driver_Flash_SRAM_Emu.c
+@@ -0,0 +1,327 @@
++/*
++ * Copyright (c) 2013-2022 ARM Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: Apache-2.0
++ *
++ * Licensed under the Apache License, Version 2.0 (the License); you may
++ * not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ * www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#include <string.h>
++#include <stdint.h>
++#include "Driver_Flash.h"
++#include "test_flash.h"
++#include "tfm_sp_log.h"
++
++#ifndef ARG_UNUSED
++#define ARG_UNUSED(arg)  ((void)arg)
++#endif
++
++/* Driver version */
++#define ARM_FLASH_DRV_VERSION      ARM_DRIVER_VERSION_MAJOR_MINOR(1, 1)
++#define ARM_FLASH_DRV_ERASE_VALUE  0xFF
++
++
++/**
++ * There is no real flash memory. This driver just emulates a flash
++ * interface and behaviour on top of the SRAM memory.
++ */
++
++/**
++ * Data width values for ARM_FLASH_CAPABILITIES::data_width
++ * \ref ARM_FLASH_CAPABILITIES
++ */
++ enum {
++    DATA_WIDTH_8BIT   = 0u,
++    DATA_WIDTH_16BIT,
++    DATA_WIDTH_32BIT,
++    DATA_WIDTH_ENUM_SIZE
++};
++
++static const uint32_t data_width_byte[DATA_WIDTH_ENUM_SIZE] = {
++    sizeof(uint8_t),
++    sizeof(uint16_t),
++    sizeof(uint32_t),
++};
++
++
++/*
++ * ARM FLASH device structure
++ *
++ */
++struct arm_flash_dev_t {
++    const uint8_t* memory_base;   /*!< FLASH memory base address */
++    ARM_FLASH_INFO *data;         /*!< FLASH data */
++};
++
++/* Flash emulated memory */
++static uint8_t flash_memory[TEST_FLASH_SIZE_IN_BYTES]
++    __attribute__((aligned(TEST_FLASH_SECTOR_SIZE_IN_BYTES)));
++
++/* Flash Status */
++static ARM_FLASH_STATUS FlashStatus = {0, 0, 0};
++
++/* Driver Version */
++static const ARM_DRIVER_VERSION DriverVersion = {
++    ARM_FLASH_API_VERSION,
++    ARM_FLASH_DRV_VERSION
++};
++
++/* Driver Capabilities */
++static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
++    0, /* event_ready */
++    0, /* data_width = 0:8-bit, 1:16-bit, 2:32-bit */
++    1  /* erase_chip */
++};
++
++static int32_t is_range_valid(struct arm_flash_dev_t *flash_dev,
++                              uint32_t offset)
++{
++    uint32_t flash_limit = 0;
++    int32_t rc = 0;
++
++    flash_limit = (flash_dev->data->sector_count * flash_dev->data->sector_size);
++    if (offset > flash_limit) {
++        rc = -1;
++    }
++    return rc;
++}
++
++static int32_t is_write_aligned(struct arm_flash_dev_t *flash_dev,
++                                uint32_t param)
++{
++    int32_t rc = 0;
++
++    if ((param % flash_dev->data->program_unit) != 0) {
++        rc = -1;
++    }
++    return rc;
++}
++
++static int32_t is_sector_aligned(struct arm_flash_dev_t *flash_dev,
++                                 uint32_t offset)
++{
++    int32_t rc = 0;
++
++    if ((offset % flash_dev->data->sector_size) != 0) {
++        rc = -1;
++    }
++    return rc;
++}
++
++static int32_t is_flash_ready_to_write(const uint8_t *start_addr, uint32_t cnt)
++{
++    int32_t rc = 0;
++    uint32_t i;
++
++    for (i = 0; i < cnt; i++) {
++        if(start_addr[i] != ARM_FLASH_DRV_ERASE_VALUE) {
++            rc = -1;
++            break;
++        }
++    }
++
++    return rc;
++}
++
++static ARM_FLASH_INFO ARM_TEST_FLASH_DEV_DATA = {
++    .sector_info  = NULL,/* Uniform sector layout */
++    .sector_count = TEST_FLASH_SIZE_IN_BYTES / TEST_FLASH_SECTOR_SIZE_IN_BYTES,
++    .sector_size  = TEST_FLASH_SECTOR_SIZE_IN_BYTES,
++    .page_size    = TEST_FLASH_PAGE_SIZE,
++    .program_unit = TEST_FLASH_PROGRAM_UNIT,
++    .erased_value = ARM_FLASH_DRV_ERASE_VALUE};
++
++static struct arm_flash_dev_t ARM_TEST_FLASH_DEV = {
++    .memory_base = flash_memory,
++    .data        = &(ARM_TEST_FLASH_DEV_DATA)};
++
++static struct arm_flash_dev_t *TEST_FLASH_DEV = &ARM_TEST_FLASH_DEV;
++
++/*
++ * Functions
++ */
++
++static ARM_DRIVER_VERSION ARM_Flash_GetVersion(void)
++{
++    return DriverVersion;
++}
++
++static ARM_FLASH_CAPABILITIES ARM_Flash_GetCapabilities(void)
++{
++    return DriverCapabilities;
++}
++
++static int32_t ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)
++{
++    ARG_UNUSED(cb_event);
++
++    if (DriverCapabilities.data_width >= DATA_WIDTH_ENUM_SIZE) {
++        return ARM_DRIVER_ERROR;
++    }
++
++    /* Nothing to be done */
++    return ARM_DRIVER_OK;
++}
++
++static int32_t ARM_Flash_Uninitialize(void)
++{
++    /* Nothing to be done */
++    return ARM_DRIVER_OK;
++}
++
++static int32_t ARM_Flash_PowerControl(ARM_POWER_STATE state)
++{
++    switch (state) {
++    case ARM_POWER_FULL:
++        /* Nothing to be done */
++        return ARM_DRIVER_OK;
++        break;
++
++    case ARM_POWER_OFF:
++    case ARM_POWER_LOW:
++    default:
++        return ARM_DRIVER_ERROR_UNSUPPORTED;
++    }
++}
++
++static int32_t ARM_Flash_ReadData(uint32_t addr, void *data, uint32_t cnt)
++{
++    int32_t rc = 0;
++
++    /* The addr given is a relative address*/
++    uint32_t offset = addr;
++    addr += (uint32_t)(TEST_FLASH_DEV->memory_base);
++
++    /* Conversion between data items and bytes */
++    cnt *= data_width_byte[DriverCapabilities.data_width];
++
++    /* Check flash memory boundaries */
++    rc = is_range_valid(TEST_FLASH_DEV, offset + cnt);
++    if (rc != 0) {
++        return ARM_DRIVER_ERROR_PARAMETER;
++    }
++
++    /* Flash interface just emulated over SRAM, use memcpy */
++    memcpy(data, (void *)addr, cnt);
++
++    /* Conversion between bytes and data items */
++    cnt /= data_width_byte[DriverCapabilities.data_width];
++
++    return cnt;
++}
++
++static int32_t ARM_Flash_ProgramData(uint32_t addr, const void *data,
++                                     uint32_t cnt)
++{
++    int32_t rc = 0;
++
++    /* The addr given is a relative address*/
++    uint32_t offset = addr;
++    addr += (uint32_t)(TEST_FLASH_DEV->memory_base);
++
++    /* Conversion between data items and bytes */
++    cnt *= data_width_byte[DriverCapabilities.data_width];
++
++    /* Check flash memory boundaries and alignment with minimal write size */
++    rc  = is_range_valid(TEST_FLASH_DEV, offset + cnt);
++    rc |= is_write_aligned(TEST_FLASH_DEV, offset);
++    rc |= is_write_aligned(TEST_FLASH_DEV, cnt);
++    if (rc != 0) {
++        return ARM_DRIVER_ERROR_PARAMETER;
++    }
++
++    /* Check if the flash area to write the data was erased previously */
++    rc = is_flash_ready_to_write((const uint8_t*)addr, cnt);
++    if (rc != 0) {
++        return ARM_DRIVER_ERROR;
++    }
++
++    /* Flash interface just emulated over SRAM, use memcpy */
++    memcpy((void *)addr, data, cnt);
++
++    /* Conversion between bytes and data items */
++    cnt /= data_width_byte[DriverCapabilities.data_width];
++
++    return cnt;
++}
++
++static int32_t ARM_Flash_EraseSector(uint32_t addr)
++{
++    uint32_t rc = 0;
++
++    /* The addr given is a relative address*/
++    uint32_t offset = addr;
++    addr += (uint32_t)(TEST_FLASH_DEV->memory_base);
++
++    rc  = is_range_valid(TEST_FLASH_DEV, offset);
++    rc |= is_sector_aligned(TEST_FLASH_DEV, offset);
++    if (rc != 0) {
++        return ARM_DRIVER_ERROR_PARAMETER;
++    }
++
++    /* Flash interface just emulated over SRAM, use memset */
++    memset((void *)addr,
++           TEST_FLASH_DEV->data->erased_value,
++           TEST_FLASH_DEV->data->sector_size);
++    return ARM_DRIVER_OK;
++}
++
++static int32_t ARM_Flash_EraseChip(void)
++{
++    uint32_t i;
++    uint32_t addr = TEST_FLASH_DEV->memory_base;
++    int32_t rc = ARM_DRIVER_ERROR_UNSUPPORTED;
++
++    /* Check driver capability erase_chip bit */
++    if (DriverCapabilities.erase_chip == 1) {
++        for (i = 0; i < TEST_FLASH_DEV->data->sector_count; i++) {
++            /* Flash interface just emulated over SRAM, use memset */
++            memset((void *)addr,
++                   TEST_FLASH_DEV->data->erased_value,
++                   TEST_FLASH_DEV->data->sector_size);
++
++            addr += TEST_FLASH_DEV->data->sector_size;
++            rc = ARM_DRIVER_OK;
++        }
++    }
++    return rc;
++}
++
++static ARM_FLASH_STATUS ARM_Flash_GetStatus(void)
++{
++    return FlashStatus;
++}
++
++static ARM_FLASH_INFO * ARM_Flash_GetInfo(void)
++{
++    return TEST_FLASH_DEV->data;
++}
++
++
++/* Global Variables */
++
++ARM_DRIVER_FLASH Driver_TEST_FLASH = {
++    ARM_Flash_GetVersion,
++    ARM_Flash_GetCapabilities,
++    ARM_Flash_Initialize,
++    ARM_Flash_Uninitialize,
++    ARM_Flash_PowerControl,
++    ARM_Flash_ReadData,
++    ARM_Flash_ProgramData,
++    ARM_Flash_EraseSector,
++    ARM_Flash_EraseChip,
++    ARM_Flash_GetStatus,
++    ARM_Flash_GetInfo
++};
++
++uintptr_t flash_base_address = flash_memory;
+diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.c b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.c
+new file mode 100644
+index 0000000000..f8be384a74
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.c
+@@ -0,0 +1,147 @@
++/*
++ * Copyright (c) 2022, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include "s_io_storage_test.h"
++
++#include "Driver_Flash.h"
++#include "flash_layout.h"
++#include "io_block.h"
++#include "io_driver.h"
++#include "io_flash.h"
++#include "tfm_sp_log.h"
++
++#define ARRAY_LENGTH(array) (sizeof(array) / sizeof(*(array)))
++
++extern ARM_DRIVER_FLASH Driver_FLASH0;
++extern ARM_DRIVER_FLASH Driver_TEST_FLASH;
++extern uintptr_t flash_base_address;
++
++void s_test_io_storage_multiple_flash_simultaneous(struct test_result_t *ret) {
++    /* FLASH0 */
++    static io_dev_connector_t* flash0_dev_con;
++    static uint8_t local_block_flash0[FLASH_SECTOR_SIZE];
++    ARM_FLASH_INFO* flash0_info = Driver_FLASH0.GetInfo();
++    size_t flash0_block_size = flash0_info->sector_size;
++    io_flash_dev_spec_t flash0_dev_spec = {
++        .buffer = local_block_flash0,
++        .bufferlen = flash0_block_size,
++        .base_addr = FLASH_BASE_ADDRESS,
++        .flash_driver = &Driver_FLASH0,
++    };
++    io_block_spec_t flash0_spec = {
++        .offset = FLASH_BASE_ADDRESS,
++        .length = flash0_info->sector_count * flash0_info->sector_size};
++    uintptr_t flash0_dev_handle = NULL;
++    uintptr_t flash0_handle = NULL;
++
++    /* EMU TEST FLASH */
++    static io_dev_connector_t* flash_emu_dev_con;
++    static uint8_t local_block_flash_emu[TEST_FLASH_SECTOR_SIZE_IN_BYTES]
++        __attribute__((aligned(TEST_FLASH_SECTOR_SIZE_IN_BYTES)));
++    ARM_FLASH_INFO* flash_emu_info = Driver_TEST_FLASH.GetInfo();
++    size_t flash_emu_block_size = flash_emu_info->sector_size;
++    io_flash_dev_spec_t flash_emu_dev_spec = {
++        .buffer = local_block_flash_emu,
++        .bufferlen = flash_emu_block_size,
++        .base_addr = flash_base_address,
++        .flash_driver = &Driver_TEST_FLASH,
++    };
++    io_block_spec_t flash_emu_spec = {
++        .offset = flash_base_address,
++        .length = flash_emu_info->sector_count * flash_emu_info->sector_size};
++    uintptr_t flash_emu_dev_handle = NULL;
++    uintptr_t flash_emu_handle = NULL;
++
++    /* Common */
++    int rc = -1;
++    static uint8_t test_data[] = {0xEE, 0xDD, 0xCC, 0xBB, 0xAA,
++                                  0x10, 0x50, 0xA0, 0xD0, 0x51,
++                                  0x55, 0x44, 0x33, 0x22, 0x11};
++    static uint8_t actual_data[15];
++    size_t bytes_written_count = 0;
++    size_t bytes_read_count = 0;
++
++    memset(local_block_flash0, -1, sizeof(local_block_flash0));
++    memset(local_block_flash_emu, -1, sizeof(local_block_flash_emu));
++
++    /* Register */
++    register_io_dev_flash(&flash0_dev_con);
++    register_io_dev_flash(&flash_emu_dev_con);
++
++    io_dev_open(flash0_dev_con, &flash0_dev_spec, &flash0_dev_handle);
++    io_dev_open(flash_emu_dev_con, &flash_emu_dev_spec, &flash_emu_dev_handle);
++
++    /* Write Data */
++    io_open(flash0_dev_handle, &flash0_spec, &flash0_handle);
++    io_open(flash_emu_dev_handle, &flash_emu_spec, &flash_emu_handle);
++
++    io_seek(flash0_handle, IO_SEEK_SET,
++            BANK_1_PARTITION_OFFSET + flash0_info->sector_size - 7);
++    io_seek(flash_emu_handle, IO_SEEK_SET, flash_emu_info->sector_size - 7);
++
++    io_write(flash0_handle, test_data, ARRAY_LENGTH(test_data),
++             &bytes_written_count);
++    if (bytes_written_count != ARRAY_LENGTH(test_data)) {
++        LOG_ERRFMT("io_write failed to write %d bytes for flash0",
++                   ARRAY_LENGTH(test_data));
++        LOG_ERRFMT("bytes_written_count %d for flash0", bytes_written_count);
++        ret->val = TEST_FAILED;
++    }
++    io_write(flash_emu_handle, test_data, ARRAY_LENGTH(test_data),
++             &bytes_written_count);
++    if (bytes_written_count != ARRAY_LENGTH(test_data)) {
++        LOG_ERRFMT("io_write failed to write %d bytes for flash emu",
++                   ARRAY_LENGTH(test_data));
++        LOG_ERRFMT("bytes_written_count %d for flash emu", bytes_written_count);
++        ret->val = TEST_FAILED;
++    }
++    io_close(flash0_handle);
++    io_close(flash_emu_handle);
++
++    /* Read Data */
++    io_open(flash0_dev_handle, &flash0_spec, &flash0_handle);
++    io_open(flash_emu_dev_handle, &flash_emu_spec, &flash_emu_handle);
++
++    io_seek(flash0_handle, IO_SEEK_SET,
++            BANK_1_PARTITION_OFFSET + flash0_info->sector_size - 7);
++    io_seek(flash_emu_handle, IO_SEEK_SET, flash_emu_info->sector_size - 7);
++
++    /* Flash0 */
++    io_read(flash0_handle, actual_data, ARRAY_LENGTH(actual_data),
++            &bytes_read_count);
++    if (bytes_read_count != ARRAY_LENGTH(test_data)) {
++        LOG_ERRFMT("io_read failed to read %d bytes for flash0",
++                   ARRAY_LENGTH(test_data));
++        LOG_ERRFMT("bytes_read_count %d for flash0", bytes_read_count);
++        ret->val = TEST_FAILED;
++    }
++    if (memcmp((uint8_t*)test_data, actual_data, ARRAY_LENGTH(actual_data)) !=
++        0) {
++        LOG_ERRFMT("Data written != Data read\r\n");
++        ret->val = TEST_FAILED;
++    }
++
++    memset(actual_data, -1, sizeof(actual_data));
++
++    /* Flash Emu */
++    io_read(flash_emu_handle, actual_data, ARRAY_LENGTH(actual_data),
++            &bytes_read_count);
++    if (bytes_read_count != ARRAY_LENGTH(test_data)) {
++        LOG_ERRFMT("io_read failed to read %d bytes for flash emu",
++                   ARRAY_LENGTH(test_data));
++        LOG_ERRFMT("bytes_read_count %d for flash emu", bytes_read_count);
++        ret->val = TEST_FAILED;
++    }
++    if (memcmp((uint8_t*)test_data, actual_data, ARRAY_LENGTH(actual_data)) !=
++        0) {
++        LOG_ERRFMT("Data written != Data read\r\n");
++        ret->val = TEST_FAILED;
++    }
++
++    LOG_INFFMT("PASS: %s\n\r", __func__);
++    ret->val = TEST_PASSED;
++}
+\ No newline at end of file
+diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.h b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.h
+new file mode 100644
+index 0000000000..fa9012776f
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_io_storage_test.h
+@@ -0,0 +1,15 @@
++/*
++ * Copyright (c) 2022, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef __S_IO_STORAGE_TEST_H__
++#define __S_IO_STORAGE_TEST_H__
++
++#include "extra_s_tests.h"
++
++void s_test_io_storage_multiple_flash_simultaneous(struct test_result_t *ret);
++
++#endif /* __S_IO_STORAGE_TEST_H__ */
+\ No newline at end of file
+diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test.c b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test.c
+index a0bf47a04b..9a8453ff57 100644
+--- a/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test.c
++++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test.c
+@@ -11,6 +11,7 @@
+ #include "platform_base_address.h"
+ #include "firewall.h"
+ #include "tfm_sp_log.h"
++#include "s_io_storage_test.h"
+ 
+ /* TODO: if needed each test function can be made as a separate test case, in
+  * such case EXTRA_TEST_XX definitions can be removed */
+@@ -19,6 +20,8 @@
+ 
+ #define DISABLED_TEST 0
+ 
++int test_io_storage_multiple_flash_simultaneous(void);
++
+ enum host_firewall_host_comp_id_t {
+   HOST_FCTRL = (0x00u),
+   COMP_SYSPERIPH,
+@@ -184,6 +187,8 @@ void s_test(struct test_result_t *ret)
+ static struct test_t plat_s_t[] = {
+     {&s_test, "TFM_S_EXTRA_TEST_1001",
+      "Extra Secure test"},
++    {&s_test_io_storage_multiple_flash_simultaneous, "TFM_S_EXTRA_TEST_1002",
++     "Extra Secure test: io storage access multiple flash simultaneous"},
+ };
+ 
+ void register_testsuite_extra_s_interface(struct test_suite_t *p_test_suite)
+diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test_config.cmake b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test_config.cmake
+index bb8d26bf1c..05b7cd7852 100644
+--- a/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test_config.cmake
++++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/s_test_config.cmake
+@@ -6,3 +6,8 @@
+ #-------------------------------------------------------------------------------
+ 
+ ############ Define secure test specific cmake configurations here #############
++
++set (TEST_FLASH_SIZE_IN_BYTES         48U  CACHE STRING   "The size of the emulated flash used in io tests")
++set (TEST_FLASH_SECTOR_SIZE_IN_BYTES  16U  CACHE STRING   "The sector size of the emulated flash used in io tests")
++set (TEST_FLASH_PAGE_SIZE              8U  CACHE STRING   "The page size of the emulated flash used in io tests")
++set (TEST_FLASH_PROGRAM_UNIT           1U  CACHE STRING   "The program unit of the emulated flash used in io tests")
+diff --git a/platform/ext/target/arm/corstone1000/ci_regression_tests/test_flash.h b/platform/ext/target/arm/corstone1000/ci_regression_tests/test_flash.h
+new file mode 100644
+index 0000000000..4d073a1d71
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/ci_regression_tests/test_flash.h
+@@ -0,0 +1,25 @@
++/*
++ * Copyright (c) 2017-2022 Arm Limited. All rights reserved.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++#ifndef __TEST_FLASH_H__
++#define __TEST_FLASH_H__
++
++#define TEST_FLASH_SIZE_IN_BYTES             (48)    // 48 bytes
++#define TEST_FLASH_SECTOR_SIZE_IN_BYTES      (16)    // 16 bytes
++#define TEST_FLASH_PAGE_SIZE                 (8U)    // 8 bytes
++#define TEST_FLASH_PROGRAM_UNIT              (1U)    /* 1 B */
++
++#endif /* __TEST_FLASH_H__ */
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0003-Platform-corstone1000-Add-soft-crc32-calculation.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0003-Platform-corstone1000-Add-soft-crc32-calculation.patch
new file mode 100644
index 0000000..5983a49
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0003-Platform-corstone1000-Add-soft-crc32-calculation.patch
@@ -0,0 +1,171 @@
+From 2de11bf9de6d0471772c100c72712d2a09c7cefc Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Wed, 21 Dec 2022 14:44:31 +0000
+Subject: [PATCH 3/10] Platform: corstone1000: Add soft crc32 calculation
+
+crc32 is required by different components.
+for example: during bl1 provisioning crc32 calculation is required
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ .../arm/corstone1000/soft_crc/soft_crc.c      | 121 ++++++++++++++++++
+ .../arm/corstone1000/soft_crc/soft_crc.h      |  18 +++
+ 2 files changed, 139 insertions(+)
+ create mode 100644 platform/ext/target/arm/corstone1000/soft_crc/soft_crc.c
+ create mode 100644 platform/ext/target/arm/corstone1000/soft_crc/soft_crc.h
+
+diff --git a/platform/ext/target/arm/corstone1000/soft_crc/soft_crc.c b/platform/ext/target/arm/corstone1000/soft_crc/soft_crc.c
+new file mode 100644
+index 0000000000..85f1e30d9f
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/soft_crc/soft_crc.c
+@@ -0,0 +1,121 @@
++/* Copyright (C) 1986 Gary S. Brown.  You may use this program, or
++   code or tables extracted from it, as desired without restriction.*/
++
++/* First, the polynomial itself and its table of feedback terms.  The  */
++/* polynomial is                                                       */
++/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
++/* Note that we take it "backwards" and put the highest-order term in  */
++/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
++/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
++/* the MSB being 1.                                                    */
++
++/* Note that the usual hardware shift register implementation, which   */
++/* is what we're using (we're merely optimizing it by doing eight-bit  */
++/* chunks at a time) shifts bits into the lowest-order term.  In our   */
++/* implementation, that means shifting towards the right.  Why do we   */
++/* do it this way?  Because the calculated CRC must be transmitted in  */
++/* order from highest-order term to lowest-order term.  UARTs transmit */
++/* characters in order from LSB to MSB.  By storing the CRC this way,  */
++/* we hand it to the UART in the order low-byte to high-byte; the UART */
++/* sends each low-bit to hight-bit; and the result is transmission bit */
++/* by bit from highest- to lowest-order term without requiring any bit */
++/* shuffling on our part.  Reception works similarly.                  */
++
++/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
++/*                                                                     */
++/*  1. The table can be generated at runtime if desired; code to do so */
++/*     is shown later.  It might not be obvious, but the feedback      */
++/*     terms simply represent the results of eight shift/xor opera-    */
++/*     tions for all combinations of data and CRC register values.     */
++/*                                                                     */
++/*  2. The CRC accumulation logic is the same for all CRC polynomials, */
++/*     be they sixteen or thirty-two bits wide.  You simply choose the */
++/*     appropriate table.  Alternatively, because the table can be     */
++/*     generated at runtime, you can start by generating the table for */
++/*     the polynomial in question and use exactly the same "updcrc",   */
++/*     if your application needn't simultaneously handle two CRC       */
++/*     polynomials.  (Note, however, that XMODEM is strange.)          */
++/*                                                                     */
++/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */
++/*     of course, 32-bit entries work OK if the high 16 bits are zero. */
++/*                                                                     */
++/*  4. The values must be right-shifted by eight bits by the "updcrc"  */
++/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
++/*     hardware you could probably optimize the shift in assembler by  */
++/*     using byte-swap instructions.                                   */
++
++/**
++ * The code derived from work by Gary S. Brown.
++*/
++
++#include "soft_crc.h"
++
++
++const static uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
++0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
++0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
++0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
++0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
++0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
++0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
++0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
++0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
++0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
++0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
++0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
++0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
++0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
++0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
++0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
++0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
++0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
++0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
++0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
++0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
++0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
++0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
++0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
++0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
++0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
++0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
++0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
++0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
++0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
++0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
++0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
++0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
++0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
++0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
++0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
++0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
++0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
++0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
++0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
++0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
++0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
++0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
++0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
++};
++
++#define UPDC32(octet,crc) (crc_32_tab[((crc)\
++     ^ ((uint8_t)octet)) & 0xff] ^ ((crc) >> 8))
++
++static inline uint32_t crc32buf(char *buf, size_t len)
++{
++      register uint32_t oldcrc32;
++
++      oldcrc32 = 0xFFFFFFFF;
++
++      for ( ; len; --len, ++buf)
++      {
++            oldcrc32 = UPDC32(*buf, oldcrc32);
++      }
++
++      return ~oldcrc32;
++}
++
++/* Calculate crc32 */
++uint32_t crc32(const void *buf, size_t len) {
++    return crc32buf(buf, len);
++}
++
+diff --git a/platform/ext/target/arm/corstone1000/soft_crc/soft_crc.h b/platform/ext/target/arm/corstone1000/soft_crc/soft_crc.h
+new file mode 100644
+index 0000000000..e5b06075c9
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/soft_crc/soft_crc.h
+@@ -0,0 +1,18 @@
++/*
++ * Copyright (c) 2023, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef __SOFT_CRC_H__
++#define __SOFT_CRC_H__
++
++#include <stddef.h>
++#include <stdint.h>
++
++/* Calculate crc32 */
++uint32_t crc32(const void *buf, size_t len);
++
++#endif /* __SOFT_CRC_H__ */
++
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0004-Platform-corstone1000-calculate-metadata-crc32.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0004-Platform-corstone1000-calculate-metadata-crc32.patch
new file mode 100644
index 0000000..4921e3a
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0004-Platform-corstone1000-calculate-metadata-crc32.patch
@@ -0,0 +1,89 @@
+From 6f8ce3c0f70fecb1e7b990b8b47af16972b90671 Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Wed, 21 Dec 2022 15:13:27 +0000
+Subject: [PATCH 4/10] Platform: corstone1000: calculate metadata crc32
+
+Calculate metadata crc32 during provisioning.
+It is requried to enable TF-A, U-Boot to verify fwu_metadata.
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ platform/ext/target/arm/corstone1000/CMakeLists.txt        | 2 ++
+ platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt    | 2 ++
+ .../target/arm/corstone1000/fw_update_agent/fwu_agent.c    | 7 ++++++-
+ 3 files changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+index 7808efae68..554fc51b21 100644
+--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
++++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+@@ -58,6 +58,7 @@ target_include_directories(platform_s
+     INTERFACE
+         cc312
+         fw_update_agent
++        soft_crc
+ )
+ 
+ target_sources(platform_s
+@@ -185,6 +186,7 @@ target_include_directories(platform_bl2
+         fip_parser
+         Native_Driver
+         fw_update_agent
++        soft_crc
+         io
+         .
+     INTERFACE
+diff --git a/platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt b/platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt
+index 62fd0f6ddf..426a8df698 100644
+--- a/platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt
++++ b/platform/ext/target/arm/corstone1000/bl1/CMakeLists.txt
+@@ -229,6 +229,7 @@ target_include_directories(bl1_main
+         $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/platform/ext/accelerator/cc312>
+         $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/lib/ext/cryptocell-312-runtime/shared/include/mbedtls>
+         $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:${CMAKE_SOURCE_DIR}/lib/ext/cryptocell-312-runtime/shared/include/crypto_api/cc3x>
++        ../soft_crc
+ )
+ 
+ # Configurations based on platform level cmake files
+@@ -241,6 +242,7 @@ target_sources(bl1_main
+         ../Native_Driver/firewall.c
+         ../Native_Driver/uart_pl011_drv.c
+         ../fw_update_agent/fwu_agent.c
++        ../soft_crc/soft_crc.c
+         ../Native_Driver/arm_watchdog_drv.c
+         ../Native_Driver/watchdog.c
+         bl1_boot_hal.c
+diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+index d5491e08db..1a42c72bd5 100644
+--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
++++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited. All rights reserved.
++ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  *
+@@ -20,6 +20,7 @@
+ #include "tfm_plat_defs.h"
+ #include "uefi_fmp.h"
+ #include "uart_stdout.h"
++#include "soft_crc.h"
+ 
+ /* Properties of image in a bank */
+ struct fwu_image_properties {
+@@ -324,6 +325,10 @@ enum fwu_agent_error_t fwu_metadata_provision(void)
+         _metadata.img_entry[i].img_props[BANK_1].version = INVALID_VERSION;
+     }
+ 
++    /* Calculate CRC32 for fwu metadata */
++    _metadata.crc_32 = crc32((uint8_t *)&_metadata.version,
++                             sizeof(struct fwu_metadata) - sizeof(uint32_t));
++
+     ret = metadata_write(&_metadata);
+     if (ret) {
+         return ret;
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0005-Platform-corstone1000-fwu-metadata_read-validate-crc.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0005-Platform-corstone1000-fwu-metadata_read-validate-crc.patch
new file mode 100644
index 0000000..49452b8
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0005-Platform-corstone1000-fwu-metadata_read-validate-crc.patch
@@ -0,0 +1,99 @@
+From 25924b6c0504faae0b0ed680c09fb8996b6aaba6 Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Wed, 21 Dec 2022 15:42:21 +0000
+Subject: [PATCH 5/10] Platform:corstone1000:fwu: metadata_read validate crc
+
+Add validation logic to metadata_read function.
+Also, add metadata_read_without_validation
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ .../target/arm/corstone1000/CMakeLists.txt    |  1 +
+ .../corstone1000/fw_update_agent/fwu_agent.c  | 51 +++++++++++++++++++
+ 2 files changed, 52 insertions(+)
+
+diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+index 554fc51b21..9db2864033 100644
+--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
++++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+@@ -75,6 +75,7 @@ target_sources(platform_s
+         fw_update_agent/uefi_capsule_parser.c
+         fw_update_agent/fwu_agent.c
+         fw_update_agent/uefi_fmp.c
++        soft_crc/soft_crc.c
+         $<$<NOT:$<BOOL:${PLATFORM_DEFAULT_OTP}>>:${PLATFORM_DIR}/ext/accelerator/cc312/otp_cc312.c>
+ )
+ 
+diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+index 1a42c72bd5..eb17c3a377 100644
+--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
++++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+@@ -193,6 +193,53 @@ static enum fwu_agent_error_t private_metadata_write(
+     return FWU_AGENT_SUCCESS;
+ }
+ 
++static enum fwu_agent_error_t metadata_validate(struct fwu_metadata *p_metadata)
++{
++    int ret;
++
++    FWU_LOG_MSG("%s: enter:\n\r", __func__);
++
++    if (!p_metadata) {
++        return FWU_AGENT_ERROR;
++    }
++
++    uint32_t calculated_crc32 = crc32((uint8_t *)&(p_metadata->version),
++                                      sizeof(struct fwu_metadata) - sizeof(uint32_t));
++
++    if (p_metadata->crc_32 != calculated_crc32) {
++        FWU_LOG_MSG("%s: failed: crc32 calculated: 0x%x, given: 0x%x\n\r", __func__,
++                    calculated_crc32, p_metadata->crc_32);
++        return FWU_AGENT_ERROR;
++    }
++
++    FWU_LOG_MSG("%s: success\n\r", __func__);
++
++    return FWU_AGENT_SUCCESS;
++}
++
++static enum fwu_agent_error_t metadata_read_without_validation(struct fwu_metadata *p_metadata)
++{
++    int ret;
++
++    FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__,
++                  FWU_METADATA_REPLICA_1_OFFSET, sizeof(struct fwu_metadata));
++
++    if (!p_metadata) {
++        return FWU_AGENT_ERROR;
++    }
++
++    ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_METADATA_REPLICA_1_OFFSET,
++                                p_metadata, sizeof(struct fwu_metadata));
++    if (ret < 0 || ret != sizeof(struct fwu_metadata)) {
++        return FWU_AGENT_ERROR;
++    }
++
++    FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__,
++                  p_metadata->active_index, p_metadata->previous_active_index);
++
++    return FWU_AGENT_SUCCESS;
++}
++
+ static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata)
+ {
+     int ret;
+@@ -210,6 +257,10 @@ static enum fwu_agent_error_t metadata_read(struct fwu_metadata *p_metadata)
+         return FWU_AGENT_ERROR;
+     }
+ 
++    if (metadata_validate(p_metadata) != FWU_AGENT_SUCCESS) {
++        return FWU_AGENT_ERROR;
++    }
++
+     FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__,
+                   p_metadata->active_index, p_metadata->previous_active_index);
+ 
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0006-Platform-corstone1000-Add-common-platform-logger.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0006-Platform-corstone1000-Add-common-platform-logger.patch
new file mode 100644
index 0000000..a7c17ab
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0006-Platform-corstone1000-Add-common-platform-logger.patch
@@ -0,0 +1,125 @@
+From 9545d9bb44f8fb5af438fb40cab7fefc95d5a9a4 Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Thu, 22 Dec 2022 09:24:50 +0000
+Subject: [PATCH 6/10] Platform:corstone1000: Add common platform logger
+
+platform_log defines log messages macros to be used by the platform code
+It allows defining the module name to be added at the beginning of the log
+message.
+Based on build type PLAT_LOG_LEVEL is defined.
+In case of Debug/RelWithDebInfo PLAT_LOG_LEVEL is defined to Debug level
+else it is defined to OFF.
+
+usage in source file:
+...
+INFO("msg");
+ERROR("msg");
+WARN("msg");
+VERBOSE("msg");
+DBG("msg");
+...
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ .../target/arm/corstone1000/CMakeLists.txt    |  1 +
+ .../ext/target/arm/corstone1000/config.cmake  |  4 +-
+ .../target/arm/corstone1000/platform_log.h    | 60 +++++++++++++++++++
+ 3 files changed, 64 insertions(+), 1 deletion(-)
+ create mode 100644 platform/ext/target/arm/corstone1000/platform_log.h
+
+diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+index 9db2864033..a120f39ea4 100644
+--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
++++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+@@ -152,6 +152,7 @@ target_compile_definitions(platform_bl2
+         $<$<BOOL:${PLATFORM_IS_FVP}>:PLATFORM_IS_FVP>
+         $<$<BOOL:${TFM_S_REG_TEST}>:TFM_S_REG_TEST>
+         $<$<BOOL:${ENABLE_FWU_AGENT_DEBUG_LOGS}>:ENABLE_FWU_AGENT_DEBUG_LOGS>
++        PLAT_LOG_LEVEL=${PLAT_LOG_LEVEL}
+ )
+ 
+ # boot_hal_bl2.c is compiled as part of 'bl2' target and not inside
+diff --git a/platform/ext/target/arm/corstone1000/config.cmake b/platform/ext/target/arm/corstone1000/config.cmake
+index b71ca672f3..de0b4b64c1 100644
+--- a/platform/ext/target/arm/corstone1000/config.cmake
++++ b/platform/ext/target/arm/corstone1000/config.cmake
+@@ -63,6 +63,8 @@ set(TFM_PARTITION_INTERNAL_TRUSTED_STORAGE ON       CACHE BOOL      "Enable Inte
+ 
+ if (${CMAKE_BUILD_TYPE} STREQUAL Debug OR ${CMAKE_BUILD_TYPE} STREQUAL RelWithDebInfo)
+   set(ENABLE_FWU_AGENT_DEBUG_LOGS     TRUE        CACHE BOOL      "Enable Firmware update agent debug logs.")
+-else()
++  set(PLAT_LOG_LEVEL                    4        CACHE STRING     "Set platform log level.")
++  else()
+   set(ENABLE_FWU_AGENT_DEBUG_LOGS     FALSE        CACHE BOOL     "Enable Firmware update agent debug logs.")
++  set(PLAT_LOG_LEVEL                    0        CACHE STRING     "Set platform log level.")
+ endif()
+diff --git a/platform/ext/target/arm/corstone1000/platform_log.h b/platform/ext/target/arm/corstone1000/platform_log.h
+new file mode 100644
+index 0000000000..b3a6e98026
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/platform_log.h
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (c) 2023, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef __PLATFORM_LOG_H__
++#define __PLATFORM_LOG_H__
++
++#define PLAT_LOG_LEVEL_OFF       (0)
++#define PLAT_LOG_LEVEL_ERROR     (1)
++#define PLAT_LOG_LEVEL_WARN      (2)
++#define PLAT_LOG_LEVEL_INFO      (3)
++#define PLAT_LOG_LEVEL_DEBUG     (4)
++
++#ifndef PLAT_LOG_MODULE_NAME
++#define MODULE_NAME_STR " "
++#else
++#define MODULE_NAME_STR "["PLAT_LOG_MODULE_NAME"]: "
++#endif
++
++#ifndef PLAT_LOG_LEVEL
++#warning "Logging level is not defined, default is PLAT_LOG_LEVEL_ERROR."
++#define PLAT_LOG_LEVEL   PLAT_LOG_LEVEL_ERROR
++#endif
++
++
++/* System can override PRINTF with other rich format function*/
++#ifndef PRINTF
++#if PLAT_LOG_LEVEL > PLAT_LOG_LEVEL_OFF
++#include <stdio.h>
++#define PRINTF printf
++#endif
++#endif
++
++#if PLAT_LOG_LEVEL >= PLAT_LOG_LEVEL_ERROR
++    #define ERROR(f_, ...) do { PRINTF("\033[31;4m[ERR]:\033[m%s"f_"\r\n", MODULE_NAME_STR, ##__VA_ARGS__);  } while (0)
++#else
++    #define ERROR(f_, ...) do {  } while(0)
++#endif
++#if PLAT_LOG_LEVEL >= PLAT_LOG_LEVEL_WARN
++    #define WARN(f_, ...) do { PRINTF("\033[33;4m[WRN]:\033[m%s"f_"\r\n", MODULE_NAME_STR, ##__VA_ARGS__);  } while (0)
++#else
++    #define WARN(f_, ...) do {  } while(0)
++#endif
++#if PLAT_LOG_LEVEL >= PLAT_LOG_LEVEL_INFO
++    #define INFO(f_, ...) do { PRINTF("[INF]:%s"f_"\r\n", MODULE_NAME_STR, ##__VA_ARGS__);  } while (0)
++#else
++    #define INFO(f_, ...) do {  } while(0)
++#endif
++#if PLAT_LOG_LEVEL >= PLAT_LOG_LEVEL_DEBUG
++    #define VERBOSE(f_, ...) do { PRINTF("[DBG]:%s" f_"\r\n",MODULE_NAME_STR, ##__VA_ARGS__);  } while (0)
++    #define DEBUG(f_, ...) do { PRINTF("[DBG]:%s" f_"\r\n",MODULE_NAME_STR, ##__VA_ARGS__);  } while (0)
++#else
++    #define VERBOSE(f_, ...) do {  } while(0)
++    #define DEBUG(f_, ...) do {  } while(0)
++#endif
++
++#endif /* __PLATFORM_LOG_H__ */
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Platform-corstone1000-Introduce-GPT-parser.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Platform-corstone1000-Introduce-GPT-parser.patch
new file mode 100644
index 0000000..418c533
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0007-Platform-corstone1000-Introduce-GPT-parser.patch
@@ -0,0 +1,735 @@
+From 1fdc3000f1ab6f9c1bb792cb8baff16a7517c03a Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Thu, 22 Dec 2022 14:27:41 +0000
+Subject: [PATCH 7/10] Platform:corstone1000: Introduce GPT parser
+
+Adding GPT parser
+Side changes required:
+Includes the implementation of the `plat_get_image_source` function
+in the platform.c file.
+
+The GPT parser requires the function. Given the image id, it should
+return handle to the IO device contains the image and image
+specification that allows IO storage access to the image.
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ .../target/arm/corstone1000/partition/efi.h   |  36 ++
+ .../target/arm/corstone1000/partition/gpt.c   |  58 ++++
+ .../target/arm/corstone1000/partition/gpt.h   |  51 +++
+ .../target/arm/corstone1000/partition/mbr.h   |  29 ++
+ .../arm/corstone1000/partition/partition.c    | 310 ++++++++++++++++++
+ .../arm/corstone1000/partition/partition.h    |  47 +++
+ .../target/arm/corstone1000/partition/uuid.h  |  76 +++++
+ .../ext/target/arm/corstone1000/platform.c    |  20 ++
+ .../ext/target/arm/corstone1000/platform.h    |  14 +
+ 9 files changed, 641 insertions(+)
+ create mode 100644 platform/ext/target/arm/corstone1000/partition/efi.h
+ create mode 100644 platform/ext/target/arm/corstone1000/partition/gpt.c
+ create mode 100644 platform/ext/target/arm/corstone1000/partition/gpt.h
+ create mode 100644 platform/ext/target/arm/corstone1000/partition/mbr.h
+ create mode 100644 platform/ext/target/arm/corstone1000/partition/partition.c
+ create mode 100644 platform/ext/target/arm/corstone1000/partition/partition.h
+ create mode 100644 platform/ext/target/arm/corstone1000/partition/uuid.h
+ create mode 100644 platform/ext/target/arm/corstone1000/platform.c
+ create mode 100644 platform/ext/target/arm/corstone1000/platform.h
+
+diff --git a/platform/ext/target/arm/corstone1000/partition/efi.h b/platform/ext/target/arm/corstone1000/partition/efi.h
+new file mode 100644
+index 0000000000..f66daffb32
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/partition/efi.h
+@@ -0,0 +1,36 @@
++/*
++ * Copyright (c) 2021, Linaro Limited
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef DRIVERS_PARTITION_EFI_H
++#define DRIVERS_PARTITION_EFI_H
++
++#include <string.h>
++
++#include "uuid.h"
++
++#define EFI_NAMELEN 36
++
++static inline int guidcmp(const void *g1, const void *g2) {
++    return memcmp(g1, g2, sizeof(struct efi_guid));
++}
++
++static inline void *guidcpy(void *dst, const void *src) {
++    return memcpy(dst, src, sizeof(struct efi_guid));
++}
++
++#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7)  \
++    {                                                      \
++        (a) & 0xffffffff, (b)&0xffff, (c)&0xffff, {        \
++            (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) \
++        }                                                  \
++    }
++
++#define NULL_GUID                                                            \
++    EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
++             0x00, 0x00)
++
++#endif /* DRIVERS_PARTITION_EFI_H */
+diff --git a/platform/ext/target/arm/corstone1000/partition/gpt.c b/platform/ext/target/arm/corstone1000/partition/gpt.c
+new file mode 100644
+index 0000000000..8549785e3b
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/partition/gpt.c
+@@ -0,0 +1,58 @@
++/*
++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include "gpt.h"
++
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++
++#include "efi.h"
++
++static int unicode_to_ascii(unsigned short *str_in, unsigned char *str_out) {
++    uint8_t *name;
++    int i;
++
++    assert((str_in != NULL) && (str_out != NULL));
++
++    name = (uint8_t *)str_in;
++
++    assert(name[0] != '\0');
++
++    /* check whether the unicode string is valid */
++    for (i = 1; i < (EFI_NAMELEN << 1); i += 2) {
++        if (name[i] != '\0') return -EINVAL;
++    }
++    /* convert the unicode string to ascii string */
++    for (i = 0; i < (EFI_NAMELEN << 1); i += 2) {
++        str_out[i >> 1] = name[i];
++        if (name[i] == '\0') break;
++    }
++    return 0;
++}
++
++int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry) {
++    int result;
++
++    assert((gpt_entry != NULL) && (entry != NULL));
++
++    if ((gpt_entry->first_lba == 0) && (gpt_entry->last_lba == 0)) {
++        return -EINVAL;
++    }
++
++    memset(entry, 0, sizeof(partition_entry_t));
++    result = unicode_to_ascii(gpt_entry->name, (uint8_t *)entry->name);
++    if (result != 0) {
++        return result;
++    }
++    entry->start = (uint64_t)gpt_entry->first_lba * PLAT_PARTITION_BLOCK_SIZE;
++    entry->length = (uint64_t)(gpt_entry->last_lba - gpt_entry->first_lba + 1) *
++                    PLAT_PARTITION_BLOCK_SIZE;
++    guidcpy(&entry->part_guid, &gpt_entry->unique_uuid);
++    guidcpy(&entry->type_guid, &gpt_entry->type_uuid);
++
++    return 0;
++}
+diff --git a/platform/ext/target/arm/corstone1000/partition/gpt.h b/platform/ext/target/arm/corstone1000/partition/gpt.h
+new file mode 100644
+index 0000000000..b528fc05c0
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/partition/gpt.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef GPT_H
++#define GPT_H
++
++#include "efi.h"
++#include "partition.h"
++#include "uuid.h"
++
++#define PARTITION_TYPE_GPT 0xee
++#define GPT_HEADER_OFFSET PLAT_PARTITION_BLOCK_SIZE
++#define GPT_ENTRY_OFFSET (GPT_HEADER_OFFSET + PLAT_PARTITION_BLOCK_SIZE)
++
++#define GPT_SIGNATURE "EFI PART"
++
++typedef struct gpt_entry {
++    struct efi_guid type_uuid;
++    struct efi_guid unique_uuid;
++    unsigned long long first_lba;
++    unsigned long long last_lba;
++    unsigned long long attr;
++    unsigned short name[EFI_NAMELEN];
++} gpt_entry_t;
++
++typedef struct gpt_header {
++    unsigned char signature[8];
++    unsigned int revision;
++    unsigned int size;
++    unsigned int header_crc;
++    unsigned int reserved;
++    unsigned long long current_lba;
++    unsigned long long backup_lba;
++    unsigned long long first_lba;
++    unsigned long long last_lba;
++    struct efi_guid disk_uuid;
++    /* starting LBA of array of partition entries */
++    unsigned long long part_lba;
++    /* number of partition entries in array */
++    unsigned int list_num;
++    /* size of a single partition entry (usually 128) */
++    unsigned int part_size;
++    unsigned int part_crc;
++} gpt_header_t;
++
++int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry);
++
++#endif /* GPT_H */
+diff --git a/platform/ext/target/arm/corstone1000/partition/mbr.h b/platform/ext/target/arm/corstone1000/partition/mbr.h
+new file mode 100644
+index 0000000000..e77f367016
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/partition/mbr.h
+@@ -0,0 +1,29 @@
++/*
++ * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef MBR_H
++#define MBR_H
++
++#define MBR_OFFSET 0
++
++#define MBR_PRIMARY_ENTRY_OFFSET 0x1be
++#define MBR_PRIMARY_ENTRY_SIZE 0x10
++#define MBR_PRIMARY_ENTRY_NUMBER 4
++#define MBR_CHS_ADDRESS_LEN 3
++
++#define MBR_SIGNATURE_FIRST 0x55
++#define MBR_SIGNATURE_SECOND 0xAA
++
++typedef struct mbr_entry {
++    unsigned char status;
++    unsigned char first_sector[MBR_CHS_ADDRESS_LEN];
++    unsigned char type;
++    unsigned char last_sector[MBR_CHS_ADDRESS_LEN];
++    unsigned int first_lba;
++    unsigned int sector_nums;
++} mbr_entry_t;
++
++#endif /* MBR_H */
+diff --git a/platform/ext/target/arm/corstone1000/partition/partition.c b/platform/ext/target/arm/corstone1000/partition/partition.c
+new file mode 100644
+index 0000000000..afc6aa1c5c
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/partition/partition.c
+@@ -0,0 +1,310 @@
++/*
++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include "partition.h"
++
++#include <assert.h>
++#include <errno.h>
++#include <inttypes.h>
++#include <stdio.h>
++#include <string.h>
++
++#include "efi.h"
++#include "gpt.h"
++#include "mbr.h"
++
++#include "io_storage.h"
++#include "platform.h"
++#include "soft_crc.h"
++
++#define PLAT_LOG_MODULE_NAME "partition"
++#include "platform_log.h"
++
++static uint8_t mbr_sector[PLAT_PARTITION_BLOCK_SIZE];
++static partition_entry_list_t list;
++
++#if LOG_LEVEL >= LOG_LEVEL_DEBUG
++static void dump_entries(int num) {
++    char name[EFI_NAMELEN];
++    int i, j, len;
++
++    VERBOSE("Partition table with %d entries:", num);
++    for (i = 0; i < num; i++) {
++        len = snprintf(name, EFI_NAMELEN, "%s", list.list[i].name);
++        for (j = 0; j < EFI_NAMELEN - len - 1; j++) {
++            name[len + j] = ' ';
++        }
++        name[EFI_NAMELEN - 1] = '\0';
++        VERBOSE("%d: %s %x%x %d", i + 1, name,
++                (uint32_t)(list.list[i].start >> 32),
++                (uint32_t)list.list[i].start,
++                (uint32_t)(list.list[i].start + list.list[i].length - 4));
++    }
++}
++#else
++#define dump_entries(num) ((void)num)
++#endif
++
++/*
++ * Load the first sector that carries MBR header.
++ * The MBR boot signature should be always valid whether it's MBR or GPT.
++ */
++static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) {
++    size_t bytes_read;
++    uintptr_t offset;
++    int result;
++
++    assert(mbr_entry != NULL);
++    /* MBR partition table is in LBA0. */
++    result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET);
++    if (result != 0) {
++        WARN("Failed to seek (%i)\n", result);
++        return result;
++    }
++    result = io_read(image_handle, (uintptr_t)&mbr_sector,
++                     PLAT_PARTITION_BLOCK_SIZE, &bytes_read);
++    if (result != 0) {
++        WARN("Failed to read data (%i)\n", result);
++        return result;
++    }
++
++    /* Check MBR boot signature. */
++    if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) ||
++        (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) {
++        ERROR("MBR signature isn't correct");
++        return -ENOENT;
++    }
++    offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET;
++    memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t));
++    return 0;
++}
++
++/*
++ * Load GPT header and check the GPT signature and header CRC.
++ * If partition numbers could be found, check & update it.
++ */
++static int load_gpt_header(uintptr_t image_handle) {
++    gpt_header_t header;
++    size_t bytes_read;
++    int result;
++    uint32_t header_crc, calc_crc;
++
++    result = io_seek(image_handle, IO_SEEK_SET, GPT_HEADER_OFFSET);
++    if (result != 0) {
++        return result;
++    }
++    result = io_read(image_handle, (uintptr_t)&header, sizeof(gpt_header_t),
++                     &bytes_read);
++    if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) {
++        return result;
++    }
++    if (memcmp(header.signature, GPT_SIGNATURE, sizeof(header.signature)) !=
++        0) {
++        return -EINVAL;
++    }
++
++    /*
++     * UEFI Spec 2.8 March 2019 Page 119: HeaderCRC32 value is
++     * computed by setting this field to 0, and computing the
++     * 32-bit CRC for HeaderSize bytes.
++     */
++    header_crc = header.header_crc;
++    header.header_crc = 0U;
++
++    calc_crc = crc32((uint8_t *)&header, DEFAULT_GPT_HEADER_SIZE);
++    if (header_crc != calc_crc) {
++        ERROR("Invalid GPT Header CRC: Expected 0x%x but got 0x%x.\n",
++              header_crc, calc_crc);
++        return -EINVAL;
++    }
++
++    header.header_crc = header_crc;
++
++    /* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */
++    list.entry_count = header.list_num;
++    if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) {
++        list.entry_count = PLAT_PARTITION_MAX_ENTRIES;
++    }
++    return 0;
++}
++
++static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry,
++                          int part_number) {
++    size_t bytes_read;
++    uintptr_t offset;
++    int result;
++
++    assert(mbr_entry != NULL);
++    /* MBR partition table is in LBA0. */
++    result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET);
++    if (result != 0) {
++        WARN("Failed to seek (%i)\n", result);
++        return result;
++    }
++    result = io_read(image_handle, (uintptr_t)&mbr_sector,
++                     PLAT_PARTITION_BLOCK_SIZE, &bytes_read);
++    if (result != 0) {
++        WARN("Failed to read data (%i)\n", result);
++        return result;
++    }
++
++    /* Check MBR boot signature. */
++    if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) ||
++        (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) {
++        return -ENOENT;
++    }
++    offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET +
++             MBR_PRIMARY_ENTRY_SIZE * part_number;
++    memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t));
++
++    return 0;
++}
++
++static int load_mbr_entries(uintptr_t image_handle) {
++    mbr_entry_t mbr_entry;
++    int i;
++
++    list.entry_count = MBR_PRIMARY_ENTRY_NUMBER;
++
++    for (i = 0; i < list.entry_count; i++) {
++        load_mbr_entry(image_handle, &mbr_entry, i);
++        list.list[i].start = mbr_entry.first_lba * 512;
++        list.list[i].length = mbr_entry.sector_nums * 512;
++        list.list[i].name[0] = mbr_entry.type;
++    }
++
++    return 0;
++}
++
++static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry) {
++    size_t bytes_read;
++    int result;
++
++    assert(entry != NULL);
++    result = io_read(image_handle, (uintptr_t)entry, sizeof(gpt_entry_t),
++                     &bytes_read);
++    if (sizeof(gpt_entry_t) != bytes_read) return -EINVAL;
++    return result;
++}
++
++static int verify_partition_gpt(uintptr_t image_handle) {
++    gpt_entry_t entry;
++    int result, i;
++
++    for (i = 0; i < list.entry_count; i++) {
++        result = load_gpt_entry(image_handle, &entry);
++        assert(result == 0);
++        if (result != 0) {
++            break;
++        }
++        result = parse_gpt_entry(&entry, &list.list[i]);
++        if (result != 0) {
++            break;
++        }
++    }
++    if (i == 0) {
++        return -EINVAL;
++    }
++    /*
++     * Only records the valid partition number that is loaded from
++     * partition table.
++     */
++    list.entry_count = i;
++    dump_entries(list.entry_count);
++
++    return 0;
++}
++
++int load_partition_table(unsigned int image_id) {
++    uintptr_t dev_handle, image_handle, image_spec = 0;
++    mbr_entry_t mbr_entry;
++    int result;
++
++    result = plat_get_image_source(image_id, &dev_handle, &image_spec);
++    if (result != 0) {
++        WARN("Failed to obtain reference to image id=%u (%i)\n", image_id,
++             result);
++        return result;
++    }
++
++    result = io_open(dev_handle, image_spec, &image_handle);
++    if (result != 0) {
++        WARN("Failed to open image id=%u (%i)\n", image_id, result);
++        return result;
++    }
++
++    result = load_mbr_header(image_handle, &mbr_entry);
++    if (result != 0) {
++        ERROR("Loading mbr header failed with image id=%u (%i)\n", image_id,
++              result);
++        return result;
++    }
++    if (mbr_entry.type == PARTITION_TYPE_GPT) {
++        INFO("Loading gpt header");
++        result = load_gpt_header(image_handle);
++        assert(result == 0);
++        if (result != 0) {
++            ERROR("Failed load gpt header! %i", result);
++            goto load_partition_table_exit;
++        }
++        result = io_seek(image_handle, IO_SEEK_SET, GPT_ENTRY_OFFSET);
++        assert(result == 0);
++        if (result != 0) {
++            ERROR("Failed seek gpt header! %i", result);
++            goto load_partition_table_exit;
++        }
++        result = verify_partition_gpt(image_handle);
++        if (result != 0) {
++            ERROR("Failed verify gpt partition %i", result);
++            goto load_partition_table_exit;
++        }
++    } else {
++        result = load_mbr_entries(image_handle);
++    }
++
++load_partition_table_exit:
++    io_close(image_handle);
++    return result;
++}
++
++const partition_entry_t *get_partition_entry(const char *name) {
++    int i;
++
++    for (i = 0; i < list.entry_count; i++) {
++        if (strcmp(name, list.list[i].name) == 0) {
++            return &list.list[i];
++        }
++    }
++    return NULL;
++}
++
++const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_uuid) {
++    int i;
++
++    for (i = 0; i < list.entry_count; i++) {
++        if (guidcmp(type_uuid, &list.list[i].type_guid) == 0) {
++            return &list.list[i];
++        }
++    }
++
++    return NULL;
++}
++
++const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid) {
++    int i;
++
++    for (i = 0; i < list.entry_count; i++) {
++        if (guidcmp(part_uuid, &list.list[i].part_guid) == 0) {
++            return &list.list[i];
++        }
++    }
++
++    return NULL;
++}
++
++const partition_entry_list_t *get_partition_entry_list(void) { return &list; }
++
++void partition_init(unsigned int image_id) { load_partition_table(image_id); }
+diff --git a/platform/ext/target/arm/corstone1000/partition/partition.h b/platform/ext/target/arm/corstone1000/partition/partition.h
+new file mode 100644
+index 0000000000..54af47aca4
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/partition/partition.h
+@@ -0,0 +1,47 @@
++/*
++ * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PARTITION_H
++#define PARTITION_H
++
++#include <stdint.h>
++
++#include "efi.h"
++#include "uuid.h"
++
++#if !PLAT_PARTITION_MAX_ENTRIES
++#define PLAT_PARTITION_MAX_ENTRIES 16
++#endif /* PLAT_PARTITION_MAX_ENTRIES */
++
++#if !PLAT_PARTITION_BLOCK_SIZE
++#define PLAT_PARTITION_BLOCK_SIZE 512
++#endif /* PLAT_PARTITION_BLOCK_SIZE */
++
++#define LEGACY_PARTITION_BLOCK_SIZE 512
++
++#define DEFAULT_GPT_HEADER_SIZE 92
++
++typedef struct partition_entry {
++    uint64_t start;
++    uint64_t length;
++    char name[EFI_NAMELEN];
++    struct efi_guid part_guid;
++    struct efi_guid type_guid;
++} partition_entry_t;
++
++typedef struct partition_entry_list {
++    partition_entry_t list[PLAT_PARTITION_MAX_ENTRIES];
++    int entry_count;
++} partition_entry_list_t;
++
++int load_partition_table(unsigned int image_id);
++const partition_entry_t *get_partition_entry(const char *name);
++const partition_entry_t *get_partition_entry_by_type(const uuid_t *type_guid);
++const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid);
++const partition_entry_list_t *get_partition_entry_list(void);
++void partition_init(unsigned int image_id);
++
++#endif /* PARTITION_H */
+diff --git a/platform/ext/target/arm/corstone1000/partition/uuid.h b/platform/ext/target/arm/corstone1000/partition/uuid.h
+new file mode 100644
+index 0000000000..06fec5a3c0
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/partition/uuid.h
+@@ -0,0 +1,76 @@
++/*-
++ * Copyright (c) 2002 Marcel Moolenaar
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions
++ * are met:
++ *
++ * 1. Redistributions of source code must retain the above copyright
++ *    notice, this list of conditions and the following disclaimer.
++ * 2. Redistributions in binary form must reproduce the above copyright
++ *    notice, this list of conditions and the following disclaimer in the
++ *    documentation and/or other materials provided with the distribution.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
++ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++ *
++ * $FreeBSD$
++ */
++
++/*
++ * Portions copyright (c) 2014-2020, ARM Limited and Contributors.
++ * All rights reserved.
++ */
++
++#ifndef UUID_H
++#define UUID_H
++
++#include <stdint.h>
++
++/* Length of a node address (an IEEE 802 address). */
++#define _UUID_NODE_LEN 6
++
++/* Length of UUID string including dashes. */
++#define _UUID_STR_LEN 36
++
++/*
++ * See also:
++ *      http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
++ *      http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
++ *
++ * A DCE 1.1 compatible source representation of UUIDs.
++ */
++struct uuid {
++    uint8_t time_low[4];
++    uint8_t time_mid[2];
++    uint8_t time_hi_and_version[2];
++    uint8_t clock_seq_hi_and_reserved;
++    uint8_t clock_seq_low;
++    uint8_t node[_UUID_NODE_LEN];
++};
++
++struct efi_guid {
++    uint32_t time_low;
++    uint16_t time_mid;
++    uint16_t time_hi_and_version;
++    uint8_t clock_seq_and_node[8];
++};
++
++union uuid_helper_t {
++    struct uuid uuid_struct;
++    struct efi_guid efi_guid;
++};
++
++/* XXX namespace pollution? */
++typedef struct uuid uuid_t;
++
++#endif /* UUID_H */
+diff --git a/platform/ext/target/arm/corstone1000/platform.c b/platform/ext/target/arm/corstone1000/platform.c
+new file mode 100644
+index 0000000000..908b66b7ac
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/platform.c
+@@ -0,0 +1,20 @@
++/*
++ * Copyright (c) 2023, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#include "platform.h"
++
++#include <stdint.h>
++
++/* Return an IO device handle and specification which can be used to access
++ * an image. This has to be implemented for the GPT parser. */
++int32_t plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
++                              uintptr_t *image_spec) {
++    (void)image_id;
++    *dev_handle = NULL;
++    *image_spec = NULL;
++    return 0;
++}
+diff --git a/platform/ext/target/arm/corstone1000/platform.h b/platform/ext/target/arm/corstone1000/platform.h
+new file mode 100644
+index 0000000000..250f9cd9f5
+--- /dev/null
++++ b/platform/ext/target/arm/corstone1000/platform.h
+@@ -0,0 +1,14 @@
++/*
++ * Copyright (c) 2023, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef __PLATFORM_H__
++#define __PLATFORM_H__
++
++int32_t plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
++                              uintptr_t *image_spec);
++
++#endif /*__PLATFORM_H__*/
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0008-Platform-corstone1000-BL1-changes-to-adapt-to-new-fl.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0008-Platform-corstone1000-BL1-changes-to-adapt-to-new-fl.patch
new file mode 100644
index 0000000..d9143a0
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0008-Platform-corstone1000-BL1-changes-to-adapt-to-new-fl.patch
@@ -0,0 +1,337 @@
+From f70bbd0d8efefcc69916fc0393bc413fb39924af Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Tue, 10 Jan 2023 22:33:26 +0000
+Subject: [PATCH 8/10] Platform: corstone1000: BL1 changes to adapt to new flash
+ layout
+
+The commit prepares BL1 to adapt to new GPT-based flash layout.
+
+BL1 does not incorporate a GPT parser and still uses a static
+configuration to understand the flash.
+
+The flash_layout.h is also modified/marked in a way to start
+the process of its simplification.
+
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ .../arm/corstone1000/bl1/bl1_boot_hal.c       | 10 +--
+ .../arm/corstone1000/bl1/bl1_flash_map.c      | 17 ++--
+ .../target/arm/corstone1000/bl2_flash_map.c   |  8 +-
+ .../corstone1000/fw_update_agent/fwu_agent.c  | 16 ++--
+ .../corstone1000/fw_update_agent/fwu_agent.h  |  4 +-
+ .../arm/corstone1000/partition/flash_layout.h | 84 +++++++++----------
+ 6 files changed, 66 insertions(+), 73 deletions(-)
+
+diff --git a/platform/ext/target/arm/corstone1000/bl1/bl1_boot_hal.c b/platform/ext/target/arm/corstone1000/bl1/bl1_boot_hal.c
+index 9caa26b26c..a5fe0f7da1 100644
+--- a/platform/ext/target/arm/corstone1000/bl1/bl1_boot_hal.c
++++ b/platform/ext/target/arm/corstone1000/bl1/bl1_boot_hal.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
++ * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  *
+@@ -601,12 +601,12 @@ __attribute__((naked)) void boot_clear_bl2_ram_area(void)
+     );
+ }
+ 
+-extern void add_bank_offset_to_image_offset(uint32_t bank_offset);
++extern void set_flash_area_image_offset(uint32_t offset);
+ 
+ int32_t boot_platform_init(void)
+ {
+     int32_t result;
+-    uint32_t bank_offset;
++    uint32_t image_offset;
+ 
+     result = corstone1000_watchdog_init();
+     if (result != ARM_DRIVER_OK) {
+@@ -653,8 +653,8 @@ int32_t boot_platform_init(void)
+         }
+     }
+ 
+-    bl1_get_boot_bank(&bank_offset);
+-    add_bank_offset_to_image_offset(bank_offset);
++    bl1_get_active_bl2_image(&image_offset);
++    set_flash_area_image_offset(image_offset);
+ 
+     return 0;
+ }
+diff --git a/platform/ext/target/arm/corstone1000/bl1/bl1_flash_map.c b/platform/ext/target/arm/corstone1000/bl1/bl1_flash_map.c
+index c8a1f13319..0e615da254 100644
+--- a/platform/ext/target/arm/corstone1000/bl1/bl1_flash_map.c
++++ b/platform/ext/target/arm/corstone1000/bl1/bl1_flash_map.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
++ * Copyright (c) 2019-2021, 2023 Arm Limited. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  *
+@@ -22,23 +22,22 @@ struct flash_area flash_map[] = {
+         .fa_id = FLASH_AREA_8_ID,
+         .fa_device_id = FLASH_DEVICE_ID,
+         .fa_driver = &FLASH_DEV_NAME,
+-        .fa_off = FLASH_AREA_8_OFFSET,
++        .fa_off = FLASH_INVALID_OFFSET,
+         .fa_size = FLASH_AREA_8_SIZE,
+     },
++    /* Secondary slot is not supported */
+     {
+-        .fa_id = FLASH_AREA_9_ID,
++        .fa_id = FLASH_INVALID_ID,
+         .fa_device_id = FLASH_DEVICE_ID,
+         .fa_driver = &FLASH_DEV_NAME,
+-        .fa_off = FLASH_AREA_9_OFFSET,
+-        .fa_size = FLASH_AREA_9_SIZE,
++        .fa_off = FLASH_INVALID_OFFSET,
++        .fa_size = FLASH_INVALID_SIZE,
+     },
+ };
+ 
+ const int flash_map_entry_num = ARRAY_SIZE(flash_map);
+ 
+-void add_bank_offset_to_image_offset(uint32_t bank_offset)
++void set_flash_area_image_offset(uint32_t offset)
+ {
+-    for (int i = 0; i < flash_map_entry_num; i++) {
+-        flash_map[i].fa_off += bank_offset;
+-    }
++    flash_map[0].fa_off = offset;
+ }
+diff --git a/platform/ext/target/arm/corstone1000/bl2_flash_map.c b/platform/ext/target/arm/corstone1000/bl2_flash_map.c
+index 0a6a592d94..f512045a44 100644
+--- a/platform/ext/target/arm/corstone1000/bl2_flash_map.c
++++ b/platform/ext/target/arm/corstone1000/bl2_flash_map.c
+@@ -28,15 +28,15 @@ struct flash_area flash_map[] = {
+         .fa_id = FLASH_AREA_0_ID,
+         .fa_device_id = FLASH_DEVICE_ID,
+         .fa_driver = &FLASH_DEV_NAME,
+-        .fa_off = FLASH_AREA_0_OFFSET,
+-        .fa_size = FLASH_AREA_0_SIZE,
++        .fa_off = FLASH_INVALID_OFFSET,
++        .fa_size = FLASH_INVALID_SIZE,
+     },
+     {
+         .fa_id = FLASH_AREA_1_ID,
+         .fa_device_id = FLASH_DEVICE_ID,
+         .fa_driver = &FLASH_DEV_NAME,
+-        .fa_off = FLASH_AREA_1_OFFSET,
+-        .fa_size = FLASH_AREA_1_SIZE,
++        .fa_off = FLASH_INVALID_OFFSET,
++        .fa_size = FLASH_INVALID_SIZE,
+     },
+ #ifndef TFM_S_REG_TEST
+     {
+diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+index eb17c3a377..e4f9da1ec3 100644
+--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
++++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+@@ -154,7 +154,7 @@ static enum fwu_agent_error_t private_metadata_read(
+         return FWU_AGENT_ERROR;
+     }
+ 
+-    ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_PRIVATE_AREA_OFFSET, p_metadata,
++    ret = FWU_METADATA_FLASH_DEV.ReadData(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET, p_metadata,
+                                           sizeof(struct fwu_private_metadata));
+     if (ret < 0 || ret != sizeof(struct fwu_private_metadata)) {
+         return FWU_AGENT_ERROR;
+@@ -178,12 +178,12 @@ static enum fwu_agent_error_t private_metadata_write(
+         return FWU_AGENT_ERROR;
+     }
+ 
+-    ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_PRIVATE_AREA_OFFSET);
++    ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET);
+     if (ret != ARM_DRIVER_OK) {
+         return FWU_AGENT_ERROR;
+     }
+ 
+-    ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_PRIVATE_AREA_OFFSET,
++    ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_PRIVATE_METADATA_REPLICA_1_OFFSET,
+                                 p_metadata, sizeof(struct fwu_private_metadata));
+     if (ret < 0 || ret != sizeof(struct fwu_private_metadata)) {
+         return FWU_AGENT_ERROR;
+@@ -769,7 +769,7 @@ static enum fwu_agent_error_t fwu_select_previous(
+ 
+ }
+ 
+-void bl1_get_boot_bank(uint32_t *bank_offset)
++void bl1_get_active_bl2_image(uint32_t *offset)
+ {
+     struct fwu_private_metadata priv_metadata;
+     enum fwu_agent_state_t current_state;
+@@ -823,15 +823,15 @@ void bl1_get_boot_bank(uint32_t *bank_offset)
+     }
+ 
+     if (boot_index == BANK_0) {
+-        *bank_offset = BANK_0_PARTITION_OFFSET;
++        *offset = SE_BL2_BANK_0_OFFSET;
+     } else if (boot_index == BANK_1) {
+-        *bank_offset = BANK_1_PARTITION_OFFSET;
++        *offset = SE_BL2_BANK_1_OFFSET;
+     } else {
+         FWU_ASSERT(0);
+     }
+ 
+-    FWU_LOG_MSG("%s: exit: booting from bank = %u, offset = %x\n\r", __func__,
+-                        boot_index, *bank_offset);
++    FWU_LOG_MSG("%s: exit: booting from bank = %u, offset = 0x%x\n\r", __func__,
++                        boot_index, *offset);
+ 
+     return;
+ }
+diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h
+index 00a08354be..eb8320ed8a 100644
+--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h
++++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited. All rights reserved.
++ * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  *
+@@ -44,7 +44,7 @@ enum fwu_agent_error_t corstone1000_fwu_flash_image(void);
+  */
+ enum fwu_agent_error_t corstone1000_fwu_host_ack(void);
+ 
+-void bl1_get_boot_bank(uint32_t *bank_offset);
++void bl1_get_active_bl2_image(uint32_t *bank_offset);
+ void bl2_get_boot_bank(uint32_t *bank_offset);
+ 
+ /* When in trial state, start the timer for host to respond.
+diff --git a/platform/ext/target/arm/corstone1000/partition/flash_layout.h b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
+index 5970a13c12..347c91acbb 100644
+--- a/platform/ext/target/arm/corstone1000/partition/flash_layout.h
++++ b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2017-2022 Arm Limited. All rights reserved.
++ * Copyright (c) 2017-2023 Arm Limited. All rights reserved.
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+@@ -98,56 +98,56 @@
+ 
+ #endif
+ 
+-/* Flash layout (32MB) :-
+- *
+- * 1 MB     : FWU_METADATA_PARTITION_SIZE
+- * 15.5 MB  : BANK 1 PARTITION SIZE
+- * 15.5 MB  : BANK 2 PARTITION SIZE
+- *
+- */
+-#define FWU_METADATA_PARTITION_SIZE     (0x100000)   /* 1MB */
+-#define BANK_PARTITION_SIZE             (0xF80000)   /* 15.5 MB */
++/* Static Configurations of the Flash */
++#define SE_BL2_PARTITION_SIZE           (0x18800)    /* 98 KB */
++#define SE_BL2_BANK_0_OFFSET            (0x9000)  /* 72nd LBA */
++#define SE_BL2_BANK_1_OFFSET            (0x1002000)  /* 32784th LBA */
+ 
+-#define FLASH_BASE_OFFSET               (0x0)
++/* Space in flash to store metadata and uefi variables */
++#define FWU_METADATA_FLASH_DEV          (FLASH_DEV_NAME)
++#define FWU_METADATA_FLASH_SECTOR_SIZE  (FLASH_SECTOR_SIZE)
+ 
+-/* BANK layout (15MB: BANK_PARTITION_SIZE) :-
+- *
+- * 200 KB    : SE_BL2_PARTITION_SIZE + SE_BL2_PARTITION_SIZE
+- * 752 KB    : TFM_PARTITION_SIZE + TFM_PARTITION_SIZE
+- * 2 MB      : FIP_PARTITION_SIZE
+- * 12+ MB    : KERNEL_PARTITION_SIZE
+- *
+- */
+-#define SE_BL2_PARTITION_SIZE           (0x19000)    /* 100 KB */
+-#define TFM_PARTITION_SIZE              (0x5E000)    /* 376 KB */
+-#define FIP_PARTITION_SIZE              (0x200000)   /* 2 MB */
+-#define KERNEL_PARTITION_SIZE           (0xC00000)   /* 12 MB */
++#define FWU_METADATA_REPLICA_1_OFFSET   (0x5000)  /* 40th LBA */
++#define FWU_METADATA_REPLICA_2_OFFSET   (FWU_METADATA_REPLICA_1_OFFSET + \
++                                         FWU_METADATA_FLASH_SECTOR_SIZE)
+ 
++#define FWU_PRIVATE_METADATA_REPLICA_1_OFFSET   (FWU_METADATA_REPLICA_2_OFFSET + \
++                                                 FWU_METADATA_FLASH_SECTOR_SIZE)
++#define FWU_PRIVATE_METADATA_REPLICA_2_OFFSET   (FWU_PRIVATE_METADATA_REPLICA_1_OFFSET + \
++                                                 FWU_METADATA_FLASH_SECTOR_SIZE)
+ 
++#define BANK_0_PARTITION_OFFSET         (SE_BL2_BANK_0_OFFSET + \
++                                         SE_BL2_PARTITION_SIZE)
++#define BANK_1_PARTITION_OFFSET         (SE_BL2_BANK_1_OFFSET + \
++                                         SE_BL2_PARTITION_SIZE)
+ 
++/* BL1: mcuboot flashmap configurations */
++#define FLASH_AREA_8_ID                 (1)
++#define FLASH_AREA_8_SIZE               (SE_BL2_PARTITION_SIZE)
+ 
+-/* 1MB: space in flash to store metadata and uefi variables */
+-#define FWU_METADATA_FLASH_DEV          (FLASH_DEV_NAME)
+-#define FWU_METADATA_FLASH_SECTOR_SIZE  (FLASH_SECTOR_SIZE)
++#define FLASH_INVALID_ID                (0xFF)
++#define FLASH_INVALID_OFFSET            (0xFFFFFFFF)
++#define FLASH_INVALID_SIZE              (0xFFFFFFFF)
+ 
+-#define FWU_METADATA_PARTITION_OFFSET   (FLASH_BASE_OFFSET)
+-#define FWU_METADATA_AREA_SIZE          (FWU_METADATA_FLASH_SECTOR_SIZE)
+-#define FWU_METADATA_REPLICA_1_OFFSET   (FLASH_BASE_OFFSET)
+-#define FWU_METADATA_REPLICA_2_OFFSET   (FWU_METADATA_REPLICA_1_OFFSET + \
+-                                         FWU_METADATA_AREA_SIZE)
+-#define FWU_PRIVATE_AREA_SIZE           (FLASH_SECTOR_SIZE)
+-#define FWU_PRIVATE_AREA_OFFSET         (FWU_METADATA_REPLICA_2_OFFSET + \
+-                                         FWU_METADATA_AREA_SIZE)
++#define BL1_FLASH_AREA_IMAGE_PRIMARY(x)     (((x) == 0) ? FLASH_AREA_8_ID : \
++                                                          255 )
++#define BL1_FLASH_AREA_IMAGE_SECONDARY(x)   (((x) == 0) ? FLASH_INVALID_ID : \
++                                                          255 )
++
++#define BL1_FLASH_AREA_IMAGE_SCRATCH        255
+ 
++/* FWU Configurations */
+ #define NR_OF_FW_BANKS                  (2)
+ #define NR_OF_IMAGES_IN_FW_BANK         (4) /* Secure Enclave: BL2 and TF-M \
+                                              * Host: FIP and Kernel image
+                                              */
+ 
+-#define BANK_0_PARTITION_OFFSET         (FWU_METADATA_PARTITION_OFFSET + \
+-                                         FWU_METADATA_PARTITION_SIZE)
+-#define BANK_1_PARTITION_OFFSET         (BANK_0_PARTITION_OFFSET + \
+-                                         BANK_PARTITION_SIZE)
++/****** TODO: START : NEED SIMPLIFICATION BASED ON GPT *******************/
++/* Bank configurations */
++#define BANK_PARTITION_SIZE             (0xFE0000)   /* 15.875 MB */
++#define TFM_PARTITION_SIZE              (0x5E000)    /* 376 KB */
++#define FIP_PARTITION_SIZE              (0x200000)   /* 2 MB */
++#define KERNEL_PARTITION_SIZE           (0xC00000)   /* 12 MB */
+ 
+ /************************************************************/
+ /* Bank : Images flash offsets are with respect to the bank */
+@@ -170,13 +170,6 @@
+ #define BL2_IMAGE_OFFSET                (0x0)
+ #define BL2_IMAGE_MAX_SIZE              (SE_BL2_PARTITION_SIZE)
+ 
+-#define BL1_FLASH_AREA_IMAGE_PRIMARY(x)     (((x) == 0) ? FLASH_AREA_8_ID : \
+-                                                          255 )
+-#define BL1_FLASH_AREA_IMAGE_SECONDARY(x)   (((x) == 0) ? FLASH_AREA_9_ID : \
+-                                                          255 )
+-
+-#define BL1_FLASH_AREA_IMAGE_SCRATCH        255
+-
+ /* Image 1: TF-M primary and secondary images */
+ #define FLASH_AREA_0_ID                 (1)
+ #define FLASH_AREA_0_OFFSET             (FLASH_AREA_9_OFFSET + \
+@@ -229,6 +222,7 @@
+ #define FWU_METADATA_IMAGE_3_OFFSET     (KERNEL_PARTITION_OFFSET)
+ #define FWU_METADATA_IMAGE_3_SIZE_LIMIT (KERNEL_PARTITION_SIZE)
+ 
++/****** TODO: END : NEED SIMPLIFICATION BASED ON GPT *******************/
+ 
+ /*******************************/
+ /*** ITS, PS and NV Counters ***/
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-Platform-corstone1000-BL2-uses-GPT-layout.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-Platform-corstone1000-BL2-uses-GPT-layout.patch
new file mode 100644
index 0000000..9df98cd
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0009-Platform-corstone1000-BL2-uses-GPT-layout.patch
@@ -0,0 +1,411 @@
+From 6f95d99329e178b7dea5cf7affac2c55135bbb85 Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Wed, 11 Jan 2023 10:27:04 +0000
+Subject: [PATCH 9/10] Platform:corstone1000: BL2 uses GPT layout
+
+Adabt BL2 to use GPT parser find tfm and fip partitions, and then
+extract info to populate MCUBOOT flashmap.
+
+Side changes required:
+Borrow 2k of BL2 code memory to Data memory (during linking)
+i.e. Increase BL2_DATA_GAP_SIZE and decrease SE_BL2_PARTITION_SIZE
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ .../target/arm/corstone1000/CMakeLists.txt    |  5 +-
+ .../target/arm/corstone1000/bl2_flash_map.c   |  7 --
+ .../target/arm/corstone1000/boot_hal_bl2.c    | 86 +++++++++++++-----
+ .../corstone1000/fw_update_agent/fwu_agent.c  | 24 ++---
+ .../corstone1000/fw_update_agent/fwu_agent.h  |  2 +-
+ .../arm/corstone1000/partition/flash_layout.h |  2 +-
+ .../ext/target/arm/corstone1000/platform.c    | 87 ++++++++++++++++++-
+ .../ext/target/arm/corstone1000/platform.h    | 10 +++
+ 8 files changed, 168 insertions(+), 55 deletions(-)
+
+diff --git a/platform/ext/target/arm/corstone1000/CMakeLists.txt b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+index a120f39ea4..f16c1c40b0 100644
+--- a/platform/ext/target/arm/corstone1000/CMakeLists.txt
++++ b/platform/ext/target/arm/corstone1000/CMakeLists.txt
+@@ -130,6 +130,10 @@ target_sources(platform_bl2
+         io/io_block.c
+         io/io_flash.c
+         io/io_storage.c
++        soft_crc/soft_crc.c
++        partition/partition.c
++        partition/gpt.c
++        platform.c
+ )
+ 
+ if (PLATFORM_IS_FVP)
+@@ -174,7 +178,6 @@ target_compile_definitions(bl2
+         $<$<BOOL:${CRYPTO_HW_ACCELERATOR}>:CRYPTO_HW_ACCELERATOR>
+         $<$<BOOL:${CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING}>:CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING>
+         $<$<BOOL:${PLATFORM_PSA_ADAC_SECURE_DEBUG}>:PLATFORM_PSA_ADAC_SECURE_DEBUG>
+-
+ )
+ target_compile_definitions(bootutil
+     PRIVATE
+diff --git a/platform/ext/target/arm/corstone1000/bl2_flash_map.c b/platform/ext/target/arm/corstone1000/bl2_flash_map.c
+index f512045a44..599f80b411 100644
+--- a/platform/ext/target/arm/corstone1000/bl2_flash_map.c
++++ b/platform/ext/target/arm/corstone1000/bl2_flash_map.c
+@@ -58,13 +58,6 @@ struct flash_area flash_map[] = {
+ 
+ const int flash_map_entry_num = ARRAY_SIZE(flash_map);
+ 
+-void add_bank_offset_to_image_offset(uint32_t bank_offset)
+-{
+-    for (int i = 0; i < flash_map_entry_num; i++) {
+-        flash_map[i].fa_off += bank_offset;
+-    }
+-}
+-
+ int boot_get_image_exec_ram_info(uint32_t image_id,
+                                  uint32_t *exec_ram_start,
+                                  uint32_t *exec_ram_size)
+diff --git a/platform/ext/target/arm/corstone1000/boot_hal_bl2.c b/platform/ext/target/arm/corstone1000/boot_hal_bl2.c
+index 323d9707fe..52db26beea 100644
+--- a/platform/ext/target/arm/corstone1000/boot_hal_bl2.c
++++ b/platform/ext/target/arm/corstone1000/boot_hal_bl2.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2019-2022, Arm Limited. All rights reserved.
++ * Copyright (c) 2019-2023, Arm Limited. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  *
+@@ -30,6 +30,14 @@
+ #include "crypto_hw.h"
+ #endif
+ 
++#include "efi.h"
++#include "partition.h"
++#include "platform.h"
++
++static const uint8_t * const tfm_part_names[] = {"tfm_primary", "tfm_secondary"};
++static const uint8_t * const fip_part_names[] = {"FIP_A", "FIP_B"};
++
++
+ /* Flash device name must be specified by target */
+ extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
+ 
+@@ -39,28 +47,62 @@ REGION_DECLARE(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)[];
+ #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof((arr)[0]))
+ extern struct flash_area flash_map[];
+ 
+-int32_t fill_bl2_flash_map_by_parsing_fips(uint32_t bank_offset)
+-{
+-    int result;
++static bool fill_flash_map_with_tfm_data(uint8_t boot_index) {
++
++    if (boot_index >= ARRAY_SIZE(tfm_part_names)) {
++        BOOT_LOG_ERR("%d is an invalid boot_index, 0 <= boot_index < %d",
++                     boot_index, ARRAY_SIZE(tfm_part_names));
++        return false;
++    }
++    partition_entry_t *tfm_entry =
++        get_partition_entry(tfm_part_names[boot_index]);
++    if (tfm_entry == NULL) {
++        BOOT_LOG_ERR("Could not find partition %s", tfm_part_names[boot_index]);
++        return false;
++    }
++    flash_map[0].fa_off = tfm_entry->start;
++    flash_map[0].fa_size = tfm_entry->length;
++    return true;
++}
++
++static bool fill_flash_map_with_fip_data(uint8_t boot_index) {
+     uint32_t tfa_offset = 0;
+-    uint32_t tfa_size = 0;
++    size_t tfa_size = 0;
++    uint32_t fip_offset = 0;
++    size_t fip_size = 0;
++    int result;
++
++    if (boot_index >= ARRAY_SIZE(fip_part_names)) {
++        BOOT_LOG_ERR("%d is an invalid boot_index, 0 <= boot_index < %d",
++                     boot_index, ARRAY_SIZE(fip_part_names));
++        return false;
++    }
++    partition_entry_t *fip_entry =
++        get_partition_entry(fip_part_names[boot_index]);
++    if (fip_entry == NULL) {
++        BOOT_LOG_ERR("Could not find partition %s", fip_part_names[boot_index]);
++        return false;
++    }
++
++    fip_offset = fip_entry->start;
++    fip_size = fip_entry->length;
+ 
+     /* parse directly from flash using XIP mode */
+     /* FIP is large so its not a good idea to load it in memory */
+-    result = parse_fip_and_extract_tfa_info(bank_offset + FLASH_FIP_ADDRESS,
+-                  FLASH_FIP_SIZE,
+-                  &tfa_offset, &tfa_size);
++    result = parse_fip_and_extract_tfa_info(
++        FLASH_BASE_ADDRESS + fip_offset + FIP_SIGNATURE_AREA_SIZE, fip_size,
++        &tfa_offset, &tfa_size);
+     if (result != FIP_PARSER_SUCCESS) {
+         BOOT_LOG_ERR("parse_fip_and_extract_tfa_info failed");
+-        return 1;
++        return false;
+     }
+ 
+-    flash_map[2].fa_off = FLASH_FIP_OFFSET + tfa_offset;
++    flash_map[2].fa_off = fip_offset + FIP_SIGNATURE_AREA_SIZE + tfa_offset;
+     flash_map[2].fa_size = tfa_size;
+     flash_map[3].fa_off = flash_map[2].fa_off + flash_map[2].fa_size;
+     flash_map[3].fa_size = tfa_size;
+ 
+-    return 0;
++    return true;
+ }
+ 
+ #ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
+@@ -89,26 +131,29 @@ uint8_t secure_debug_rotpk[32];
+ 
+ #endif
+ 
+-extern void add_bank_offset_to_image_offset(uint32_t bank_offset);
+-
+ int32_t boot_platform_init(void)
+ {
+     int32_t result;
++    uint8_t boot_index;
+ 
+     result = corstone1000_watchdog_init();
+     if (result != ARM_DRIVER_OK) {
+         return 1;
+     }
+ 
+-#ifndef TFM_S_REG_TEST
+-    result = fill_bl2_flash_map_by_parsing_fips(BANK_0_PARTITION_OFFSET);
+-    if (result) {
++    result = FLASH_DEV_NAME.Initialize(NULL);
++    if (result != ARM_DRIVER_OK) {
+         return 1;
+     }
+-#endif
+ 
+-    result = FLASH_DEV_NAME.Initialize(NULL);
+-    if (result != ARM_DRIVER_OK) {
++    plat_io_storage_init();
++    partition_init(PLATFORM_GPT_IMAGE);
++
++    boot_index = bl2_get_boot_bank();
++
++    if (!fill_flash_map_with_tfm_data(boot_index)
++    || !fill_flash_map_with_fip_data(boot_index)) {
++        BOOT_LOG_ERR("Filling flash map has failed!");
+         return 1;
+     }
+ 
+@@ -149,9 +194,6 @@ int32_t boot_platform_post_init(void)
+     }
+ #endif
+ 
+-    bl2_get_boot_bank(&bank_offset);
+-    add_bank_offset_to_image_offset(bank_offset);
+-
+     return 0;
+ }
+ 
+diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+index e4f9da1ec3..1052bf9f00 100644
+--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
++++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+@@ -836,34 +836,20 @@ void bl1_get_active_bl2_image(uint32_t *offset)
+     return;
+ }
+ 
+-void bl2_get_boot_bank(uint32_t *bank_offset)
++uint8_t bl2_get_boot_bank(void)
+ {
+-    uint32_t boot_index;
++    uint8_t boot_index;
+     struct fwu_private_metadata priv_metadata;
+-    FWU_LOG_MSG("%s: enter\n\r", __func__);
+-
++    FWU_LOG_MSG("%s: enter", __func__);
+     if (fwu_metadata_init()) {
+         FWU_ASSERT(0);
+     }
+-
+     if (private_metadata_read(&priv_metadata)) {
+         FWU_ASSERT(0);
+     }
+-
+     boot_index = priv_metadata.boot_index;
+-
+-    if (boot_index == BANK_0) {
+-        *bank_offset = BANK_0_PARTITION_OFFSET;
+-    } else if (boot_index == BANK_1) {
+-        *bank_offset = BANK_1_PARTITION_OFFSET;
+-    } else {
+-        FWU_ASSERT(0);
+-    }
+-
+-    FWU_LOG_MSG("%s: exit: booting from bank = %u, offset = %x\n\r", __func__,
+-                        boot_index, *bank_offset);
+-
+-    return;
++    FWU_LOG_MSG("%s: exit: booting from bank = %u", __func__, boot_index);
++    return boot_index;
+ }
+ 
+ static void disable_host_ack_timer(void)
+diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h
+index eb8320ed8a..701f205583 100644
+--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h
++++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.h
+@@ -45,7 +45,7 @@ enum fwu_agent_error_t corstone1000_fwu_flash_image(void);
+ enum fwu_agent_error_t corstone1000_fwu_host_ack(void);
+ 
+ void bl1_get_active_bl2_image(uint32_t *bank_offset);
+-void bl2_get_boot_bank(uint32_t *bank_offset);
++uint8_t bl2_get_boot_bank(void);
+ 
+ /* When in trial state, start the timer for host to respond.
+  * Diable timer when host responds back either by calling
+diff --git a/platform/ext/target/arm/corstone1000/partition/flash_layout.h b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
+index 347c91acbb..c5cf94a52c 100644
+--- a/platform/ext/target/arm/corstone1000/partition/flash_layout.h
++++ b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
+@@ -32,7 +32,7 @@
+ #define SRAM_BASE                       (0x30000000)
+ #define SRAM_SIZE                       (0x80000)     /* 512 KB */
+ 
+-#define BL2_DATA_GAP_SIZE               (0x09000)     /* 36 KB */
++#define BL2_DATA_GAP_SIZE               (0x09800)  /* 38 KB */
+ 
+ #define BL1_DATA_START                  (SRAM_BASE)
+ #define BL1_DATA_SIZE                   (0x10000)     /* 64 KiB*/
+diff --git a/platform/ext/target/arm/corstone1000/platform.c b/platform/ext/target/arm/corstone1000/platform.c
+index 908b66b7ac..6add0d7e1b 100644
+--- a/platform/ext/target/arm/corstone1000/platform.c
++++ b/platform/ext/target/arm/corstone1000/platform.c
+@@ -5,16 +5,95 @@
+  *
+  */
+ 
++#include "stdint.h"
++
++#include "Driver_Flash.h"
++#include "flash_layout.h"
++
++#include "io_driver.h"
++#include "io_flash.h"
++#include "io_storage.h"
++
+ #include "platform.h"
+ 
+-#include <stdint.h>
++#define PLAT_LOG_MODULE_NAME    "platform"
++#include "platform_log.h"
++
++typedef struct {
++    uintptr_t dev_handle;
++    uintptr_t image_spec;
++} platform_image_source_t;
++
++extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
++
++static io_dev_connector_t *flash_dev_con;
++static uint8_t local_block_flash[FLASH_SECTOR_SIZE];
++static io_flash_dev_spec_t flash_dev_spec = {
++    .buffer = local_block_flash,
++    .bufferlen = FLASH_SECTOR_SIZE,
++    .base_addr = FLASH_BASE_ADDRESS,
++    .flash_driver = &FLASH_DEV_NAME,
++};
++static io_block_spec_t flash_spec = {
++    .offset = FLASH_BASE_ADDRESS,
++    .length = FLASH_TOTAL_SIZE
++};
++
++static platform_image_source_t platform_image_source[] = {
++    [PLATFORM_GPT_IMAGE] = {
++        .dev_handle = NULL,
++        .image_spec = &flash_spec,
++    }
++};
++
++/* Initialize io storage of the platform */
++int32_t plat_io_storage_init(void)
++{
++    int rc = -1;
++    uintptr_t flash_dev_handle = NULL;
++    uintptr_t flash_handle = NULL;
++
++    rc = register_io_dev_flash((const io_dev_connector_t **) &flash_dev_con);
++    if (rc != 0) {
++        ERROR("Failed to register io flash rc: %d", rc);
++        return rc;
++    }
++
++    rc = io_dev_open(flash_dev_con, (const uintptr_t)&flash_dev_spec, &flash_dev_handle);
++    if (rc != 0) {
++        ERROR("Failed to open io flash dev rc: %d", rc);
++        return rc;
++    }
++
++    VERBOSE("Flash_dev_handle = %p",flash_dev_handle);
++
++    rc = io_open(flash_dev_handle, (const uintptr_t)&flash_spec, &flash_handle);
++    if (rc != 0) {
++        ERROR("Failed to open io flash rc: %d", rc);
++        return rc;
++    }
++
++    VERBOSE("Flash_handle = %p",flash_handle);
++
++    rc = io_close(flash_handle);
++    if (rc != 0) {
++        ERROR("Failed to close io flash rc: %d", rc);
++        return rc;
++    }
++    /* Update the platform image source that uses the flash with dev handles */
++    platform_image_source[PLATFORM_GPT_IMAGE].dev_handle = flash_dev_handle;
++
++    return rc;
++}
+ 
+ /* Return an IO device handle and specification which can be used to access
+  * an image. This has to be implemented for the GPT parser. */
+ int32_t plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+                               uintptr_t *image_spec) {
+-    (void)image_id;
+-    *dev_handle = NULL;
+-    *image_spec = NULL;
++    if (image_id >= PLATFORM_IMAGE_COUNT) {
++        return -1;
++    }
++    *dev_handle = platform_image_source[image_id].dev_handle;
++    *image_spec = platform_image_source[image_id].image_spec;
+     return 0;
+ }
+diff --git a/platform/ext/target/arm/corstone1000/platform.h b/platform/ext/target/arm/corstone1000/platform.h
+index 250f9cd9f5..894f5e3090 100644
+--- a/platform/ext/target/arm/corstone1000/platform.h
++++ b/platform/ext/target/arm/corstone1000/platform.h
+@@ -8,6 +8,16 @@
+ #ifndef __PLATFORM_H__
+ #define __PLATFORM_H__
+ 
++typedef enum {
++    PLATFORM_GPT_IMAGE = 0,
++    PLATFORM_IMAGE_COUNT,
++}platform_image_id_t;
++
++/* Initialize io storage of the platform */
++int32_t plat_io_storage_init(void);
++
++/* Return an IO device handle and specification which can be used to access
++ * an image. This has to be implemented for the GPT parser. */
+ int32_t plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
+                               uintptr_t *image_spec);
+ 
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-Platform-corstone1000-flash_layout-simplification.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-Platform-corstone1000-flash_layout-simplification.patch
new file mode 100644
index 0000000..c3376e1
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0010-Platform-corstone1000-flash_layout-simplification.patch
@@ -0,0 +1,103 @@
+From c385b628aa3588aeb6f86f8b98fd3bdb304a296c Mon Sep 17 00:00:00 2001
+From: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Date: Wed, 11 Jan 2023 12:47:45 +0000
+Subject: [PATCH 10/10] Platform: corstone1000:flash_layout simplification
+
+Complete the simplification of the flash layout.
+The flash layout contains only the static definitions
+that describe the static layout and the boundries of the dynamic
+regions.
+
+The dynamic regions addresses are known by the GPT parser.
+
+Signed-off-by: Mohamed Omar Asaker <mohamed.omarasaker@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ .../arm/corstone1000/partition/flash_layout.h | 44 -------------------
+ 1 file changed, 44 deletions(-)
+
+diff --git a/platform/ext/target/arm/corstone1000/partition/flash_layout.h b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
+index c5cf94a52c..b01a3621b3 100644
+--- a/platform/ext/target/arm/corstone1000/partition/flash_layout.h
++++ b/platform/ext/target/arm/corstone1000/partition/flash_layout.h
+@@ -142,28 +142,9 @@
+                                              * Host: FIP and Kernel image
+                                              */
+ 
+-/****** TODO: START : NEED SIMPLIFICATION BASED ON GPT *******************/
+ /* Bank configurations */
+ #define BANK_PARTITION_SIZE             (0xFE0000)   /* 15.875 MB */
+ #define TFM_PARTITION_SIZE              (0x5E000)    /* 376 KB */
+-#define FIP_PARTITION_SIZE              (0x200000)   /* 2 MB */
+-#define KERNEL_PARTITION_SIZE           (0xC00000)   /* 12 MB */
+-
+-/************************************************************/
+-/* Bank : Images flash offsets are with respect to the bank */
+-/************************************************************/
+-
+-/* Image 0: BL2 primary and secondary images */
+-#define FLASH_AREA_8_ID                 (1)
+-#define FLASH_AREA_8_OFFSET             (0) /* starting from 0th offset of the bank */
+-#define FLASH_AREA_8_SIZE               (SE_BL2_PARTITION_SIZE)
+-
+-#define FLASH_AREA_9_ID                 (FLASH_AREA_8_ID + 1)
+-#define FLASH_AREA_9_OFFSET             (FLASH_AREA_8_OFFSET + FLASH_AREA_8_SIZE)
+-#define FLASH_AREA_9_SIZE               (SE_BL2_PARTITION_SIZE)
+-
+-#define FWU_METADATA_IMAGE_0_OFFSET     (FLASH_AREA_8_OFFSET)
+-#define FWU_METADATA_IMAGE_0_SIZE_LIMIT (FLASH_AREA_8_SIZE + FLASH_AREA_9_SIZE)
+ 
+ /* Macros needed to imgtool.py, used when creating BL2 signed image */
+ #define BL2_IMAGE_LOAD_ADDRESS          (SRAM_BASE + TFM_PARTITION_SIZE + BL2_DATA_GAP_SIZE)
+@@ -172,33 +153,16 @@
+ 
+ /* Image 1: TF-M primary and secondary images */
+ #define FLASH_AREA_0_ID                 (1)
+-#define FLASH_AREA_0_OFFSET             (FLASH_AREA_9_OFFSET + \
+-                                         FLASH_AREA_9_SIZE)
+ #define FLASH_AREA_0_SIZE               (TFM_PARTITION_SIZE)
+-
+ #define FLASH_AREA_1_ID                 (FLASH_AREA_0_ID + 1)
+-#define FLASH_AREA_1_OFFSET             (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE)
+ #define FLASH_AREA_1_SIZE               (TFM_PARTITION_SIZE)
+ 
+-#define FWU_METADATA_IMAGE_1_OFFSET     (FLASH_AREA_0_OFFSET)
+-#define FWU_METADATA_IMAGE_1_SIZE_LIMIT (FLASH_AREA_0_SIZE + FLASH_AREA_1_SIZE)
+-
+ /* Image 2: Host FIP */
+ #define FIP_SIGNATURE_AREA_SIZE         (0x1000)      /* 4 KB */
+ 
+-#define FLASH_FIP_OFFSET                (FLASH_AREA_1_OFFSET + \
+-                                         FLASH_AREA_1_SIZE + FIP_SIGNATURE_AREA_SIZE)
+-#define FLASH_FIP_ADDRESS               (FLASH_BASE_ADDRESS + FLASH_FIP_OFFSET)
+-#define FLASH_FIP_SIZE                  (FIP_PARTITION_SIZE)
+-
+ /* Host BL2 (TF-A) primary and secondary image. */
+ #define FLASH_AREA_2_ID                 (FLASH_AREA_1_ID + 1)
+ #define FLASH_AREA_3_ID                 (FLASH_AREA_2_ID + 1)
+-#define FLASH_INVALID_OFFSET            (0xFFFFFFFF)
+-#define FLASH_INVALID_SIZE              (0xFFFFFFFF)
+-
+-#define FWU_METADATA_IMAGE_2_OFFSET     (FLASH_FIP_OFFSET)
+-#define FWU_METADATA_IMAGE_2_SIZE_LIMIT (FLASH_FIP_SIZE)
+ 
+ /* Macros needed to imgtool.py, used when creating TF-M signed image */
+ #define S_IMAGE_LOAD_ADDRESS            (SRAM_BASE)
+@@ -216,14 +180,6 @@
+ 
+ #define FLASH_AREA_IMAGE_SCRATCH        255
+ 
+-/* Image 3: Kernel image */
+-#define KERNEL_PARTITION_OFFSET         (FLASH_FIP_OFFSET + FLASH_FIP_SIZE)
+-
+-#define FWU_METADATA_IMAGE_3_OFFSET     (KERNEL_PARTITION_OFFSET)
+-#define FWU_METADATA_IMAGE_3_SIZE_LIMIT (KERNEL_PARTITION_SIZE)
+-
+-/****** TODO: END : NEED SIMPLIFICATION BASED ON GPT *******************/
+-
+ /*******************************/
+ /*** ITS, PS and NV Counters ***/
+ /*******************************/
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0011-corstone1000-make-sure-to-write-fwu-metadata-to-repl.patch b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0011-corstone1000-make-sure-to-write-fwu-metadata-to-repl.patch
new file mode 100644
index 0000000..24150b6
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/files/corstone1000/0011-corstone1000-make-sure-to-write-fwu-metadata-to-repl.patch
@@ -0,0 +1,43 @@
+From 0ee6842d348e206d511ec89a7ff5b29a6f325456 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Sun, 29 Jan 2023 19:01:08 +0000
+Subject: [PATCH] corstone1000: make sure to write fwu metadata to replica 2
+
+u-boot and other, before using fwu metadata validate if
+the copies in both replicas are good. so, make sure
+we write fwu metadata in both replicas.
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ .../arm/corstone1000/fw_update_agent/fwu_agent.c   | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+index e1fa297ac923..215902ce71b9 100644
+--- a/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
++++ b/platform/ext/target/arm/corstone1000/fw_update_agent/fwu_agent.c
+@@ -238,6 +238,20 @@ static enum fwu_agent_error_t metadata_write(
+         return FWU_AGENT_ERROR;
+     }
+ 
++    FWU_LOG_MSG("%s: enter: flash addr = %u, size = %d\n\r", __func__,
++                  FWU_METADATA_REPLICA_2_OFFSET, sizeof(struct fwu_metadata));
++
++    ret = FWU_METADATA_FLASH_DEV.EraseSector(FWU_METADATA_REPLICA_2_OFFSET);
++    if (ret != ARM_DRIVER_OK) {
++        return FWU_AGENT_ERROR;
++    }
++
++    ret = FWU_METADATA_FLASH_DEV.ProgramData(FWU_METADATA_REPLICA_2_OFFSET,
++                                p_metadata, sizeof(struct fwu_metadata));
++    if (ret < 0 || ret != sizeof(struct fwu_metadata)) {
++        return FWU_AGENT_ERROR;
++    }
++
+     FWU_LOG_MSG("%s: success: active = %u, previous = %d\n\r", __func__,
+                   p_metadata->active_index, p_metadata->previous_active_index);
+     return FWU_AGENT_SUCCESS;
+-- 
+2.39.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-1.7.0-corstone1000.inc b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-1.7.0-corstone1000.inc
index d89aca3..a8e76d0 100644
--- a/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-1.7.0-corstone1000.inc
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/trusted-firmware-m/trusted-firmware-m-1.7.0-corstone1000.inc
@@ -11,9 +11,6 @@
 EXTRA_OECMAKE += "-DPLATFORM_IS_FVP=${TFM_PLATFORM_IS_FVP}"
 EXTRA_OECMAKE += "-DCC312_LEGACY_DRIVER_API_ENABLED=OFF"
 
-## Setting SPM backend to IPC
-EXTRA_OECMAKE += "-DCONFIG_TFM_SPM_BACKEND=IPC"
-
 # libmetal
 LICENSE += "& BSD-3-Clause"
 LIC_FILES_CHKSUM += "file://../libmetal/LICENSE.md;md5=fe0b8a4beea8f0813b606d15a3df3d3c"
@@ -30,8 +27,18 @@
 
 
 FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
-SRC_URI:append= " \
-    file://0001-Platform-corstone1000-Increase-number-of-assets.patch  \
+SRC_URI:append:corstone1000 = " \
+    file://0001-Platform-corstone1000-Introduce-IO-framework.patch              \
+    file://0002-Platform-corstone1000-Add-IO-test-in-ci_regressions.patch       \
+    file://0003-Platform-corstone1000-Add-soft-crc32-calculation.patch          \
+    file://0004-Platform-corstone1000-calculate-metadata-crc32.patch            \
+    file://0005-Platform-corstone1000-fwu-metadata_read-validate-crc.patch      \
+    file://0006-Platform-corstone1000-Add-common-platform-logger.patch          \
+    file://0007-Platform-corstone1000-Introduce-GPT-parser.patch                \
+    file://0008-Platform-corstone1000-BL1-changes-to-adapt-to-new-fl.patch      \
+    file://0009-Platform-corstone1000-BL2-uses-GPT-layout.patch                 \
+    file://0010-Platform-corstone1000-flash_layout-simplification.patch         \
+    file://0011-corstone1000-make-sure-to-write-fwu-metadata-to-repl.patch      \
            "
 
 do_install() {
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-drivers-nvmxip-introduce-NVM-XIP-block-storage-emula.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-drivers-nvmxip-introduce-NVM-XIP-block-storage-emula.patch
new file mode 100644
index 0000000..30baf68
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0027-drivers-nvmxip-introduce-NVM-XIP-block-storage-emula.patch
@@ -0,0 +1,595 @@
+From 1d277bc8c275fae8e8cd400344bdacbdce3a6b46 Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Tue, 13 Dec 2022 19:47:49 +0000
+Subject: [PATCH 27/43] drivers/nvmxip: introduce NVM XIP block storage
+ emulation
+
+add block storage emulation for NVM XIP flash devices
+
+Some paltforms such as Corstone-1000 need to see NVM XIP raw flash
+as a block storage device with read only capability.
+
+Here NVM flash devices are devices with addressable
+memory (e.g: QSPI NOR flash).
+
+The implementation is generic and can be used by different platforms.
+
+Two drivers are provided as follows.
+
+  nvmxip-blk :
+
+    a generic block driver allowing to read from the XIP flash
+
+  nvmxip_qspi :
+
+    The driver probed with the DT and parent of the nvmxip-blk device.
+    nvmxip_qspi can be reused by other platforms. If the platform
+    has custom settings to apply before using the flash, then the platform
+    can provide its own parent driver belonging to UCLASS_NVMXIP and reuse
+    nvmxip-blk. The custom driver can be implmented like nvmxip_qspi in
+    addition to the platform custom settings.
+
+Platforms can use multiple NVM XIP devices at the same time by defining a
+DT node for each one of them.
+
+For more details please refer to doc/develop/driver-model/nvmxip.rst
+
+Upstream-Status: Submitted
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ MAINTAINERS                                |   7 ++
+ doc/develop/driver-model/index.rst         |   1 +
+ doc/develop/driver-model/nvmxip.rst        |  70 ++++++++++++
+ doc/device-tree-bindings/nvmxip/nvmxip.txt |  56 +++++++++
+ drivers/Kconfig                            |   2 +
+ drivers/Makefile                           |   1 +
+ drivers/block/blk-uclass.c                 |   1 +
+ drivers/nvmxip/Kconfig                     |  17 +++
+ drivers/nvmxip/Makefile                    |   7 ++
+ drivers/nvmxip/nvmxip-uclass.c             |  13 +++
+ drivers/nvmxip/nvmxip.c                    | 127 +++++++++++++++++++++
+ drivers/nvmxip/nvmxip.h                    |  46 ++++++++
+ drivers/nvmxip/nvmxip_qspi.c               |  65 +++++++++++
+ include/dm/uclass-id.h                     |   1 +
+ 14 files changed, 414 insertions(+)
+ create mode 100644 doc/develop/driver-model/nvmxip.rst
+ create mode 100644 doc/device-tree-bindings/nvmxip/nvmxip.txt
+ create mode 100644 drivers/nvmxip/Kconfig
+ create mode 100644 drivers/nvmxip/Makefile
+ create mode 100644 drivers/nvmxip/nvmxip-uclass.c
+ create mode 100644 drivers/nvmxip/nvmxip.c
+ create mode 100644 drivers/nvmxip/nvmxip.h
+ create mode 100644 drivers/nvmxip/nvmxip_qspi.c
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 9feaf0502f5b..ba15dd02d58d 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1204,6 +1204,13 @@ F:	cmd/nvme.c
+ F:	include/nvme.h
+ F:	doc/develop/driver-model/nvme.rst
+ 
++NVMXIP
++M:	Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++S:	Maintained
++F:	doc/develop/driver-model/nvmxip.rst
++F:	doc/device-tree-bindings/nvmxip/nvmxip.txt
++F:	drivers/nvmxip/
++
+ NVMEM
+ M:	Sean Anderson <seanga2@gmail.com>
+ S:	Maintained
+diff --git a/doc/develop/driver-model/index.rst b/doc/develop/driver-model/index.rst
+index 7366ef818c5a..8e12bbd9366a 100644
+--- a/doc/develop/driver-model/index.rst
++++ b/doc/develop/driver-model/index.rst
+@@ -20,6 +20,7 @@ subsystems
+    livetree
+    migration
+    nvme
++   nvmxip
+    of-plat
+    pci-info
+    pmic-framework
+diff --git a/doc/develop/driver-model/nvmxip.rst b/doc/develop/driver-model/nvmxip.rst
+new file mode 100644
+index 000000000000..91b24e4e50d2
+--- /dev/null
++++ b/doc/develop/driver-model/nvmxip.rst
+@@ -0,0 +1,70 @@
++.. SPDX-License-Identifier: GPL-2.0+
++
++NVM XIP Block Storage Emulation Driver
++=======================================
++
++Summary
++-------
++
++Non-Volatile Memory devices with addressable memory (e.g: QSPI NOR flash) could
++be used for block storage needs (e.g: parsing a GPT layout in a raw QSPI NOR flash).
++
++The NVMXIP class provides this functionality and can be used for any 64-bit platform.
++
++The NVMXIP class provides the following drivers:
++
++      nvmxip-blk :
++
++        A generic block driver allowing to read from the XIP flash.
++	The driver belongs to UCLASS_BLK.
++	The driver implemented by drivers/nvmxip/nvmxip.c
++
++      nvmxip_qspi :
++
++        The driver probed with the DT and parent of the nvmxip-blk device.
++        nvmxip_qspi can be reused by other platforms. If the platform
++        has custom settings to apply before using the flash, then the platform
++        can provide its own parent driver belonging to UCLASS_NVMXIP and reuse
++        nvmxip-blk. The custom driver can be implmented like nvmxip_qspi in
++        addition to the platform custom settings.
++	The nvmxip_qspi driver belongs to UCLASS_NVMXIP.
++	The driver implemented by drivers/nvmxip/nvmxip_qspi.c
++
++    The implementation is generic and can be used by different platforms.
++
++Supported hardware
++--------------------------------
++
++Any 64-bit plaform.
++
++Configuration
++----------------------
++
++config NVMXIP
++	  This option allows the emulation of a block storage device
++	  on top of a direct access non volatile memory XIP flash devices.
++	  This support provides the read operation.
++	  This option provides the block storage driver nvmxip-blk which
++	  handles the read operation. This driver is HW agnostic and can support
++	  multiple flash devices at the same time.
++
++config NVMXIP_QSPI
++	  This option allows the emulation of a block storage device on top of a QSPI XIP flash.
++	  Any platform that needs to emulate one or multiple XIP flash devices can turn this
++	  option on to enable the functionality. NVMXIP config is selected automatically.
++	  Platforms that need to add custom treatments before accessing to the flash, can
++	  write their own driver (same as nvmxip_qspi in addition to the custom settings).
++
++Device Tree nodes
++--------------------
++
++Multiple XIP flash devices can be used at the same time by describing them through DT
++nodes.
++
++Please refer to the documentation of the DT binding at:
++
++doc/device-tree-bindings/nvmxip/nvmxip.txt
++
++Contributors
++------------
++   * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+diff --git a/doc/device-tree-bindings/nvmxip/nvmxip.txt b/doc/device-tree-bindings/nvmxip/nvmxip.txt
+new file mode 100644
+index 000000000000..7c4b03f66b57
+--- /dev/null
++++ b/doc/device-tree-bindings/nvmxip/nvmxip.txt
+@@ -0,0 +1,56 @@
++Specifying NVMXIP information for devices
++======================================
++
++NVM XIP flash device nodes
++---------------------------
++
++Each flash device should have its own node.
++
++Each node must specify the following fields:
++
++1)
++		compatible = "nvmxip,qspi";
++
++This allows to bind the flash device with the nvmxip_qspi driver
++If a platform has its own driver, please provide your own compatible
++string.
++
++2)
++		reg = <0x0 0x08000000 0x0 0x00200000>;
++
++The start address and size of the flash device. The values give here are an
++example (when the cell size is 2).
++
++When cell size is 1, the reg field looks like this:
++
++		reg = <0x08000000 0x00200000>;
++
++3)
++
++		lba_shift = <9>;
++
++The number of bit shifts used to calculate the size in bytes of one block.
++In this example the block size is 1 << 9 = 2 ^ 9 = 512 bytes
++
++4)
++
++		lba = <4096>;
++
++The number of blocks.
++
++Example of multiple flash devices
++----------------------------------------------------
++
++	nvmxip-qspi1@08000000 {
++		compatible = "nvmxip,qspi";
++		reg = <0x0 0x08000000 0x0 0x00200000>;
++		lba_shift = <9>;
++		lba = <4096>;
++	};
++
++	nvmxip-qspi2@08200000 {
++		compatible = "nvmxip,qspi";
++		reg = <0x0 0x08200000 0x0 0x00100000>;
++		lba_shift = <9>;
++		lba = <2048>;
++	};
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index e51f0547c3da..d425ff1e76c7 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -78,6 +78,8 @@ source "drivers/net/Kconfig"
+ 
+ source "drivers/nvme/Kconfig"
+ 
++source "drivers/nvmxip/Kconfig"
++
+ source "drivers/pci/Kconfig"
+ 
+ source "drivers/pci_endpoint/Kconfig"
+diff --git a/drivers/Makefile b/drivers/Makefile
+index f0a7530295c5..fb1b62cbd6ff 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -89,6 +89,7 @@ obj-$(CONFIG_FWU_MDATA) += fwu-mdata/
+ obj-y += misc/
+ obj-$(CONFIG_MMC) += mmc/
+ obj-$(CONFIG_NVME) += nvme/
++obj-$(CONFIG_NVMXIP) += nvmxip/
+ obj-$(CONFIG_PCI_ENDPOINT) += pci_endpoint/
+ obj-y += dfu/
+ obj-$(CONFIG_PCH) += pch/
+diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
+index c69fc4d51829..e8ab576c3253 100644
+--- a/drivers/block/blk-uclass.c
++++ b/drivers/block/blk-uclass.c
+@@ -28,6 +28,7 @@ static struct {
+ 	{ UCLASS_AHCI, "sata" },
+ 	{ UCLASS_HOST, "host" },
+ 	{ UCLASS_NVME, "nvme" },
++	{ UCLASS_NVMXIP, "nvmxip" },
+ 	{ UCLASS_EFI_MEDIA, "efi" },
+ 	{ UCLASS_EFI_LOADER, "efiloader" },
+ 	{ UCLASS_VIRTIO, "virtio" },
+diff --git a/drivers/nvmxip/Kconfig b/drivers/nvmxip/Kconfig
+new file mode 100644
+index 000000000000..6a23acaf1895
+--- /dev/null
++++ b/drivers/nvmxip/Kconfig
+@@ -0,0 +1,17 @@
++# SPDX-License-Identifier: GPL-2.0+
++#
++# Copyright (C) 2022, Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++
++config NVMXIP
++	bool "NVM XIP devices support"
++	select BLK
++	help
++	  This option allows the emulation of a block storage device
++	  on top of a direct access non volatile memory XIP flash devices.
++	  This support provides the read operation.
++
++config NVMXIP_QSPI
++	bool "QSPI XIP  support"
++	select NVMXIP
++	help
++	  This option allows the emulation of a block storage device on top of a QSPI XIP flash
+diff --git a/drivers/nvmxip/Makefile b/drivers/nvmxip/Makefile
+new file mode 100644
+index 000000000000..d8ad2a160b47
+--- /dev/null
++++ b/drivers/nvmxip/Makefile
+@@ -0,0 +1,7 @@
++# SPDX-License-Identifier: GPL-2.0+
++#
++# (C) Copyright 2022
++# Abdellatif El Khlifi, Arm Limited, abdellatif.elkhlifi@arm.com.
++
++obj-y += nvmxip-uclass.o nvmxip.o
++obj-$(CONFIG_NVMXIP_QSPI) += nvmxip_qspi.o
+diff --git a/drivers/nvmxip/nvmxip-uclass.c b/drivers/nvmxip/nvmxip-uclass.c
+new file mode 100644
+index 000000000000..0f7e47b8af86
+--- /dev/null
++++ b/drivers/nvmxip/nvmxip-uclass.c
+@@ -0,0 +1,13 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#include <common.h>
++#include <dm.h>
++
++UCLASS_DRIVER(nvmxip) = {
++	.name	= "nvmxip",
++	.id	= UCLASS_NVMXIP,
++};
+diff --git a/drivers/nvmxip/nvmxip.c b/drivers/nvmxip/nvmxip.c
+new file mode 100644
+index 000000000000..6ba48183c575
+--- /dev/null
++++ b/drivers/nvmxip/nvmxip.c
+@@ -0,0 +1,127 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <dm/device-internal.h>
++#include "nvmxip.h"
++
++static u32 nvmxip_bdev_max_devs;
++
++static int nvmxip_mmio_rawread(const phys_addr_t address, u64 *value)
++{
++	*value = readq(address);
++	return 0;
++}
++
++static ulong nvmxip_blk_read(struct udevice *udev, lbaint_t blknr, lbaint_t blkcnt, void *buffer)
++{
++	struct nvmxip_blk_priv *bpriv_data = dev_get_priv(udev);
++	struct blk_desc *desc = dev_get_uclass_plat(udev);
++
++	/* size of 1 block */
++	/* number of the u64 words to read */
++	u32 qwords = (blkcnt * desc->blksz) / sizeof(u64);
++	/* physical address of the first block to read */
++	phys_addr_t blkaddr = bpriv_data->pplat_data->phys_base + blknr * desc->blksz;
++	u64 *virt_blkaddr;
++	u64 *pdst = buffer;
++	u32 qdata_idx;
++
++	if (!pdst)
++		return -EINVAL;
++
++	pr_debug("[%s]: reading from blknr: %lu , blkcnt: %lu\n", udev->name, blknr, blkcnt);
++
++	virt_blkaddr = map_sysmem(blkaddr, 0);
++
++	/* assumption: the data is virtually contiguous */
++
++	for (qdata_idx = 0 ; qdata_idx < qwords ; qdata_idx++)
++		nvmxip_mmio_rawread((phys_addr_t)(virt_blkaddr + qdata_idx), pdst++);
++
++	pr_debug("[%s]:     src[0]: 0x%llx , dst[0]: 0x%llx , src[-1]: 0x%llx , dst[-1]: 0x%llx\n",
++		 udev->name,
++		 *virt_blkaddr,
++		 *(u64 *)buffer,
++		 *(u64 *)((u8 *)virt_blkaddr + desc->blksz * blkcnt - sizeof(u64)),
++		 *(u64 *)((u8 *)buffer + desc->blksz * blkcnt - sizeof(u64)));
++
++	unmap_sysmem(virt_blkaddr);
++
++	return blkcnt;
++}
++
++static int nvmxip_blk_probe(struct udevice *udev)
++{
++	struct nvmxip_priv *ppriv_data = dev_get_priv(udev->parent);
++	struct blk_desc *desc = dev_get_uclass_plat(udev);
++	struct nvmxip_blk_priv *bpriv_data = dev_get_priv(udev);
++
++	bpriv_data->bdev = udev;
++	bpriv_data->pplat_data = ppriv_data->plat_data;
++	desc->lba = bpriv_data->pplat_data->lba;
++	desc->log2blksz = bpriv_data->pplat_data->lba_shift;
++	desc->blksz = 1 << bpriv_data->pplat_data->lba_shift;
++	desc->bdev = bpriv_data->bdev;
++
++	pr_debug("[%s]: block storage layout\n    lbas: %lu , log2blksz: %d, blksz: %lu\n",
++		 udev->name, desc->lba, desc->log2blksz, desc->blksz);
++
++	return 0;
++}
++
++int nvmxip_init(struct udevice *udev)
++{
++	struct nvmxip_plat *plat_data = dev_get_plat(udev);
++	struct nvmxip_priv *priv_data = dev_get_priv(udev);
++	int ret;
++	struct udevice *bdev = NULL;
++	char bdev_name[NVMXIP_BLKDEV_NAME_SZ + 1] = {0};
++
++	priv_data->udev = udev;
++	priv_data->plat_data = plat_data;
++
++	nvmxip_bdev_max_devs++;
++
++	snprintf(bdev_name, NVMXIP_BLKDEV_NAME_SZ, "nvmxip-blk#%d", nvmxip_bdev_max_devs);
++
++	ret = blk_create_devicef(udev, NVMXIP_BLKDRV_NAME, bdev_name, UCLASS_NVMXIP,
++				 nvmxip_bdev_max_devs, NVMXIP_DEFAULT_LBA_SZ,
++				 NVMXIP_DEFAULT_LBA_COUNT, &bdev);
++	if (ret) {
++		pr_err("[%s]: failure during creation of the block device %s, error %d\n",
++		       udev->name, bdev_name, ret);
++		goto blkdev_setup_error;
++	}
++
++	ret = blk_probe_or_unbind(bdev);
++	if (ret) {
++		pr_err("[%s]: failure during probing the block device %s, error %d\n",
++		       udev->name, bdev_name, ret);
++		goto blkdev_setup_error;
++	}
++
++	pr_info("[%s]: the block device %s ready for use\n", udev->name, bdev_name);
++
++	return 0;
++
++blkdev_setup_error:
++	nvmxip_bdev_max_devs--;
++	return ret;
++}
++
++static const struct blk_ops nvmxip_blk_ops = {
++	.read	= nvmxip_blk_read,
++};
++
++U_BOOT_DRIVER(nvmxip_blk) = {
++	.name	= NVMXIP_BLKDRV_NAME,
++	.id	= UCLASS_BLK,
++	.probe	= nvmxip_blk_probe,
++	.ops	= &nvmxip_blk_ops,
++	.priv_auto	= sizeof(struct nvmxip_blk_priv),
++};
+diff --git a/drivers/nvmxip/nvmxip.h b/drivers/nvmxip/nvmxip.h
+new file mode 100644
+index 000000000000..393172cc2f86
+--- /dev/null
++++ b/drivers/nvmxip/nvmxip.h
+@@ -0,0 +1,46 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#ifndef __DRIVER_NVMXIP_H__
++#define __DRIVER_NVMXIP_H__
++
++#include <asm/io.h>
++#include <blk.h>
++#include <linux/bitops.h>
++#include <linux/compat.h>
++#include <mapmem.h>
++
++#define NVMXIP_BLKDRV_NAME    "nvmxip-blk"
++
++#define NVMXIP_BLKDEV_NAME_SZ 20
++
++#define NVMXIP_DEFAULT_LBA_SHIFT 10 /* 1024 bytes per block */
++#define NVMXIP_DEFAULT_LBA_COUNT 1024 /* block count */
++
++#define NVMXIP_DEFAULT_LBA_SZ BIT(NVMXIP_DEFAULT_LBA_SHIFT)
++
++/* NVM XIP device platform data */
++struct nvmxip_plat {
++	phys_addr_t phys_base; /* NVM XIP device base address */
++	u32 lba_shift; /* block size shift count (read from device tree) */
++	lbaint_t lba; /* number of blocks (read from device tree) */
++};
++
++/* NVM XIP device private data */
++struct nvmxip_priv {
++	struct udevice *udev;
++	struct nvmxip_plat *plat_data;
++};
++
++/* Private data of the block device associated with the NVM XIP device (the parent) */
++struct nvmxip_blk_priv {
++	struct udevice *bdev;
++	struct nvmxip_plat *pplat_data; /* parent device platform data */
++};
++
++int nvmxip_init(struct udevice *udev);
++
++#endif /* __DRIVER_NVMXIP_H__ */
+diff --git a/drivers/nvmxip/nvmxip_qspi.c b/drivers/nvmxip/nvmxip_qspi.c
+new file mode 100644
+index 000000000000..749625134acd
+--- /dev/null
++++ b/drivers/nvmxip/nvmxip_qspi.c
+@@ -0,0 +1,65 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#include <common.h>
++#include <dm.h>
++#include <fdt_support.h>
++#include "nvmxip.h"
++
++#include <asm/global_data.h>
++DECLARE_GLOBAL_DATA_PTR;
++
++#define NVMXIP_QSPI_DRV_NAME "nvmxip_qspi"
++
++static int nvmxip_qspi_probe(struct udevice *dev)
++{
++	pr_debug("[%s][%s]\n", __func__, dev->name);
++	return nvmxip_init(dev);
++}
++
++static int nvmxip_qspi_of_to_plat(struct udevice *dev)
++{
++	struct nvmxip_plat *plat_data = dev_get_plat(dev);
++	int ret;
++
++	plat_data->phys_base = (phys_addr_t)dev_read_addr(dev);
++	if (plat_data->phys_base == FDT_ADDR_T_NONE) {
++		pr_err("[%s]: can not get base address from device tree\n", dev->name);
++		return -EINVAL;
++	}
++
++	ret = dev_read_u32(dev, "lba_shift", &plat_data->lba_shift);
++	if (ret) {
++		pr_err("[%s]: can not get lba_shift from device tree\n", dev->name);
++		return -EINVAL;
++	}
++
++	ret = dev_read_u32(dev, "lba", (u32 *)&plat_data->lba);
++	if (ret) {
++		pr_err("[%s]: can not get lba from device tree\n", dev->name);
++		return -EINVAL;
++	}
++
++	pr_debug("[%s]: XIP device base addr: 0x%llx , lba_shift: %d , lbas: %lu\n",
++		 dev->name, plat_data->phys_base, plat_data->lba_shift, plat_data->lba);
++
++	return 0;
++}
++
++static const struct udevice_id nvmxip_qspi_ids[] = {
++	{ .compatible = "nvmxip,qspi" },
++	{ /* sentinel */ }
++};
++
++U_BOOT_DRIVER(nvmxip_qspi) = {
++	.name = NVMXIP_QSPI_DRV_NAME,
++	.id = UCLASS_NVMXIP,
++	.of_match = nvmxip_qspi_ids,
++	.of_to_plat = nvmxip_qspi_of_to_plat,
++	.priv_auto = sizeof(struct nvmxip_priv),
++	.plat_auto = sizeof(struct nvmxip_plat),
++	.probe = nvmxip_qspi_probe,
++};
+diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
+index fa08a66ac8e0..f3564a49d912 100644
+--- a/include/dm/uclass-id.h
++++ b/include/dm/uclass-id.h
+@@ -92,6 +92,7 @@ enum uclass_id {
+ 	UCLASS_NOP,		/* No-op devices */
+ 	UCLASS_NORTHBRIDGE,	/* Intel Northbridge / SDRAM controller */
+ 	UCLASS_NVME,		/* NVM Express device */
++	UCLASS_NVMXIP,		/* NVM XIP devices */
+ 	UCLASS_P2SB,		/* (x86) Primary-to-Sideband Bus */
+ 	UCLASS_PANEL,		/* Display panel, such as an LCD */
+ 	UCLASS_PANEL_BACKLIGHT,	/* Backlight controller for panel */
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-sandbox64-fix-return-unsigned-long-in-readq.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-sandbox64-fix-return-unsigned-long-in-readq.patch
new file mode 100644
index 0000000..b0e8366
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0028-sandbox64-fix-return-unsigned-long-in-readq.patch
@@ -0,0 +1,46 @@
+From 3262ee6a5300221969e61eff7a8f18336a135a73 Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Fri, 16 Dec 2022 17:20:58 +0000
+Subject: [PATCH 28/43] sandbox64: fix: return unsigned long in readq()
+
+make readq return unsigned long
+
+readq should return 64-bit data
+
+Upstream-Status: Submitted
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ arch/sandbox/cpu/cpu.c        | 2 +-
+ arch/sandbox/include/asm/io.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
+index 636d3545b954..248d17a85c82 100644
+--- a/arch/sandbox/cpu/cpu.c
++++ b/arch/sandbox/cpu/cpu.c
+@@ -230,7 +230,7 @@ phys_addr_t map_to_sysmem(const void *ptr)
+ 	return mentry->tag;
+ }
+ 
+-unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size)
++unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size)
+ {
+ 	struct sandbox_state *state = state_get_current();
+ 
+diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
+index ad6c29a4e26c..31ab7289b4bd 100644
+--- a/arch/sandbox/include/asm/io.h
++++ b/arch/sandbox/include/asm/io.h
+@@ -45,7 +45,7 @@ static inline void unmap_sysmem(const void *vaddr)
+ /* Map from a pointer to our RAM buffer */
+ phys_addr_t map_to_sysmem(const void *ptr);
+ 
+-unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size);
++unsigned long sandbox_read(const void *addr, enum sandboxio_size_t size);
+ void sandbox_write(void *addr, unsigned int val, enum sandboxio_size_t size);
+ 
+ #define readb(addr) sandbox_read((const void *)addr, SB_SIZE_8)
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-sandbox64-add-support-for-NVMXIP-QSPI.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-sandbox64-add-support-for-NVMXIP-QSPI.patch
new file mode 100644
index 0000000..d6168b9
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0029-sandbox64-add-support-for-NVMXIP-QSPI.patch
@@ -0,0 +1,113 @@
+From 2b0606f603de13524ce9b63578f4c3358c3ac6df Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Thu, 22 Dec 2022 12:15:42 +0000
+Subject: [PATCH 29/43] sandbox64: add support for NVMXIP QSPI
+
+enable NVMXIP QSPI for sandbox 64-bit
+
+Adding two NVM XIP QSPI storage devices.
+
+Upstream-Status: Submitted
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ arch/sandbox/dts/sandbox64.dts | 13 +++++++++++++
+ arch/sandbox/dts/test.dts      | 14 ++++++++++++++
+ configs/sandbox_defconfig      |  1 +
+ drivers/nvmxip/nvmxip.c        |  4 ++++
+ drivers/nvmxip/nvmxip.h        |  3 +++
+ 5 files changed, 35 insertions(+)
+
+diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts
+index a9cd7908f83e..aed3801af8a9 100644
+--- a/arch/sandbox/dts/sandbox64.dts
++++ b/arch/sandbox/dts/sandbox64.dts
+@@ -89,6 +89,19 @@
+ 		cs-gpios = <0>, <&gpio_a 0>;
+ 	};
+ 
++	nvmxip-qspi1@08000000 {
++		compatible = "nvmxip,qspi";
++		reg = <0x0 0x08000000 0x0 0x00200000>;
++		lba_shift = <9>;
++		lba = <4096>;
++	};
++
++	nvmxip-qspi2@08200000 {
++		compatible = "nvmxip,qspi";
++		reg = <0x0 0x08200000 0x0 0x00100000>;
++		lba_shift = <9>;
++		lba = <2048>;
++	};
+ };
+ 
+ #include "sandbox.dtsi"
+diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
+index 2e580f980fc6..54f2b308e793 100644
+--- a/arch/sandbox/dts/test.dts
++++ b/arch/sandbox/dts/test.dts
+@@ -1756,6 +1756,20 @@
+ 		compatible = "u-boot,fwu-mdata-gpt";
+ 		fwu-mdata-store = <&mmc0>;
+ 	};
++
++	nvmxip-qspi1@08000000 {
++		compatible = "nvmxip,qspi";
++		reg = <0x08000000 0x00200000>;
++		lba_shift = <9>;
++		lba = <4096>;
++	};
++
++	nvmxip-qspi2@08200000 {
++		compatible = "nvmxip,qspi";
++		reg = <0x08200000 0x00100000>;
++		lba_shift = <9>;
++		lba = <2048>;
++	};
+ };
+ 
+ #include "sandbox_pmic.dtsi"
+diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
+index e6ea96a6b924..f22230b5cce2 100644
+--- a/configs/sandbox_defconfig
++++ b/configs/sandbox_defconfig
+@@ -138,6 +138,7 @@ CONFIG_NETCONSOLE=y
+ CONFIG_IP_DEFRAG=y
+ CONFIG_BOOTP_SERVERIP=y
+ CONFIG_IPV6=y
++CONFIG_NVMXIP_QSPI=y
+ CONFIG_DM_DMA=y
+ CONFIG_DEVRES=y
+ CONFIG_DEBUG_DEVRES=y
+diff --git a/drivers/nvmxip/nvmxip.c b/drivers/nvmxip/nvmxip.c
+index 6ba48183c575..af9c9a3b7270 100644
+--- a/drivers/nvmxip/nvmxip.c
++++ b/drivers/nvmxip/nvmxip.c
+@@ -85,6 +85,10 @@ int nvmxip_init(struct udevice *udev)
+ 	priv_data->udev = udev;
+ 	priv_data->plat_data = plat_data;
+ 
++#if CONFIG_IS_ENABLED(SANDBOX64)
++	sandbox_set_enable_memio(true);
++#endif
++
+ 	nvmxip_bdev_max_devs++;
+ 
+ 	snprintf(bdev_name, NVMXIP_BLKDEV_NAME_SZ, "nvmxip-blk#%d", nvmxip_bdev_max_devs);
+diff --git a/drivers/nvmxip/nvmxip.h b/drivers/nvmxip/nvmxip.h
+index 393172cc2f86..0384ce2e2b47 100644
+--- a/drivers/nvmxip/nvmxip.h
++++ b/drivers/nvmxip/nvmxip.h
+@@ -8,6 +8,9 @@
+ #define __DRIVER_NVMXIP_H__
+ 
+ #include <asm/io.h>
++#if CONFIG_IS_ENABLED(SANDBOX64)
++#include <asm/test.h>
++#endif
+ #include <blk.h>
+ #include <linux/bitops.h>
+ #include <linux/compat.h>
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-corstone1000-add-NVM-XIP-QSPI-device-tree-node.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-corstone1000-add-NVM-XIP-QSPI-device-tree-node.patch
new file mode 100644
index 0000000..21ad210
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0030-corstone1000-add-NVM-XIP-QSPI-device-tree-node.patch
@@ -0,0 +1,35 @@
+From 3f72e390fc8e1a0d774d80c3ccd21be38c9af1db Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Mon, 19 Dec 2022 13:20:19 +0000
+Subject: [PATCH 30/43] corstone1000: add NVM XIP QSPI device tree node
+
+add QSPI flash device node for block storage access
+
+Upstream-Status: Submitted
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ arch/arm/dts/corstone1000.dtsi | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi
+index 61e0c33247ce..faf4e12bab2a 100644
+--- a/arch/arm/dts/corstone1000.dtsi
++++ b/arch/arm/dts/corstone1000.dtsi
+@@ -38,6 +38,13 @@
+ 		reg = <0x88200000 0x77e00000>;
+ 	};
+ 
++	nvmxip-qspi@08000000 {
++		compatible = "nvmxip,qspi";
++		reg = <0x08000000 0x2000000>;
++		lba_shift = <9>;
++		lba = <65536>;
++	};
++
+ 	gic: interrupt-controller@1c000000 {
+ 		compatible = "arm,gic-400";
+ 		#interrupt-cells = <3>;
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-corstone1000-enable-NVM-XIP-QSPI-flash.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-corstone1000-enable-NVM-XIP-QSPI-flash.patch
new file mode 100644
index 0000000..64bf97d
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0031-corstone1000-enable-NVM-XIP-QSPI-flash.patch
@@ -0,0 +1,29 @@
+From 0c3d61d499039ff0828376bb21b4fb1de071b8d2 Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Mon, 19 Dec 2022 13:25:23 +0000
+Subject: [PATCH 31/43] corstone1000: enable NVM XIP QSPI flash
+
+add the QSPI flash device with block storage capability
+
+Upstream-Status: Submitted
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ configs/corstone1000_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
+index 1179bf5f3bfd..2986cc95932f 100644
+--- a/configs/corstone1000_defconfig
++++ b/configs/corstone1000_defconfig
+@@ -58,6 +58,7 @@ CONFIG_DM_SERIAL=y
+ CONFIG_USB=y
+ CONFIG_USB_ISP1760=y
+ CONFIG_ERRNO_STR=y
++CONFIG_NVMXIP_QSPI=y
+ CONFIG_EFI_MM_COMM_TEE=y
+ CONFIG_ARM_FFA_TRANSPORT=y
+ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-sandbox64-add-a-test-case-for-UCLASS_NVMXIP.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-sandbox64-add-a-test-case-for-UCLASS_NVMXIP.patch
new file mode 100644
index 0000000..5724283
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0032-sandbox64-add-a-test-case-for-UCLASS_NVMXIP.patch
@@ -0,0 +1,174 @@
+From 3be91bde755c376a38c3affb9640b39df1acdd9c Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Thu, 22 Dec 2022 11:30:16 +0000
+Subject: [PATCH 32/43] sandbox64: add a test case for UCLASS_NVMXIP
+
+provide a test for NVM XIP devices
+
+The test case allows to make sure of the following:
+
+- The NVM XIP QSPI devices are probed
+- The DT entries are read correctly
+- the data read from the flash by the NVMXIP block driver is correct
+
+Upstream-Status: Submitted
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ MAINTAINERS      |   1 +
+ test/dm/Makefile |   4 ++
+ test/dm/nvmxip.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 120 insertions(+)
+ create mode 100644 test/dm/nvmxip.c
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index ba15dd02d58d..82cb6075cb32 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -1210,6 +1210,7 @@ S:	Maintained
+ F:	doc/develop/driver-model/nvmxip.rst
+ F:	doc/device-tree-bindings/nvmxip/nvmxip.txt
+ F:	drivers/nvmxip/
++F:	test/dm/nvmxip.c
+ 
+ NVMEM
+ M:	Sean Anderson <seanga2@gmail.com>
+diff --git a/test/dm/Makefile b/test/dm/Makefile
+index 85e99e1c120e..bc8214da2da2 100644
+--- a/test/dm/Makefile
++++ b/test/dm/Makefile
+@@ -18,6 +18,10 @@ obj-$(CONFIG_UT_DM) += test-uclass.o
+ obj-$(CONFIG_UT_DM) += core.o
+ obj-$(CONFIG_UT_DM) += read.o
+ obj-$(CONFIG_UT_DM) += phys2bus.o
++ifeq ($(CONFIG_NVMXIP_QSPI)$(CONFIG_SANDBOX64),yy)
++obj-y += nvmxip.o
++endif
++
+ ifneq ($(CONFIG_SANDBOX),)
+ ifeq ($(CONFIG_ACPIGEN),y)
+ obj-y += acpi.o
+diff --git a/test/dm/nvmxip.c b/test/dm/nvmxip.c
+new file mode 100644
+index 000000000000..484e6077b4a9
+--- /dev/null
++++ b/test/dm/nvmxip.c
+@@ -0,0 +1,115 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Functional tests for UCLASS_FFA  class
++ *
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#include <common.h>
++#include <console.h>
++#include <blk.h>
++#include <dm.h>
++#include <dm/test.h>
++#include "../../drivers/nvmxip/nvmxip.h"
++#include <test/test.h>
++#include <test/ut.h>
++
++/* NVMXIP devices described in the device tree  */
++#define SANDBOX_NVMXIP_DEVICES 2
++
++/* reference device tree data for the probed devices */
++static struct nvmxip_plat nvmqspi_refdata[SANDBOX_NVMXIP_DEVICES] = {
++	{0x08000000, 9, 4096}, {0x08200000, 9, 2048}
++};
++
++#define NVMXIP_BLK_START_PATTERN 0x1122334455667788ULL
++#define NVMXIP_BLK_END_PATTERN 0xa1a2a3a4a5a6a7a8ULL
++
++static int dm_nvmxip_flash_sanity(u8 device_idx, void *buffer)
++{
++	int i;
++	u64 *ptr = NULL;
++	u8 *base = NULL;
++	unsigned long blksz;
++
++	blksz = 1 << nvmqspi_refdata[device_idx].lba_shift;
++
++	/* if buffer not NULL, init the flash with the pattern data*/
++	if (!buffer)
++		base = map_sysmem(nvmqspi_refdata[device_idx].phys_base, 0);
++	else
++		base = buffer;
++
++	for (i = 0; i < nvmqspi_refdata[device_idx].lba ; i++) {
++		ptr = (u64 *)(base + i * blksz);
++
++		/* write an 8 bytes pattern at the start of the current block*/
++		if (!buffer)
++			*ptr = NVMXIP_BLK_START_PATTERN;
++		else if (*ptr != NVMXIP_BLK_START_PATTERN)
++			return -EINVAL;
++
++		ptr = (u64 *)((u8 *)ptr + blksz - sizeof(u64));
++
++		/* write an 8 bytes pattern at the end of the current block*/
++		if (!buffer)
++			*ptr = NVMXIP_BLK_END_PATTERN;
++		else if (*ptr != NVMXIP_BLK_END_PATTERN)
++			return -EINVAL;
++	}
++
++	if (!buffer)
++		unmap_sysmem(base);
++
++	return 0;
++}
++
++static int dm_test_nvmxip(struct unit_test_state *uts)
++{
++	struct nvmxip_plat *plat_data = NULL;
++	struct udevice *dev = NULL, *bdev = NULL;
++	u8 device_idx;
++	void *buffer = NULL;
++	unsigned long flashsz;
++
++	/* set the flash content first for both devices */
++	dm_nvmxip_flash_sanity(0, NULL);
++	dm_nvmxip_flash_sanity(1, NULL);
++
++	/*  probing all NVM XIP QSPI devices */
++	for (device_idx = 0, uclass_first_device(UCLASS_NVMXIP, &dev);
++	     dev;
++	     uclass_next_device(&dev), device_idx++) {
++		plat_data = dev_get_plat(dev);
++
++		/* device tree entries checks */
++		ut_assertok(nvmqspi_refdata[device_idx].phys_base != plat_data->phys_base);
++		ut_assertok(nvmqspi_refdata[device_idx].lba_shift != plat_data->lba_shift);
++		ut_assertok(nvmqspi_refdata[device_idx].lba != plat_data->lba);
++
++		/* before reading all the flash blocks, let's calculate the flash size */
++		flashsz = plat_data->lba << plat_data->lba_shift;
++
++		/* allocate the user buffer where to copy the blocks data to */
++		buffer = calloc(flashsz, 1);
++		ut_assertok(!buffer);
++
++		/* the block device is the child of the parent device probed with DT*/
++		ut_assertok(device_find_first_child(dev, &bdev));
++
++		/* reading all the flash blocks*/
++		ut_asserteq(plat_data->lba, blk_read(bdev, 0, plat_data->lba, buffer));
++
++		/* compare the data read from flash with the expected data */
++		ut_assertok(dm_nvmxip_flash_sanity(device_idx, buffer));
++
++		free(buffer);
++	}
++
++	ut_assertok(device_idx != SANDBOX_NVMXIP_DEVICES);
++
++	return CMD_RET_SUCCESS;
++}
++
++DM_TEST(dm_test_nvmxip, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-nvmxip-provide-a-u-boot-shell-test-command.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-nvmxip-provide-a-u-boot-shell-test-command.patch
new file mode 100644
index 0000000..e8adbc1
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0033-nvmxip-provide-a-u-boot-shell-test-command.patch
@@ -0,0 +1,135 @@
+From 560ebe3eb6197322b9d00c8e3cf30fb7e679d8b2 Mon Sep 17 00:00:00 2001
+From: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Date: Thu, 22 Dec 2022 16:20:46 +0000
+Subject: [PATCH 33/43] nvmxip: provide a u-boot shell test command
+
+nvmxip command allows probing the NVM XIP devices manually
+
+The command is provided for test purposes only.
+
+Use:
+
+nvmxip probe
+
+Upstream-Status: Submitted
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ cmd/Kconfig                    |  7 +++++
+ cmd/Makefile                   |  1 +
+ cmd/nvmxip.c                   | 47 ++++++++++++++++++++++++++++++++++
+ configs/corstone1000_defconfig |  1 +
+ configs/sandbox_defconfig      |  1 +
+ 5 files changed, 57 insertions(+)
+ create mode 100644 cmd/nvmxip.c
+
+diff --git a/cmd/Kconfig b/cmd/Kconfig
+index 5e278ecb1597..b6a3e5908534 100644
+--- a/cmd/Kconfig
++++ b/cmd/Kconfig
+@@ -938,6 +938,13 @@ config CMD_ARMFFA
+ 		- Sending a data pattern to the specified partition
+ 		- Displaying the arm_ffa device info
+ 
++config CMD_NVMXIP
++	bool "NVM XIP probe command"
++	depends on NVMXIP
++	help
++	  Probes all NVM XIP devices. The command is for
++	  test purposes only (not to be upstreamed)
++
+ config CMD_ARMFLASH
+ 	#depends on FLASH_CFI_DRIVER
+ 	bool "armflash"
+diff --git a/cmd/Makefile b/cmd/Makefile
+index c757f1647da6..0a3d98100703 100644
+--- a/cmd/Makefile
++++ b/cmd/Makefile
+@@ -154,6 +154,7 @@ obj-$(CONFIG_CMD_RTC) += rtc.o
+ obj-$(CONFIG_SANDBOX) += host.o
+ obj-$(CONFIG_CMD_SATA) += sata.o
+ obj-$(CONFIG_CMD_NVME) += nvme.o
++obj-$(CONFIG_CMD_NVMXIP) += nvmxip.o
+ obj-$(CONFIG_SANDBOX) += sb.o
+ obj-$(CONFIG_CMD_SF) += sf.o
+ obj-$(CONFIG_CMD_SCSI) += scsi.o disk.o
+diff --git a/cmd/nvmxip.c b/cmd/nvmxip.c
+new file mode 100644
+index 000000000000..3eb0d84afc04
+--- /dev/null
++++ b/cmd/nvmxip.c
+@@ -0,0 +1,47 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * (C) Copyright 2022 ARM Limited
++ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
++ */
++
++#include <common.h>
++#include <command.h>
++#include <dm.h>
++
++int do_nvmxip_probe(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
++{
++	struct udevice *dev = NULL;
++	for (uclass_first_device(UCLASS_NVMXIP, &dev); dev; uclass_next_device(&dev));
++
++	return 0;
++}
++
++static struct cmd_tbl nvmxip_commands[] = {
++	U_BOOT_CMD_MKENT(probe, 1, 1, do_nvmxip_probe, "", ""),
++};
++
++static int do_nvmxip(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
++{
++	struct cmd_tbl *nvmxip_cmd;
++	int ret;
++
++	if (argc < 2)
++		return CMD_RET_USAGE;
++
++	nvmxip_cmd = find_cmd_tbl(argv[1], nvmxip_commands, ARRAY_SIZE(nvmxip_commands));
++
++	argc -= 2;
++	argv += 2;
++
++	if (!nvmxip_cmd || argc > nvmxip_cmd->maxargs)
++		return CMD_RET_USAGE;
++
++	ret = nvmxip_cmd->cmd(nvmxip_cmd, flag, argc, argv);
++
++	return cmd_process_error(nvmxip_cmd, ret);
++}
++
++U_BOOT_CMD(nvmxip, 4, 1, do_nvmxip,
++	   "NVM XIP probe command",
++	   "probe\n"
++	"	 - probes all NVM XIP devices\n");
+diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
+index 2986cc95932f..e009faee0252 100644
+--- a/configs/corstone1000_defconfig
++++ b/configs/corstone1000_defconfig
+@@ -59,6 +59,7 @@ CONFIG_USB=y
+ CONFIG_USB_ISP1760=y
+ CONFIG_ERRNO_STR=y
+ CONFIG_NVMXIP_QSPI=y
++CONFIG_CMD_NVMXIP=y
+ CONFIG_EFI_MM_COMM_TEE=y
+ CONFIG_ARM_FFA_TRANSPORT=y
+ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
+index f22230b5cce2..3b895be9e4ba 100644
+--- a/configs/sandbox_defconfig
++++ b/configs/sandbox_defconfig
+@@ -139,6 +139,7 @@ CONFIG_IP_DEFRAG=y
+ CONFIG_BOOTP_SERVERIP=y
+ CONFIG_IPV6=y
+ CONFIG_NVMXIP_QSPI=y
++CONFIG_CMD_NVMXIP=y
+ CONFIG_DM_DMA=y
+ CONFIG_DEVRES=y
+ CONFIG_DEBUG_DEVRES=y
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-corstone1000-add-fwu-metadata-store-info.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-corstone1000-add-fwu-metadata-store-info.patch
new file mode 100644
index 0000000..facd19b
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0034-corstone1000-add-fwu-metadata-store-info.patch
@@ -0,0 +1,42 @@
+From 9ef889ff89e6d2e2e40edecbd4ab7601c3d68052 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Wed, 1 Feb 2023 15:58:07 +0000
+Subject: [PATCH 34/43] corstone1000: add fwu-metadata store info
+
+Add fwu-mdata node and handle for the reference
+nvmxip-qspi.
+
+Upstream-Status: Submitted
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ arch/arm/dts/corstone1000.dtsi | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/dts/corstone1000.dtsi b/arch/arm/dts/corstone1000.dtsi
+index faf4e12bab2a..b1d83b5ba861 100644
+--- a/arch/arm/dts/corstone1000.dtsi
++++ b/arch/arm/dts/corstone1000.dtsi
+@@ -38,7 +38,7 @@
+ 		reg = <0x88200000 0x77e00000>;
+ 	};
+ 
+-	nvmxip-qspi@08000000 {
++	nvmxip: nvmxip-qspi@08000000 {
+ 		compatible = "nvmxip,qspi";
+ 		reg = <0x08000000 0x2000000>;
+ 		lba_shift = <9>;
+@@ -106,6 +106,11 @@
+ 		method = "smc";
+ 	};
+ 
++	fwu-mdata {
++		compatible = "u-boot,fwu-mdata-gpt";
++		fwu-mdata-store = <&nvmxip>;
++	};
++
+ 	soc {
+ 		compatible = "simple-bus";
+ 		#address-cells = <1>;
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-nvmxip-shorter-block-device-name.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-nvmxip-shorter-block-device-name.patch
new file mode 100644
index 0000000..74e4ccb
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0035-nvmxip-shorter-block-device-name.patch
@@ -0,0 +1,44 @@
+From 83823733015998702e4dc0365764fe7dde4a321f Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Wed, 1 Feb 2023 15:59:36 +0000
+Subject: [PATCH 35/43] nvmxip: shorter block device name
+
+Make the block device name shorter, so it will be set and presented
+inside the array limits.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ drivers/nvmxip/nvmxip.c      | 2 +-
+ drivers/nvmxip/nvmxip_qspi.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/nvmxip/nvmxip.c b/drivers/nvmxip/nvmxip.c
+index af9c9a3b7270..91fe995f2d4d 100644
+--- a/drivers/nvmxip/nvmxip.c
++++ b/drivers/nvmxip/nvmxip.c
+@@ -91,7 +91,7 @@ int nvmxip_init(struct udevice *udev)
+ 
+ 	nvmxip_bdev_max_devs++;
+ 
+-	snprintf(bdev_name, NVMXIP_BLKDEV_NAME_SZ, "nvmxip-blk#%d", nvmxip_bdev_max_devs);
++	snprintf(bdev_name, NVMXIP_BLKDEV_NAME_SZ, "blk#%d", nvmxip_bdev_max_devs);
+ 
+ 	ret = blk_create_devicef(udev, NVMXIP_BLKDRV_NAME, bdev_name, UCLASS_NVMXIP,
+ 				 nvmxip_bdev_max_devs, NVMXIP_DEFAULT_LBA_SZ,
+diff --git a/drivers/nvmxip/nvmxip_qspi.c b/drivers/nvmxip/nvmxip_qspi.c
+index 749625134acd..f6f5435e6377 100644
+--- a/drivers/nvmxip/nvmxip_qspi.c
++++ b/drivers/nvmxip/nvmxip_qspi.c
+@@ -43,7 +43,7 @@ static int nvmxip_qspi_of_to_plat(struct udevice *dev)
+ 		return -EINVAL;
+ 	}
+ 
+-	pr_debug("[%s]: XIP device base addr: 0x%llx , lba_shift: %d , lbas: %lu\n",
++	log_err("[%s]: XIP device base addr: 0x%llx , lba_shift: %d , lbas: %lu\n",
+ 		 dev->name, plat_data->phys_base, plat_data->lba_shift, plat_data->lba);
+ 
+ 	return 0;
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-efi_boottime-allow-to-reset-a-path-after-boot.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-efi_boottime-allow-to-reset-a-path-after-boot.patch
new file mode 100644
index 0000000..59a60af
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0036-efi_boottime-allow-to-reset-a-path-after-boot.patch
@@ -0,0 +1,31 @@
+From 53d29d35cdbcf493f6a9046458947d3e91f01add Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Wed, 1 Feb 2023 16:11:25 +0000
+Subject: [PATCH 36/43] efi_boottime: allow to reset a path after boot
+
+Allow to install multiple protocol interfaces in an
+already installed root interface.
+This may need to be fix in other way, but for now
+looks like the get away fix.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ lib/efi_loader/efi_boottime.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
+index fea4eb7a342e..90f43ff9a62f 100644
+--- a/lib/efi_loader/efi_boottime.c
++++ b/lib/efi_loader/efi_boottime.c
+@@ -2669,7 +2669,6 @@ efi_install_multiple_protocol_interfaces_int(efi_handle_t *handle,
+ 				EFI_PRINT("Path %pD already installed\n",
+ 					  protocol_interface);
+ 				ret = EFI_ALREADY_STARTED;
+-				break;
+ 			}
+ 		}
+ 		ret = EFI_CALL(efi_install_protocol_interface(handle, protocol,
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-fwu_metadata-make-sure-structures-are-packed.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-fwu_metadata-make-sure-structures-are-packed.patch
new file mode 100644
index 0000000..7781a1e
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0037-fwu_metadata-make-sure-structures-are-packed.patch
@@ -0,0 +1,50 @@
+From a8142be9b32a769040b6238ff611c22cb31c8cb5 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Wed, 1 Feb 2023 16:13:24 +0000
+Subject: [PATCH 37/43] fwu_metadata: make sure structures are packed
+
+The fwu metadata in the metadata partitions
+should/are packed to guarantee that the info is
+correct in all platforms. Also the size of them
+are used to calculate the crc32 and that is important
+to get it right.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ include/fwu_mdata.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/include/fwu_mdata.h b/include/fwu_mdata.h
+index 8fda4f4ac225..c61221a91735 100644
+--- a/include/fwu_mdata.h
++++ b/include/fwu_mdata.h
+@@ -22,7 +22,7 @@ struct fwu_image_bank_info {
+ 	efi_guid_t  image_uuid;
+ 	uint32_t accepted;
+ 	uint32_t reserved;
+-};
++} __packed;
+ 
+ /**
+  * struct fwu_image_entry - information for a particular type of image
+@@ -38,7 +38,7 @@ struct fwu_image_entry {
+ 	efi_guid_t image_type_uuid;
+ 	efi_guid_t location_uuid;
+ 	struct fwu_image_bank_info img_bank_info[CONFIG_FWU_NUM_BANKS];
+-};
++} __packed;
+ 
+ /**
+  * struct fwu_mdata - FWU metadata structure for multi-bank updates
+@@ -62,6 +62,6 @@ struct fwu_mdata {
+ 	uint32_t previous_active_index;
+ 
+ 	struct fwu_image_entry img_entry[CONFIG_FWU_NUM_IMAGES_PER_BANK];
+-};
++} __packed;
+ 
+ #endif /* _FWU_MDATA_H_ */
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0038-corstone1000-add-boot-index.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0038-corstone1000-add-boot-index.patch
new file mode 100644
index 0000000..afaf967
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0038-corstone1000-add-boot-index.patch
@@ -0,0 +1,33 @@
+From ceae4ec0d459b1ef12e544f4e36d6043a09d3b05 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Wed, 1 Feb 2023 16:15:30 +0000
+Subject: [PATCH 38/43] corstone1000: add boot index
+
+it is expected that the firmware that runs before
+u-boot somehow provide the information of the bank
+(index) of it is booting.
+We will need to extend tf-a to pass that info,
+meanwhile just set it to the default bank.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ board/armltd/corstone1000/corstone1000.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
+index d6ca6e896140..0a58ccd99cdd 100644
+--- a/board/armltd/corstone1000/corstone1000.c
++++ b/board/armltd/corstone1000/corstone1000.c
+@@ -106,6 +106,7 @@ int dram_init_banksize(void)
+ 	return 0;
+ }
+ 
+-void reset_cpu(ulong addr)
++void fwu_plat_get_bootidx(int *boot_idx)
+ {
++	*boot_idx = 0;
+ }
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-corstone1000-adjust-boot-bank-and-kernel-location.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-corstone1000-adjust-boot-bank-and-kernel-location.patch
new file mode 100644
index 0000000..a42b3a2
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0039-corstone1000-adjust-boot-bank-and-kernel-location.patch
@@ -0,0 +1,36 @@
+From 80a2910370b0acc35f6fb2fbe3a7e56fecb1a08a Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Wed, 1 Feb 2023 16:17:21 +0000
+Subject: [PATCH 39/43] corstone1000: adjust boot bank and kernel location
+
+Adjust in the env boot script the address of the
+bootbank with the new gpt layout, and also the
+kernel partition address. Please be aware that
+this is hack and needs a proper fix, since the
+offset of the kernel partition is not fixed,
+but for the propose of PoC it is enough for testing.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ board/armltd/corstone1000/corstone1000.env | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/board/armltd/corstone1000/corstone1000.env b/board/armltd/corstone1000/corstone1000.env
+index b24ff07fc6bd..a6ee4962211b 100644
+--- a/board/armltd/corstone1000/corstone1000.env
++++ b/board/armltd/corstone1000/corstone1000.env
+@@ -1,8 +1,8 @@
+ /* SPDX-License-Identifier: GPL-2.0+ */
+ 
+ usb_pgood_delay=250
+-boot_bank_flag=0x08002000
+-kernel_addr_bank_0=0x083EE000
++boot_bank_flag=0x08005006
++kernel_addr_bank_0=0x08280000
+ kernel_addr_bank_1=0x0936E000
+ retrieve_kernel_load_addr=
+ 	if itest.l *${boot_bank_flag} == 0; then
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0040-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0040-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch
new file mode 100644
index 0000000..d1fa8ff
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0040-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch
@@ -0,0 +1,133 @@
+From 7c694af3fd5de372349f740b62cd3d909483fe2e Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Wed, 1 Feb 2023 16:19:40 +0000
+Subject: [PATCH 40/43] corstone1000: add nvmxip, fwu-mdata and gpt options
+
+Enable the newest features: nvmxip, fwu-metadata and
+gpt. Commands to print the partition info, gpt info
+and fwu metadata will be available.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ configs/corstone1000_defconfig | 31 +++++++++++++++++++------------
+ fs/fs.c                        |  5 +++++
+ 2 files changed, 24 insertions(+), 12 deletions(-)
+
+diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
+index e009faee0252..711cf13592db 100644
+--- a/configs/corstone1000_defconfig
++++ b/configs/corstone1000_defconfig
+@@ -4,13 +4,15 @@ CONFIG_TARGET_CORSTONE1000=y
+ CONFIG_TEXT_BASE=0x80000000
+ CONFIG_SYS_MALLOC_LEN=0x2000000
+ CONFIG_NR_DRAM_BANKS=1
++CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
++CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x83f00000
++CONFIG_DM_GPIO=y
+ CONFIG_DEFAULT_DEVICE_TREE="corstone1000-mps3"
+ CONFIG_SYS_PROMPT="corstone1000# "
+ CONFIG_IDENT_STRING=" corstone1000 aarch64 "
+ CONFIG_SYS_LOAD_ADDR=0x82100000
++CONFIG_FWU_NUM_IMAGES_PER_BANK=4
+ CONFIG_DISTRO_DEFAULTS=y
+-CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
+-CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x83f00000
+ CONFIG_FIT=y
+ CONFIG_BOOTDELAY=3
+ CONFIG_USE_BOOTARGS=y
+@@ -23,11 +25,16 @@ CONFIG_LOGLEVEL=7
+ CONFIG_SYS_MAXARGS=64
+ CONFIG_SYS_CBSIZE=512
+ # CONFIG_CMD_CONSOLE is not set
++CONFIG_CMD_FWU_METADATA=y
+ CONFIG_CMD_BOOTZ=y
+ CONFIG_SYS_BOOTM_LEN=0x800000
+ # CONFIG_CMD_XIMG is not set
++CONFIG_CMD_NVMXIP=y
++CONFIG_CMD_GPT=y
++# CONFIG_RANDOM_UUID is not set
+ CONFIG_CMD_LOADM=y
+ # CONFIG_CMD_LOADS is not set
++CONFIG_CMD_MMC=y
+ CONFIG_CMD_USB=y
+ # CONFIG_CMD_SETEXPR is not set
+ # CONFIG_CMD_NFS is not set
+@@ -39,29 +46,29 @@ CONFIG_OF_CONTROL=y
+ CONFIG_VERSION_VARIABLE=y
+ CONFIG_NET_RANDOM_ETHADDR=y
+ CONFIG_REGMAP=y
+-CONFIG_MISC=y
++CONFIG_ARM_FFA_TRANSPORT=y
+ CONFIG_CLK=y
+-CONFIG_CMD_MMC=y
+-CONFIG_DM_MMC=y
++CONFIG_FWU_MDATA=y
++CONFIG_FWU_MDATA_GPT_BLK=y
++CONFIG_MISC=y
+ CONFIG_ARM_PL180_MMCI=y
+-CONFIG_MMC_SDHCI_ADMA_HELPERS=y
+-CONFIG_MMC_WRITE=y
+-CONFIG_DM_GPIO=y
+ CONFIG_PHYLIB=y
+ CONFIG_PHY_SMSC=y
+ CONFIG_SMC911X=y
++CONFIG_NVMXIP_QSPI=y
+ CONFIG_PHY=y
+ CONFIG_RAM=y
+ CONFIG_DM_RTC=y
+ CONFIG_RTC_EMULATION=y
+ CONFIG_DM_SERIAL=y
++CONFIG_SYSRESET=y
+ CONFIG_USB=y
+ CONFIG_USB_ISP1760=y
+ CONFIG_ERRNO_STR=y
+-CONFIG_NVMXIP_QSPI=y
+-CONFIG_CMD_NVMXIP=y
+ CONFIG_EFI_MM_COMM_TEE=y
+-CONFIG_ARM_FFA_TRANSPORT=y
+ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
++CONFIG_EFI_CAPSULE_ON_DISK=y
++CONFIG_EFI_IGNORE_OSINDICATIONS=y
+ CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
+-CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
++CONFIG_FWU_MULTI_BANK_UPDATE=y
++# CONFIG_TOOLS_MKEFICAPSULE is not set
+diff --git a/fs/fs.c b/fs/fs.c
+index 8324b4a22f20..f54955a2b7f6 100644
+--- a/fs/fs.c
++++ b/fs/fs.c
+@@ -437,11 +437,13 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
+ 	}
+ #endif
+ 
++	log_err("RUI: fs_set_blk_dev fstype: %d\n", fstype);
+ 	part = part_get_info_by_dev_and_name_or_num(ifname, dev_part_str, &fs_dev_desc,
+ 						    &fs_partition, 1);
+ 	if (part < 0)
+ 		return -1;
+ 
++	log_err("RUI: fs_set_blk_dev 1\n");
+ 	for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) {
+ 		if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY &&
+ 				fstype != info->fstype)
+@@ -450,6 +452,8 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
+ 		if (!fs_dev_desc && !info->null_dev_desc_ok)
+ 			continue;
+ 
++		log_err("RUI: fs_set_blk_dev 2: info->fstype: %d part: %d\n",
++			info->fstype, part);
+ 		if (!info->probe(fs_dev_desc, &fs_partition)) {
+ 			fs_type = info->fstype;
+ 			fs_dev_part = part;
+@@ -457,6 +461,7 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
+ 		}
+ 	}
+ 
++	log_err("RUI: fs_set_blk_dev 3\n");
+ 	return -1;
+ }
+ 
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0041-nvmxip-move-header-to-include.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0041-nvmxip-move-header-to-include.patch
new file mode 100644
index 0000000..4e4ae17
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0041-nvmxip-move-header-to-include.patch
@@ -0,0 +1,42 @@
+From 37b3c73d9307d1de3b78e3ccba0ba6ba0867d6b8 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Thu, 23 Feb 2023 10:32:04 +0000
+Subject: [PATCH 41/43] nvmxip: move header to include
+
+Move header to include to allow external code
+to get the internal bdev structures to access
+block device operations.
+
+as at it, just add the UCLASS_NVMXIP string
+so we get the correct output in partitions
+listing.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ disk/part.c                          | 3 +++
+ {drivers/nvmxip => include}/nvmxip.h | 0
+ 2 files changed, 3 insertions(+)
+ rename {drivers/nvmxip => include}/nvmxip.h (100%)
+
+diff --git a/disk/part.c b/disk/part.c
+index 5ee60a7fb591..593dd0004fa4 100644
+--- a/disk/part.c
++++ b/disk/part.c
+@@ -270,6 +270,9 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc)
+ 	case UCLASS_NVME:
+ 		puts ("NVMe");
+ 		break;
++	case UCLASS_NVMXIP:
++		puts ("NVMXIP");
++		break;
+ 	case UCLASS_PVBLOCK:
+ 		puts("PV BLOCK");
+ 		break;
+diff --git a/drivers/nvmxip/nvmxip.h b/include/nvmxip.h
+similarity index 100%
+rename from drivers/nvmxip/nvmxip.h
+rename to include/nvmxip.h
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0042-corstone1000-set-kernel_addr-based-on-boot_idx.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0042-corstone1000-set-kernel_addr-based-on-boot_idx.patch
new file mode 100644
index 0000000..25e248b
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0042-corstone1000-set-kernel_addr-based-on-boot_idx.patch
@@ -0,0 +1,112 @@
+From e8272dc9390adfd0818d1093c83f3b5c07649a95 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Thu, 23 Feb 2023 10:35:00 +0000
+Subject: [PATCH 42/43] corstone1000: set kernel_addr based on boot_idx
+
+We need to distinguish between boot banks and from which
+partition to load the kernel+initramfs to memory.
+
+For that, fetch the boot index, fetch the correspondent
+partition, calculate the correct kernel address and
+then set the env variable kernel_addr with that value.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ board/armltd/corstone1000/corstone1000.c | 55 +++++++++++++++++++++++-
+ configs/corstone1000_defconfig           |  1 +
+ 2 files changed, 55 insertions(+), 1 deletion(-)
+
+diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
+index 0a58ccd99cdd..0923ca6e8c5b 100644
+--- a/board/armltd/corstone1000/corstone1000.c
++++ b/board/armltd/corstone1000/corstone1000.c
+@@ -5,13 +5,23 @@
+  * Rui Miguel Silva <rui.silva@linaro.org>
+  */
+ 
++#include <blk.h>
+ #include <common.h>
+ #include <dm.h>
++#include <env.h>
+ #include <netdev.h>
++#include <nvmxip.h>
++#include <part.h>
+ #include <dm/platform_data/serial_pl01x.h>
+ #include <asm/armv8/mmu.h>
+ #include <asm/global_data.h>
+ 
++#define CORSTONE1000_KERNEL_PARTS 2
++#define CORSTONE1000_KERNEL_PRIMARY "kernel_primary"
++#define CORSTONE1000_KERNEL_SECONDARY "kernel_secondary"
++
++static int corstone1000_boot_idx;
++
+ static struct mm_region corstone1000_mem_map[] = {
+ 	{
+ 		/* CVM */
+@@ -108,5 +118,48 @@ int dram_init_banksize(void)
+ 
+ void fwu_plat_get_bootidx(int *boot_idx)
+ {
+-	*boot_idx = 0;
++	*boot_idx = corstone1000_boot_idx;
++}
++
++int board_late_init(void)
++{
++	struct disk_partition part_info;
++	struct udevice *dev, *bdev;
++	struct nvmxip_plat *plat;
++	struct blk_desc *desc;
++	int ret;
++
++	ret = uclass_first_device_err(UCLASS_NVMXIP, &dev);
++	if (ret < 0) {
++		log_err("Cannot find kernel device\n");
++		return ret;
++	}
++
++	plat = dev_get_plat(dev);
++	device_find_first_child(dev, &bdev);
++	desc = dev_get_uclass_plat(bdev);
++
++	if (!corstone1000_boot_idx)
++		ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_PRIMARY,
++					    &part_info);
++	else
++		ret = part_get_info_by_name(desc, CORSTONE1000_KERNEL_SECONDARY,
++					    &part_info);
++
++	if (ret < 0) {
++		log_err("failed to fetch kernel partition index: %d\n",
++			corstone1000_boot_idx);
++		return ret;
++	}
++
++	ret = 0;
++
++	ret |= env_set_hex("kernel_addr", plat->phys_base +
++			   (part_info.start * part_info.blksz));
++	ret |= env_set_hex("kernel_size", part_info.size * part_info.blksz);
++
++	if (ret < 0)
++		log_err("failed to setup kernel addr and size\n");
++
++	return ret;
+ }
+diff --git a/configs/corstone1000_defconfig b/configs/corstone1000_defconfig
+index 711cf13592db..68054f755624 100644
+--- a/configs/corstone1000_defconfig
++++ b/configs/corstone1000_defconfig
+@@ -22,6 +22,7 @@ CONFIG_CONSOLE_RECORD=y
+ CONFIG_LOGLEVEL=7
+ # CONFIG_DISPLAY_CPUINFO is not set
+ # CONFIG_DISPLAY_BOARDINFO is not set
++CONFIG_BOARD_LATE_INIT=y
+ CONFIG_SYS_MAXARGS=64
+ CONFIG_SYS_CBSIZE=512
+ # CONFIG_CMD_CONSOLE is not set
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0043-corstone1000-boot-index-from-active.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0043-corstone1000-boot-index-from-active.patch
new file mode 100644
index 0000000..9080ecb
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/corstone1000/0043-corstone1000-boot-index-from-active.patch
@@ -0,0 +1,42 @@
+From b32aee10c66a9c2a3b6b948ad957deca3391c4bf Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Mon, 27 Feb 2023 14:40:13 +0000
+Subject: [PATCH 43/43] corstone1000: boot index from active
+
+In our platform, the Secure Enclave is the one who control
+all the boot tries and status, so, every time we get here
+we know that the we are booting from the active index.
+
+Upstream-Status: Pending
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+---
+ board/armltd/corstone1000/corstone1000.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/board/armltd/corstone1000/corstone1000.c b/board/armltd/corstone1000/corstone1000.c
+index 0923ca6e8c5b..e949edb79745 100644
+--- a/board/armltd/corstone1000/corstone1000.c
++++ b/board/armltd/corstone1000/corstone1000.c
+@@ -118,7 +118,18 @@ int dram_init_banksize(void)
+ 
+ void fwu_plat_get_bootidx(int *boot_idx)
+ {
+-	*boot_idx = corstone1000_boot_idx;
++	int ret;
++
++	/*
++	 * in our platform, the Secure Enclave is the one who control
++	 * all the boot tries and status, so, every time we get here
++	 * we know that the we are booting from the active index
++	 */
++	ret = fwu_get_active_index(boot_idx);
++	if (ret < 0)
++		log_err("corstone1000: failed to read active index\n");
++
++	return ret;
+ }
+ 
+ int board_late_init(void)
+-- 
+2.39.2
+
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0001-Add-vexpress_aemv8a_aarch32-variant.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0001-Add-vexpress_aemv8a_aarch32-variant.patch
deleted file mode 100644
index 5138335..0000000
--- a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0001-Add-vexpress_aemv8a_aarch32-variant.patch
+++ /dev/null
@@ -1,184 +0,0 @@
-From 424d186ab0a0c4dd62dfb13ac87e8d1fd26c101e Mon Sep 17 00:00:00 2001
-From: Anders Dellien <anders.dellien@arm.com>
-Date: Thu, 23 Jul 2020 17:32:55 +0100
-Subject: [PATCH 1/2] Add vexpress_aemv8a_aarch32 variant
-
-The ARM AEMv8 FVP model can be run in Aarch64 or Aarch32 mode. Aarch32
-support is enable per-CPU when launching the model, eg:
-
--C cluster0.cpu0.CONFIG64=0
-
-This patch adds a new defconfig and some variant specific selections in
-vexpress_armv8a.h.
-
-This patch is co-authored with Soby Mathew <Soby.Mathew@arm.com>.
-
-Upstream-Status: Denied
-
-For upstream discussion, please visit
-https://www.mail-archive.com/u-boot@lists.denx.de/msg233429.html
-
-Signed-off-by: Ryan Harkin <ryan.harkin@linaro.org>
-Signed-off-by: Asha R <asha.r@arm.com>
-Signed-off-by: Anders Dellien <anders.dellien@arm.com>
----
- arch/arm/Kconfig                          |  5 +++
- board/armltd/vexpress64/Kconfig           |  2 +-
- configs/vexpress_aemv8a_aarch32_defconfig | 40 ++++++++++++++++++
- include/configs/vexpress_aemv8.h          | 50 +++++++++++++++--------
- 4 files changed, 80 insertions(+), 17 deletions(-)
- create mode 100644 configs/vexpress_aemv8a_aarch32_defconfig
-
-diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index 4567c183fb84..99cc414d6760 100644
---- a/arch/arm/Kconfig
-+++ b/arch/arm/Kconfig
-@@ -1250,6 +1250,11 @@ config TARGET_VEXPRESS64_BASE_FVP
- 	select PL01X_SERIAL
- 	select SEMIHOSTING
- 
-+config TARGET_VEXPRESS64_BASE_FVP_AARCH32
-+        bool "Support Versatile Express ARMv8a 32-bit FVP BASE model"
-+        select CPU_V7A
-+        select SEMIHOSTING
-+
- config TARGET_VEXPRESS64_JUNO
- 	bool "Support Versatile Express Juno Development Platform"
- 	select ARM64
-diff --git a/board/armltd/vexpress64/Kconfig b/board/armltd/vexpress64/Kconfig
-index 4aab3f092ecb..0a5e3fcc004a 100644
---- a/board/armltd/vexpress64/Kconfig
-+++ b/board/armltd/vexpress64/Kconfig
-@@ -1,4 +1,4 @@
--if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO
-+if TARGET_VEXPRESS64_BASE_FVP || TARGET_VEXPRESS64_JUNO || TARGET_VEXPRESS64_BASE_FVP_AARCH32
- 
- config SYS_BOARD
- 	default "vexpress64"
-diff --git a/configs/vexpress_aemv8a_aarch32_defconfig b/configs/vexpress_aemv8a_aarch32_defconfig
-new file mode 100644
-index 000000000000..9c5c3367ec4d
---- /dev/null
-+++ b/configs/vexpress_aemv8a_aarch32_defconfig
-@@ -0,0 +1,40 @@
-+CONFIG_ARM=y
-+CONFIG_SYS_ARCH_TIMER=y
-+CONFIG_TARGET_VEXPRESS64_BASE_FVP_AARCH32=y
-+CONFIG_SYS_TEXT_BASE=0x88000000
-+CONFIG_SYS_MALLOC_F_LEN=0x2000
-+CONFIG_NR_DRAM_BANKS=2
-+CONFIG_IDENT_STRING=" vexpress_aemv8a fvp aarch32"
-+CONFIG_REMAKE_ELF=y
-+CONFIG_SYS_LOAD_ADDR=0x90000000
-+CONFIG_BOOTDELAY=1
-+CONFIG_USE_BOOTARGS=y
-+CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 systemd.log_target=null root=/dev/vda1 rw androidboot.hardware=fvpbase rootwait loglevel=9"
-+# CONFIG_DISPLAY_CPUINFO is not set
-+# CONFIG_DISPLAY_BOARDINFO is not set
-+CONFIG_HUSH_PARSER=y
-+CONFIG_SYS_PROMPT="fvp32# "
-+# CONFIG_CMD_CONSOLE is not set
-+CONFIG_CMD_BOOTZ=y
-+# CONFIG_CMD_XIMG is not set
-+# CONFIG_CMD_EDITENV is not set
-+# CONFIG_CMD_ENV_EXISTS is not set
-+CONFIG_CMD_MEMTEST=y
-+CONFIG_CMD_ARMFLASH=y
-+# CONFIG_CMD_LOADS is not set
-+# CONFIG_CMD_ITEST is not set
-+# CONFIG_CMD_SETEXPR is not set
-+CONFIG_CMD_DHCP=y
-+# CONFIG_CMD_NFS is not set
-+CONFIG_CMD_MII=y
-+CONFIG_CMD_PING=y
-+CONFIG_CMD_CACHE=y
-+CONFIG_CMD_FAT=y
-+CONFIG_DM=y
-+CONFIG_MTD_NOR_FLASH=y
-+CONFIG_FLASH_CFI_DRIVER=y
-+CONFIG_SYS_FLASH_CFI=y
-+CONFIG_DM_SERIAL=y
-+CONFIG_PL01X_SERIAL=y
-+CONFIG_OF_LIBFDT=y
-+CONFIG_REMAKE_ELF=y
-diff --git a/include/configs/vexpress_aemv8.h b/include/configs/vexpress_aemv8.h
-index f0c5ceb3849a..854fbb41bfc1 100644
---- a/include/configs/vexpress_aemv8.h
-+++ b/include/configs/vexpress_aemv8.h
-@@ -86,7 +86,7 @@
- #endif
- #endif /* !CONFIG_GICV3 */
- 
--#if defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) && !defined(CONFIG_DM_ETH)
-+#if (defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) || defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP_AARCH32)) && !defined(CONFIG_DM_ETH)
- /* The Vexpress64 BASE_FVP simulator uses SMSC91C111 */
- #define CONFIG_SMC91111			1
- #define CONFIG_SMC91111_BASE		(V2M_PA_BASE + 0x01A000000)
-@@ -114,7 +114,7 @@
- #ifdef CONFIG_TARGET_VEXPRESS64_JUNO
- #define PHYS_SDRAM_2			(0x880000000)
- #define PHYS_SDRAM_2_SIZE		0x180000000
--#elif CONFIG_NR_DRAM_BANKS == 2
-+#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP && CONFIG_NR_DRAM_BANKS == 2
- #define PHYS_SDRAM_2			(0x880000000)
- #define PHYS_SDRAM_2_SIZE		0x80000000
- #endif
-@@ -171,23 +171,41 @@
- 				"fdt_addr_r=0x80000000\0" \
- 				BOOTENV
- 
--#elif CONFIG_TARGET_VEXPRESS64_BASE_FVP
-+#elif defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP) || \
-+        defined(CONFIG_TARGET_VEXPRESS64_BASE_FVP_AARCH32)
- 
--#define VEXPRESS_KERNEL_ADDR	0x80080000
--#define VEXPRESS_FDT_ADDR	0x8fc00000
--#define VEXPRESS_BOOT_ADDR	0x8fd00000
--#define VEXPRESS_RAMDISK_ADDR	0x8fe00000
-+#define VEXPRESS_KERNEL_ADDR   0x80080000
-+#define VEXPRESS_FDT_ADDR      0x8fc00000
-+#define VEXPRESS_BOOT_ADDR     0x8fd00000
-+#define VEXPRESS_RAMDISK_ADDR  0x8fe00000
- 
--#define CONFIG_EXTRA_ENV_SETTINGS	\
-+#define CONFIG_EXTRA_ENV_SETTINGS      \
- 				"kernel_name=Image\0"		\
--				"kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0"	\
--				"ramdisk_name=ramdisk.img\0"	\
--				"ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \
--				"fdtfile=devtree.dtb\0"	\
--				"fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0"	\
--				"boot_name=boot.img\0" \
--				"boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0"
--
-+                                "kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \
-+                                "ramdisk_name=ramdisk.img\0"    \
-+                                "ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \
-+                                "fdtfile=devtree.dtb\0" \
-+                                "fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0"       \
-+                                "boot_name=boot.img\0" \
-+                                "boot_addr_r=" __stringify(VEXPRESS_BOOT_ADDR) "\0"
-+
-+#ifndef CONFIG_BOOTCOMMAND
-+#define CONFIG_BOOTCOMMAND	"if smhload ${boot_name} ${boot_addr_r}; then " \
-+				"  set bootargs; " \
-+				"  abootimg addr ${boot_addr_r}; " \
-+				"  abootimg get dtb --index=0 fdt_addr_r; " \
-+				"  bootm ${boot_addr_r} ${boot_addr_r} " \
-+				"  ${fdt_addr_r}; " \
-+				"else; " \
-+				"  smhload ${kernel_name} ${kernel_addr_r}; " \
-+				"  smhload ${fdtfile} ${fdt_addr_r}; " \
-+				"  smhload ${ramdisk_name} ${initrd_addr_r} "\
-+				"  initrd_end; " \
-+				"  fdt addr ${fdt_addr_r}; fdt resize; " \
-+				"  fdt chosen ${ramdisk_addr_r} ${initrd_end}; " \
-+				"  bootz $kernel_addr_r - $fdt_addr_r; " \
-+				"fi"
-+#endif
- #endif
- 
- /* Monitor Command Prompt */
--- 
-2.30.2
-
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch
deleted file mode 100644
index d916d42..0000000
--- a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base-arm32/0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-From e896d48c57d272327410416887f34ac0db550390 Mon Sep 17 00:00:00 2001
-From: Jon Mason <jdmason@kudzu.us>
-Date: Mon, 13 Jun 2022 10:59:53 -0400
-Subject: [PATCH 2/2] Revert "vexpress64: Enable OF_CONTROL and OF_BOARD for
- VExpress64"
-
-This patch only works for aarch64 (as the 'x' registers are not
-available for ARMv7). Since this platform is ARMv7 in the previous
-patch, this either needs to be changed or removed.  I opted to remove
-it, as it doesn't seem to be necessary to boot the virtual hardware.
-Given that the previous patch was rejected upstream, it is not
-appropriate to fix this upstream.
-
-Upstream-Status: Inappropriate
-Signed-off-by: Jon Mason <jon.mason@arm.com>
-
-This reverts commit 2661397464e47d45cd25bbc5e6b9de7594b3268d.
----
- board/armltd/vexpress64/Makefile        |  2 +-
- board/armltd/vexpress64/lowlevel_init.S | 12 ------------
- board/armltd/vexpress64/vexpress64.c    | 26 -------------------------
- 3 files changed, 1 insertion(+), 39 deletions(-)
- delete mode 100644 board/armltd/vexpress64/lowlevel_init.S
-
-diff --git a/board/armltd/vexpress64/Makefile b/board/armltd/vexpress64/Makefile
-index 1878fbed4ec9..868dc4f629f2 100644
---- a/board/armltd/vexpress64/Makefile
-+++ b/board/armltd/vexpress64/Makefile
-@@ -3,5 +3,5 @@
- # (C) Copyright 2000-2004
- # Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- 
--obj-y	:= vexpress64.o lowlevel_init.o
-+obj-y	:= vexpress64.o
- obj-$(CONFIG_TARGET_VEXPRESS64_JUNO)	+= pcie.o
-diff --git a/board/armltd/vexpress64/lowlevel_init.S b/board/armltd/vexpress64/lowlevel_init.S
-deleted file mode 100644
-index 3dcfb85d0e9a..000000000000
---- a/board/armltd/vexpress64/lowlevel_init.S
-+++ /dev/null
-@@ -1,12 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0 */
--/*
-- * (C) Copyright 2021 Arm Limited
-- */
--
--.global save_boot_params
--save_boot_params:
--
--	adr	x8, prior_stage_fdt_address
--	str	x0, [x8]
--
--	b	save_boot_params_ret
-diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
-index 5e22e89824ee..cedab86d984b 100644
---- a/board/armltd/vexpress64/vexpress64.c
-+++ b/board/armltd/vexpress64/vexpress64.c
-@@ -92,15 +92,7 @@ int dram_init_banksize(void)
- 	return 0;
- }
- 
--/* Assigned in lowlevel_init.S
-- * Push the variable into the .data section so that it
-- * does not get cleared later.
-- */
--unsigned long __section(".data") prior_stage_fdt_address;
--
- #ifdef CONFIG_OF_BOARD
--
--#ifdef CONFIG_TARGET_VEXPRESS64_JUNO
- #define JUNO_FLASH_SEC_SIZE	(256 * 1024)
- static phys_addr_t find_dtb_in_nor_flash(const char *partname)
- {
-@@ -145,11 +137,9 @@ static phys_addr_t find_dtb_in_nor_flash(const char *partname)
- 
- 	return ~0;
- }
--#endif
- 
- void *board_fdt_blob_setup(int *err)
- {
--#ifdef CONFIG_TARGET_VEXPRESS64_JUNO
- 	phys_addr_t fdt_rom_addr = find_dtb_in_nor_flash(CONFIG_JUNO_DTB_PART);
- 
- 	*err = 0;
-@@ -159,22 +149,6 @@ void *board_fdt_blob_setup(int *err)
- 	}
- 
- 	return (void *)fdt_rom_addr;
--#endif
--
--#ifdef VEXPRESS_FDT_ADDR
--	if (fdt_magic(VEXPRESS_FDT_ADDR) == FDT_MAGIC) {
--		*err = 0;
--		return (void *)VEXPRESS_FDT_ADDR;
--	}
--#endif
--
--	if (fdt_magic(prior_stage_fdt_address) == FDT_MAGIC) {
--		*err = 0;
--		return (void *)prior_stage_fdt_address;
--	}
--
--	*err = -ENXIO;
--	return NULL;
- }
- #endif
- 
--- 
-2.30.2
-
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/0001-Revert-vexpress64-pick-DRAM-size-from-DT.patch b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/0001-Revert-vexpress64-pick-DRAM-size-from-DT.patch
new file mode 100644
index 0000000..d551622
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/0001-Revert-vexpress64-pick-DRAM-size-from-DT.patch
@@ -0,0 +1,44 @@
+From 4f649e0a3e0f9ed1f0d6efdff5b14cdc40d84201 Mon Sep 17 00:00:00 2001
+From: Jon Mason <jon.mason@arm.com
+Date: Thu, 2 Mar 2023 15:22:08 +0000
+Subject: [PATCH] Revert "vexpress64: pick DRAM size from DT"
+
+This reverts commit 1a1143a45457161e90ea4cd5f3b0561d924ed8fe.
+
+DRAM is determined via dtb in recent versions.  Since fvp isn't
+reading and specifying a dtb, this fails and hangs u-boot.  Remove this
+and go back to the way things were.
+
+Signed-off-by: Jon Mason <jon.mason@arm.com>
+Upstream-Status: Inappropriate
+---
+ board/armltd/vexpress64/vexpress64.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c
+index af326dc6f453..e8ce88b22c5a 100644
+--- a/board/armltd/vexpress64/vexpress64.c
++++ b/board/armltd/vexpress64/vexpress64.c
+@@ -88,12 +88,20 @@ int board_init(void)
+ 
+ int dram_init(void)
+ {
+-	return fdtdec_setup_mem_size_base();
++	gd->ram_size = PHYS_SDRAM_1_SIZE;
++	return 0;
+ }
+ 
+ int dram_init_banksize(void)
+ {
+-	return fdtdec_setup_memory_banksize();
++	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
++	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
++#ifdef PHYS_SDRAM_2
++	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
++	gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
++#endif
++
++	return 0;
+ }
+ 
+ /* Assigned in lowlevel_init.S
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/bootargs.cfg b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/bootargs.cfg
index 716600f..13f4cb4 100644
--- a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/bootargs.cfg
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-base/bootargs.cfg
@@ -1,3 +1,4 @@
 CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda1 rw rootwait"
+CONFIG_BOOTCOMMAND="booti $kernel_addr_r - $fdt_addr_r"
 # Our FVP support CRC instructions
 CONFIG_ARM64_CRC32=y
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend
index 9cc1bcd..6e68a42 100644
--- a/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot_%.bbappend
@@ -44,19 +44,31 @@
         file://0024-arm-corstone1000-esrt-support.patch					\
         file://0025-efi_setup-discover-FF-A-bus-before-raising-EFI-start.patch		\
         file://0026-corstone1000-enable-distro-booting-command.patch			\
+        file://0027-drivers-nvmxip-introduce-NVM-XIP-block-storage-emula.patch		\
+        file://0028-sandbox64-fix-return-unsigned-long-in-readq.patch			\
+        file://0029-sandbox64-add-support-for-NVMXIP-QSPI.patch			\
+        file://0030-corstone1000-add-NVM-XIP-QSPI-device-tree-node.patch		\
+        file://0031-corstone1000-enable-NVM-XIP-QSPI-flash.patch			\
+        file://0032-sandbox64-add-a-test-case-for-UCLASS_NVMXIP.patch			\
+        file://0033-nvmxip-provide-a-u-boot-shell-test-command.patch			\
+        file://0034-corstone1000-add-fwu-metadata-store-info.patch			\
+        file://0035-nvmxip-shorter-block-device-name.patch				\
+        file://0036-efi_boottime-allow-to-reset-a-path-after-boot.patch		\
+        file://0037-fwu_metadata-make-sure-structures-are-packed.patch			\
+        file://0038-corstone1000-add-boot-index.patch					\
+        file://0039-corstone1000-adjust-boot-bank-and-kernel-location.patch		\
+        file://0040-corstone1000-add-nvmxip-fwu-mdata-and-gpt-options.patch		\
+        file://0041-nvmxip-move-header-to-include.patch				\
+        file://0042-corstone1000-set-kernel_addr-based-on-boot_idx.patch		\
+        file://0043-corstone1000-boot-index-from-active.patch				\
         "
 
 #
 # FVP BASE
 #
-SRC_URI:append:fvp-base = " file://bootargs.cfg"
-
-#
-# FVP BASE ARM32
-#
-SRC_URI:append:fvp-base-arm32 = " file://0001-Add-vexpress_aemv8a_aarch32-variant.patch \
-				  file://0002-Revert-vexpress64-Enable-OF_CONTROL-and-OF_BOARD-for.patch \
-				"
+SRC_URI:append:fvp-base = " file://bootargs.cfg \
+	file://0001-Revert-vexpress64-pick-DRAM-size-from-DT.patch \
+	"
 
 #
 # FVP BASER