subtree updates

meta-security: a397a38ed9..53c5cc794f:
  Anton Antonov (2):
        Fix PACKAGECONFIG check in Parsec OEQA tests
        Flush caches after OEQA tests

  Armin Kuster (6):
        checksecurity: update to 2.0.16
        krill: forced to inclued fetch hashes.
        suricata: Fixup to work within the recent crate changes.
        suricata: Missed on crate depends
        parsec-tool: update SRC_URI hash
        parsec-service: fix SRC_URI hash

  Gowtham Suresh Kumar (2):
        meta-parsec: Disable RSA-OAEP OEQA tests for Parsec PKCS11 backend
        parsec-service: Update parsec recipes to 1.2.0 and parsec-tool to 0.6.0

  Patrick Williams (1):
        libwhisker2-perl: adjust perl-version variable

meta-openembedded: 17243e70c8..c5f330bc9a:
  Alex Yao (3):
        lcov: Fix Perl Path
        lcov: Upgrade 1.14 -> 1.16
        lcov: Fix homepage

  Ari Parkkila (1):
        python3-appdirs: add native and nativesdk to BBCLASSEXTEND

  Arsalan H. Awan (1):
        meta-networking/licenses/netperf: remove unused license

  Bartosz Golaszewski (11):
        reboot-mode: put the build artifacts in ${B}
        libgpiod: enable all features for ptest
        libgpiod: drop unneeded S assignment
        libgpiod: generalize the local files directories
        libgpiod: update to v2.0.1
        python3-gpiod: don't hardcode the project version in recipe
        python3-gpiod: add missing run-time dependencies
        libgpiod: install the libgpiosim header
        python3-gpiod: fetch sources from pypi
        libgpiod: fold libgpiod-src.inc into libgpiod.inc
        libgpiod: remove test executables from ${bindir}

  Chen Qi (1):
        android-tools: fix systemd service setting

  Enrico Scholz (1):
        sox: remove ffmpeg dependency

  Etienne Cordonnier (4):
        uutils-coreutils: Add crates checksum
        uutils-coreutils: remove obsolete comment
        uutils-coreutils: upgrade 0.0.17 -> 0.0.18
        uutils-coreutils: disable musl support

  Ever ATILANO (4):
        meta-python: python3-path: Add ptest
        meta-python: python3-lorem: Add ptest
        meta-oe: recipes-support: dc: Add ptest
        meta-oe: recipes-extended: bitwise: Add ptest

  Gianfranco Costamagna (1):
        vbxguestdrivers: upgrade 7.0.4 -> 7.0.8

  Jasper Orschulko (1):
        python3-gcovr: Add missing runtime dependency

  Jayanth Othayoth (1):
        etcd-cpp-apiv3: add recipe

  Johannes Kirchmair (1):
        redirect unwanted error message in nginx install

  Johannes Pointner (1):
        python3-pyzstd: add new recipe

  Kai Kang (16):
        xfce4-taskmanager: 1.5.2 -> 1.5.5
        xfce4-terminal: 1.0.0 -> 1.0.4
        syslog-ng: not deliver syslog-ng-update-virtualenv
        xfce4-notifyd: 0.6.3 -> 0.8.2
        xfce4-screenshooter: 1.9.10 -> 1.10.3
        thunar: 4.18.0 -> 4.18.4
        thunar-media-tags-plugin: 0.3.0 -> 0.4.0
        libxfce4util: 4.18.0 -> 4.18.1
        libxfce4ui: 4.18.0 -> 4.18.3
        xfce4-settings: 4.18.0 -> 4.18.2
        xfce4-session: 4.18.0 -> 4.18.2
        xfce4-panel: 4.18.0 -> 4.18.3
        thunar-archive-plugin: 0.5.0 -> 0.5.1
        xfce4-power-manager: 4.18.0 -> 4.18.1
        garcon: 4.18.0 -> 4.18.1
        xfce4-screensaver: 4.16.0 -> 4.18.1

  Khem Raj (36):
        krb5: Fix build with autoconf 2.72
        cyrus-sasl: Fix autoconf patch to work with new autoconf 2.72
        gmime: Update to 3.2.13
        imagemagick: Update to 7.1.1
        mpv: Upgrade to 0.35.1
        fwknop: Use pkg-config instead of gpgme-config
        fwknop: Fix AS_IF configure syntax
        libstemmer: Update to 2.2.0
        libidn: Update largefile m4 macros
        emacs: Fix build with autconf 2.72+
        ptest-packagelists-meta-oe: Remove minicoredumper from PTESTS_FAST_META_OE on musl
        poco: Remove pushd/popd from run-ptest
        surf: Fix build with gtkwebkit 2.40
        libio-pty-perl: Fix build with musl/clang
        meta-gnome: Update patch status for several recipes
        libnet-ssleay-perl: Fix patch upstream status
        meta-xfce: Fix missing upstream status in patches
        meta-multimedia: Fix missing upstream status in several patches
        meta-webserver: Fix missing upstream status on patches
        babl: Drop clang10 workaround for mips/rv64
        babl: Package /usr/lib/babl-0.1/ directory
        libtinyxml2: Add ptest support
        ptest-packagelists-meta-oe: Add libtinyxml2
        minifi-cpp: Always use stat on 64bit linux
        libdnet: Upgrade to 1.16.3
        python3-pyruvate: regenerate with updated bbclass
        monkey,webmin: Fix upstream patch status
        python3-pyruvate: Upgrade to 1.2.1
        onig: Ignore .debug directories while finding ptests
        python3-h5py: Fix TMPDIR references in dbg files
        python3-pandas: Fix TMPDIR references in dbg files
        fwupd: Do not emit build time paths into generated headers
        libcereal: Fix TMPDIR leaking into debug_str section
        xmlrpc-c: Upgrade to 1.59.01
        grilo: Fix buildpaths in generated header file
        python3-click: Fix ptest failure

  Leon Anavi (2):
        libpcsc-perl: Add recipe
        pcsc-tools: Add runtime dependencies

  Linus Jacobson (1):
        khronos-cts: Replace wayland feature dependancy with vulkan

  Markus Volk (40):
        nv-codec-headers: add clean target to Makefile
        flatpak: update 1.15.3 -> 1.15.4
        libcamera: re-introduce fix for gcc-13
        polkit-gnome: add recipe
        eog: update 43.2 -> 44.0
        evince: update 43.1 -> 44.0
        gdm: update 43.0 -> 44.0
        gnome-calculator: update 43.0.1 -> 44.0
        gnome-calendar: update 43.1 -> 44.0
        gnome-desktop: update 43 -> 44.0
        gnome-disk-utility: update 43.0 -> 44.0
        gnome-font-viewer: update 43.0 -> 44.0
        gnome-online-accounts: update 3.46.0 -> 3.48.0
        gnome-photos: update 43.0 -> 44.0
        gnome-session: update 43.0 -> 44.0
        gnome-settings-daemon: update 43.0 -> 44.0
        gnome-shell-extensions: update 43.1 -> 44.0
        gnome-software: update 43.4 -> 44.0
        gnome-terminal: update 3.46.7 -> 3.48.0
        gnome-text-editor: update 43.1 -> 44.0
        tracker-miners: update 3.4.2 -> 3.5.0
        zenity: update 3.43.0 -> 3.44.0
        xdg-desktop-portal-gnome: update 43.1 -> 44.0
        gedit: update 43.2 -> 44.2
        evolution-data-server: build oauth with gtk+3
        file-roller: set cpio path manually
        libdecor: update 1.1.0 -> 1.1.99
        freerdp: set PROXY_PLUGINDIR
        libnfs: add recipe
        pipewire: update 0.3.67 -> 0.3.68
        iwd: update 2.3 -> 2.4
        mozjs: update 102.5.0 -> 102.9.0
        glibmm: fix reproducibility issues
        adw-gtk3: add recipe
        xdg-desktop-portal-wlr: update
        pipewire: remove 'inherit gsettings'
        polkit: update SRC_URI
        webp-pixbuf-loader: update 0.2.0 -> 0.2.4
        udisks2: add PACKAGECONFIGs for btrfs,lvm2 and lsm
        pipewire: update 0.3.68 -> 0.3.70

  Martin Jansa (7):
        zsh: fix installed-vs-shipped with multilib
        restinio: fix S variable in multilib builds
        mongodb: fix chown user for multilib builds
        pahole: respect libdir
        lvgl,lv-lib-png,lv-drivers: fix installed-vs-shipped QA issue with multilib
        dleyna-{server,renderer}: fix dev-so QA issue with multilib
        lirc: fix do_install with multilib

  Mingli Yu (2):
        mcelog: improve the ptest output
        php: Fix GCC 12 -Og

  Peter Johennecken (1):
        nginx: added packagegroup for webdav module

  Peter Kjellerstedt (5):
        python3-crc32c: Correct the license information
        paho-mqtt-cpp: Improve the license information
        autossh: Correct the license information
        paho-mqtt-c: Improve the license information
        recipes: Remove double protocol= from SRC_URIs

  Peter Marko (1):
        ntp: whitelist CVE-2019-11331

  Petr Gotthard (2):
        cockpit: upgrade 276 -> 289
        nftables: upgrade 1.0.6 -> 1.0.7

  Randolph Sapp (1):
        glfw: add packageconfig and wayland dependencies

  Steffen Trumtrar (3):
        openocd: 0.11->0.12
        openocd: fix jimtcl url
        openocd: enable jtag-vpi and buspirate

  Tim Orling (11):
        cli11: do not inherit ptest
        span-lite: do not inherit ptest
        ptest-packagelists-meta-oe.inc: add ptest recipes
        meta-oe-ptest*-image: enable BBCLASSEXTEND parallel execution
        ptest-packagelists-meta-python.inc: add ptest recipes
        meta-python-ptest*-image: enable BBCLASSEXTEND parallel execution
        python3-aspectlib: fix ptest
        ptest-packagelists-meta-perl.inc: add ptest recipes
        recipes-perl/packagegroups: move to recipes-core/
        recipes-perl/images: move to recipes-core
        meta-perl-ptest*-image: enable BBCLASSEXTEND parallel execution

  Ulrich Ölmann (1):
        jwt-cpp: enable usage in an SDK

  Valeria Petrov (1):
        apache2: upgrade 2.4.56 -> 2.4.57

  Virendra Thakur (2):
        p7zip: fix for CVE-2018-5996
        p7zip: Fix for CVE-2016-9296

  Wang Mingyu (117):
        abseil-cpp: upgrade 20230125.1 -> 20230125.2
        libbytesize: upgrade 2.7 -> 2.8
        gegl: upgrade 0.4.42 -> 0.4.44
        ctags: upgrade 6.0.20230319.0 -> 6.0.20230402.0
        libdeflate: upgrade 1.17 -> 1.18
        libldb: upgrade 2.7.1 -> 2.7.2
        ndisc6: upgrade 1.0.6 -> 1.0.7
        libpfm4: upgrade 4.12.0 -> 4.13.0
        libtraceevent: upgrade 1.7.1 -> 1.7.2
        nginx: upgrade 1.23.3 -> 1.23.4
        links: upgrade 2.28 -> 2.29
        python3-pyproj: upgrade 3.4.1 -> 3.5.0
        ostree: upgrade 2023.1 -> 2023.2
        openvpn: upgrade 2.6.1 -> 2.6.2
        python3-aenum: upgrade 3.1.11 -> 3.1.12
        python3-argcomplete: upgrade 3.0.0 -> 3.0.5
        python3-cassandra-driver: upgrade 3.25.0 -> 3.26.0
        python3-astroid: upgrade 2.15.0 -> 2.15.1
        python3-cmake: upgrade 3.26.0 -> 3.26.1
        python3-dateparser: upgrade 1.1.7 -> 1.1.8
        python3-google-api-python-client: upgrade 2.81.0 -> 2.83.0
        python3-elementpath: upgrade 4.0.1 -> 4.1.0
        python3-googleapis-common-protos: upgrade 1.58.0 -> 1.59.0
        python3-httplib2: upgrade 0.21.0 -> 0.22.0
        python3-google-auth: upgrade 2.16.2 -> 2.17.1
        python3-ipython: upgrade 8.11.0 -> 8.12.0
        python3-imageio: upgrade 2.26.0 -> 2.27.0
        python3-pychromecast: upgrade 13.0.4 -> 13.0.6
        python3-jdatetime: upgrade 4.1.0 -> 4.1.1
        python3-luma-oled: upgrade 3.11.0 -> 3.12.0
        python3-pydantic: upgrade 1.10.6 -> 1.10.7
        python3-pymodbus: upgrade 3.2.1 -> 3.2.2
        python3-pymisp: upgrade 2.4.169.2 -> 2.4.169.3
        python3-pywbemtools: upgrade 1.1.1 -> 1.2.0
        python3-redis: upgrade 4.5.1 -> 4.5.4
        python3-regex: upgrade 2022.10.31 -> 2023.3.23
        python3-typeguard: upgrade 3.0.1 -> 3.0.2
        python3-sentry-sdk: upgrade 1.17.0 -> 1.18.0
        python3-rich: upgrade 13.3.2 -> 13.3.3
        python3-watchdog: upgrade 2.3.1 -> 3.0.0
        feh: upgrade 3.9.1 -> 3.10
        c-periphery: upgrade 2.3.1 -> 2.4.0
        grilo-plugins: upgrade 0.3.15 -> 0.3.16
        hwdata: upgrade 0.368 -> 0.369
        hwloc: upgrade 2.9.0 -> 2.9.1
        libconfig-tiny-perl: upgrade 2.28 -> 2.29
        mg: upgrade 20221112 -> 20230406
        python3-pillow: upgrade 9.4.0 -> 9.5.0
        python3-websockets: upgrade 10.4 -> 11.0.1
        poppler: upgrade 23.03.0 -> 23.04.0
        python3-alembic: upgrade 1.10.2 -> 1.10.3
        python3-astroid: upgrade 2.15.1 -> 2.15.2
        python3-coverage: upgrade 7.2.2 -> 7.2.3
        python3-google-api-python-client: upgrade 2.83.0 -> 2.84.0
        python3-google-auth: upgrade 2.17.1 -> 2.17.2
        python3-imgtool: upgrade 1.9.0 -> 1.10.0
        python3-pychromecast: upgrade 13.0.6 -> 13.0.7
        python3-simplejson: upgrade 3.18.4 -> 3.19.1
        python3-networkx: upgrade 3.0 -> 3.1
        tesseract: upgrade 5.3.0 -> 5.3.1
        python3-zeroconf: upgrade 0.47.4 -> 0.55.0
        python3-web3: upgrade 6.0.0 -> 6.1.0
        python3-sqlalchemy: upgrade 2.0.7 -> 2.0.9
        python3-sentry-sdk: upgrade 1.18.0 -> 1.19.1
        hdf5: Fix install conflict when enable multilib.
        capnproto: upgrade 0.10.3 -> 0.10.4
        ctags: upgrade 6.0.20230402.0 -> 6.0.20230416.0
        mctp: upgrade 1.0 -> 1.1
        php: upgrade 8.2.4 -> 8.2.5
        openvpn: upgrade 2.6.2 -> 2.6.3
        python3-croniter: upgrade 1.3.8 -> 1.3.14
        python3-diskcache: upgrade 5.4.0 -> 5.5.1
        python3-cmake: upgrade 3.26.1 -> 3.26.3
        python3-elementpath: upgrade 4.1.0 -> 4.1.1
        python3-google-api-python-client: upgrade 2.84.0 -> 2.85.0
        python3-google-auth: upgrade 2.17.2 -> 2.17.3
        python3-protobuf: upgrade 4.22.1 -> 4.22.3
        python3-web3: upgrade 6.1.0 -> 6.2.0
        python3-rich: upgrade 13.3.3 -> 13.3.4
        python3-pymisp: upgrade 2.4.169.3 -> 2.4.170
        python3-xlsxwriter: upgrade 3.0.9 -> 3.1.0
        python3-zeroconf: upgrade 0.55.0 -> 0.56.0
        remmina: upgrade 1.4.29 -> 1.4.30
        tbb: upgrade 2021.8.0 -> 2021.9.0
        sip: upgrade 6.7.7 -> 6.7.8
        tcpdump: upgrade 4.99.3 -> 4.99.4
        tcsh: upgrade 6.24.07 -> 6.24.10
        evolution-data-server: upgrade 3.48.0 -> 3.48.1
        babl: upgrade 0.1.102 -> 0.1.104
        gensio: upgrade 2.6.2 -> 2.6.4
        libopus: upgrade 1.3.1 -> 1.4
        network-manager-applet: upgrade 1.30.0 -> 1.32.0
        networkmanager: upgrade 1.42.4 -> 1.42.6
        opencl-headers: upgrade 2023.02.06 -> 2023.04.17
        c-periphery: upgrade 2.4.0 -> 2.4.1
        mbw: upgrade 1.5 -> 2.0
        libmodule-build-tiny-perl: upgrade 0.039 -> 0.043
        python3-periphery: upgrade 2.3.0 -> 2.4.1
        python3-astroid: upgrade 2.15.2 -> 2.15.3
        python3-diskcache: upgrade 5.5.1 -> 5.6.1
        python3-engineio: upgrade 4.4.0 -> 4.4.1
        python3-soupsieve: upgrade 2.4 -> 2.4.1
        python3-google-api-python-client: upgrade 2.85.0 -> 2.86.0
        python3-mock: upgrade 5.0.1 -> 5.0.2
        python3-pyalsaaudio: upgrade 0.9.2 -> 0.10.0
        python3-icu: upgrade 2.10.2 -> 2.11
        python3-pymisp: upgrade 2.4.170 -> 2.4.170.1
        python3-python-vlc: upgrade 3.0.18121 -> 3.0.18122
        python3-sentry-sdk: upgrade 1.19.1 -> 1.20.0
        python3-pyscaffold: upgrade 4.4 -> 4.4.1
        python3-websockets: upgrade 11.0.1 -> 11.0.2
        python3-tornado: upgrade 6.2 -> 6.3
        redis: upgrade 7.0.10 -> 7.0.11
        python3-xmlschema: upgrade 2.2.2 -> 2.2.3
        samba: upgrade 4.18.1 -> 4.18.2
        ser2net: upgrade 4.3.11 -> 4.3.12
        sip: upgrade 6.7.8 -> 6.7.9

  Wentao Zhang (2):
        jemalloc: include the missing shell scripts and source the corresponds shell scripts for some test cases.
        nss: fix failed test of nss.

  Wolfgang Meyer (2):
        qrencode: add PACKAGECONFIG for command line tools
        qrencode: enable native build

  Yi Zhao (1):
        samba: upgrade 4.18.0 -> 4.18.1

  Yogita Urade (1):
        dlt-daemon: fix CVE-2023-26257

  Zoltán Böszörményi (2):
        hplip: Fix installation and QA
        libgusb: Allow building in native mode

poky: 0907793d5e..cce6db2a59:
  Alex Kiernan (2):
        cargo_common.bbclass: Support local github repos
        rust: Upgrade 1.68.1 -> 1.68.2

  Alexander Kanavin (5):
        rust: do not run separate build/install steps
        rust: install llvm item only once
        rust: update 1.67.1 -> 1.68.1
        ffmpeg: update 5.1.2 -> 6.0
        meta/recipes: ensure all recipes have a SUMMARY

  Arslan Ahmad (1):
        kernel-fitimage: Fix the default dtb config check

  Bartosz Golaszewski (5):
        python3-pyproject-hooks: add missing run-time dependencies
        python3-packaging: add missing run-time dependencies
        python3-manifest: add tomllib
        python3-manifest: add ensurepip
        python3-build: add missing run-time dependencies

  Bruce Ashfield (7):
        kernel: improve initramfs bundle processing time
        linux-yocto/6.1: update to v6.1.23
        linux-yocto/5.15: update to v5.15.106
        linux-yocto/6.1: update to v6.1.24
        linux-yocto/5.15: update to v5.15.107
        linux-yocto/6.1: update to v6.1.25
        linux-yocto/5.15: update to v5.15.108

  Chen Qi (1):
        bitbake: runqueue: fix PSI check calculation

  Chris Elledge (1):
        busybox: move hwclock init earlier in startup

  Denys Dmytriyenko (2):
        xz: upgrade 5.4.1 -> 5.4.2
        grep: upgrade 3.9 -> 3.10

  Dit Kozmaj (2):
        wic: use part_name when defined
        selftest: wic: Add test for --part-name argument

  Dmitry Baryshkov (1):
        linux-firmware: upgrade 20230210 -> 20230404

  Enrico Jörns (10):
        oeqa/selftest/cases/runqemu: update imports
        oeqa/targetcontrol: fix misspelled RuntimeError
        oeqa/targetcontrol: do not set dump_host_cmds redundantly
        oeqa/targetcontrol: remove unused imports
        oeqa/utils/commands: fix usage of undefined EPIPE
        oeqa/utils/commands: remove unused imports
        oeqa/utils/qemurunner: replace hard-coded user 'root' in debug output
        oeqa/utils/qemurunner: limit precision of timing debugging output
        oeqa/utils/qemurunner: fix undefined TimeoutExpired
        oeqa: whitespace and indentation cleanups

  Enrico Scholz (2):
        bitbake: fetch2/crate: create versioned 'name' entries
        bitbake: cooker: do not abort on single ctrl-c

  Fabio Estevam (1):
        u-boot: Upgrade to 2023.04

  Frank WOLFF (1):
        logrotate: add ptest support

  Frederic Martinsons (6):
        cargo_common.bbclass: add support of user in url for patch
        devtool: add support for multiple git url inside a cargo based recipe
        patch: support of git patches when the source uri contained subpath parameter
        meta-selftest: provide a recipe for zvariant
        cargo-update-recipe-crates: force name overrides
        bitbake: fetch2: Display all missing checksum at once

  Geoffrey GIRY (1):
        cve-extra-exclusions: ignore inapplicable linux-yocto CVEs

  Jan Vermaete (1):
        cve-update-nvd2-native: added the missing http import

  Kai Kang (2):
        libnotify: remove dependency dbus
        bitbake: bitbake: ConfHandler: Allow variable flag name with a single character

  Khem Raj (16):
        e2fsprogs: Define 64bit off_t on rv32
        ffmpeg: Disable asm and rvv on riscv32
        cargo: Fix build on musl/riscv
        musl: Update to latest trunk
        systemd: Refresh a musl patch to remove patch-fuzz with 253.3
        musl-locales: Add Canadian French (fr_CA) locale support
        gawk: Disable known ptest fails on musl
        gawk: Remove redundant patch
        gawk: Add skipped.txt to emit test to ignore
        libxml2: Disable icu tests on musl
        apt-util: Fix ptest on musl
        lua: Disable locale dependent tests on musl
        attr: Disable attr.test on musl
        acl: Disable misc.test on musl
        fts: Fix typo in summary
        m4: Do not munge locale in ptests for musl

  Lee Chee Yang (2):
        migration-guides: add release-notes for 4.0.9
        release-notes-4.2: update RC3 changes

  Luca Ceresoli (1):
        devicetree.bbclass: fix typo

  Marek Vasut (1):
        cpio: Fix wrong CRC with ASCII CRC for large files

  Mark Asselstine (2):
        oeqa/selftest/bblogging: uncomment python stdout checks
        python3-psutil: fix-up -tests runtime dependencies

  Mark Hatle (1):
        sanity.bbclass: Update minimum gcc version to 8.0

  Markus Volk (1):
        at-spi2-core: update 2.46.0 -> 2.48.0

  Marta Rybczynska (1):
        cve-update-nvd2-native: new CVE database fetcher

  Martin Jansa (8):
        selftest: imagefeatures.py: don't mix tabs and spaces for indentation
        selftest: runqemu: better check for ROOTFS: in the log
        selftest: runqemu: use better error message when asserts fail
        runqemu: respect IMAGE_LINK_NAME
        python3-cryptography-crates.inc: regenerate with updated bbclass
        python3-bcrypt-crates.inc: regenerate with updated bbclass
        selftest: efibootpartition.py: fix QEMU_USE_KVM usage
        populate_sdk_ext.bbclass: set METADATA_REVISION with an DISTRO override

  Michael Opdenacker (20):
        manuals: update disk space requirements
        manuals: add rm_work disk space data
        manuals: add minimum RAM requirements
        ref-manual: release-process.rst: update testing section
        ref-manual: release-process.rst: major updates
        manuals: add "LTS" term
        manuals: improve and fix target for supported distros
        ref-manual: variables: document VOLATILE_TMP_DIR
        migration-guides: update 4.2 migration and release notes
        ref-manual: classes.rst: document devicetree.bbclass
        ref-manual: remove unused and obsolete file
        ref-manual: variables.rst: add wikipedia shortcut for "getty"
        overview-manual: update section about source archives
        manuals: document SPDX_CUSTOM_ANNOTATION_VARS
        overview-manual: development-environment: update text and screenshots
        ref-manual: add "Mixin" term
        migration-guides: release-notes-4.0.9.rst: add missing SPDX info
        migration-guides: fixes and improvements to 4.2 release notes
        manuals: expand init manager documentation
        ref-manual: variables.rst: document KERNEL_DANGLING_FEATURES_WARN_ONLY

  Mikko Rapeli (2):
        oeqa ping.py: avoid busylooping failing ping command
        oeqa ping.py: fail test if target IP address has not been set

  Mingli Yu (3):
        report-error: catch Nothing PROVIDES error
        bitbake: event: add bb.event.ParseError
        report-error: make it catch ParseError error

  Ola x Nilsson (2):
        patch.py: Use shlex instead of deprecated pipe
        package: Use shlex instead of deprecated pipe

  Pascal Bach (1):
        cmake: add CMAKE_SYSROOT to generated toolchain file

  Paul Eggleton (20):
        bitbake: bitbake-user-manual: document BB_CACHEDIR
        bitbake: bitbake-user-manual: add addpylib and BB_GLOBAL_PYMODULES
        bitbake: bitbake-user-manual: add BB_HASH_CODEPARSER_VALS
        ref-manual: add new SDK_ZIP_OPTIONS variable
        ref-manual: Add new RUST_CHANNEL variable
        ref-manual: update for IMAGE_MACHINE_SUFFIX addition
        dev/ref-manual: Remove references to INC_PR
        ref-manual: add BB_CACHEDIR
        migration-guides: Add coverage of addpylib directive
        ref-manual: Remove references to package_tar class
        ref-manual: add missing QA checks from previous releases
        ref-manual: document new patch-status-* QA checks
        ref-manual: add FIT_CONF_DEFAULT_DTB
        ref-manual: add section link also to buildtools-extended entry
        ref-manual: add SDK_ARCHIVE_TYPE
        ref-manual: move Initramfs entry from variables to terms
        dev/ref-manual: Document INIT_MANAGER
        migration-guides: extend migration guide for 4.2
        release-notes-4.1: fix some CVE links
        release-notes-4.2: add release notes

  Pavel Zhukov (2):
        scripts/rpm2cpio.sh: Use bzip2 instead of bunzip2
        scripts/runqemu: Add possibility to disable network

  Pawan Badganchi (1):
        tiff: Add fix for CVE-2022-4645

  Peter Kjellerstedt (1):
        cargo-update-recipe-crates.bbclass: Do not add name= to crate:// URIs

  Petr Kubizňák (12):
        harfbuzz: depend on glib-2.0-native
        json-glib: depend on glib-2.0-native
        libgudev: depend on glib-2.0-native
        at-spi2-core: depend on glib-2.0-native
        avahi: add missing dependencies
        graphene: add gobject-types PACKAGECONFIG
        python3-pygobject: depend on gobject-introspection
        gconf: add missing dependencies
        webkitgtk: add missing dependencies
        libnotify: depend on glib-2.0-native
        vte: depend on glib-2.0-native
        gobject-introspection: reduce dependencies

  Piotr Łobacz (1):
        libarchive: Enable acls, xattr for native as well as target

  Qiu Tingting (1):
        coreutils: Delete gcc sysroot parameter for ptest on target

  Randolph Sapp (1):
        wic/bootimg-efi: if fixed-size is set then use that for mkdosfs

  Richard Purdie (11):
        oeqa/loader: Ensure module names don't contain uppercase characters
        zvariant: Exclude from world for now to avoid reproducibility issues
        xdg-utils: Add a patch for CVE-2020-27748
        cve-extra-exclusions.inc: Exclude some issues not present in linux-yocto
        xdg-utils: Fix CVE number
        bitbake: bitbake: Bump to version 2.4.0
        build-appliance-image: Update to master head revision
        poky.conf: Bump version for 4.2 mickledore release
        build-appliance-image: Update to master head revision
        build-appliance-image: Update to master head revision
        cve-exclusions: Document some further linux-yocto CVE statuses

  Ross Burton (11):
        llvm: remove redundant CMake variables
        libgit2: clean up CMake variables
        webkitgtk: clean up Python variables
        oeqa/runtime: clean up deprecated backslash expansion
        classes-recipe/setuptools3-base: clean up FILES assignments
        bind: don't package non-existant .la files into -staticdev
        gstreamer1.0-plugins: package the internal libraries explicitly
        Increase minimum GCC version to 8.0
        machine/qemuarm*: don't explicitly set vmalloc
        screen: backport fix for CVE-2023-24626
        go: backport fix for CVE-2023-24537

  Soumya (1):
        shadow: Fix can not print full login timeout message

  Svend Meyland Nicolaisen (1):
        bitbake: npmsw fetcher: Avoid instantiating Fetch class if url list is empty

  Thomas De Schampheleire (3):
        qemu: make tracetool-generated output reproducible
        qemu: retain default trace backend if 'ust' is not enabled
        qemu: rename deprecated --enable-trace-backend configure option

  Thomas Roos (2):
        oeqa/selftest: Use SSTATE_DIR of parent build dir
        oeqa/utils/metadata.py: Fix running oe-selftest running with no distro set

  Tobias Hagelborn (1):
        lib/oe/gpg_sign.py: Avoid race when creating .sig files in detach_sign

  Ulrich Ölmann (3):
        kernel-dev: fix typos
        ref-manual: classes.rst: fix typo
        bitbake: bitbake-user-manual: fix BB_RUNFMT's default value

  Wang Mingyu (46):
        apr: upgrade 1.7.2 -> 1.7.3
        bind: upgrade 9.18.12 -> 9.18.13
        cracklib: upgrade 2.9.10 -> 2.9.11
        libhandy: upgrade 1.8.1 -> 1.8.2
        libpcap: upgrade 1.10.3 -> 1.10.4
        libsdl2: upgrade 2.26.3 -> 2.26.5
        libsoup: upgrade 3.2.2 -> 3.4.0
        mpg123: upgrade 1.31.2 -> 1.31.3
        acpica: upgrade 20220331 -> 20230331
        ccache: upgrade 4.7.4 -> 4.8
        libcap: upgrade 2.67 -> 2.68
        man-pages: upgrade 6.03 -> 6.04
        mtools: upgrade 4.0.42 -> 4.0.43
        pango: upgrade 1.50.13 -> 1.50.14
        ruby: upgrade 3.2.1 -> 3.2.2
        spirv-headers: upgrade 1.3.239.0 -> 1.3.243.0
        spirv-tools: upgrade 1.3.239.0 -> 1.3.243.0
        sqlite3: upgrade 3.41.0 -> 3.41.2
        texinfo: upgrade 7.0.2 -> 7.0.3
        wayland: upgrade 1.21.0 -> 1.22.0
        wpebackend-fdo: upgrade 1.14.0 -> 1.14.2
        xserver-xorg: upgrade 21.1.7 -> 21.1.8
        xwayland: upgrade 22.1.8 -> 23.1.1
        vala: upgrade 0.56.4 -> 0.56.6
        python3-cython: upgrade 0.29.33 -> 0.29.34
        python3-hypothesis: upgrade 6.68.2 -> 6.71.0
        python3-importlib-metadata: upgrade 6.0.0 -> 6.2.0
        python3-installer: upgrade 0.6.0 -> 0.7.0
        python3-markdown: upgrade 3.4.1 -> 3.4.3
        python3-pathspec: upgrade 0.11.0 -> 0.11.1
        python3-pygobject: upgrade 3.42.2 -> 3.44.1
        python3-pyopenssl: upgrade 23.0.0 -> 23.1.1
        python3-pytz: upgrade 2022.7.1 -> 2023.3
        python3-setuptools: upgrade 67.6.0 -> 67.6.1
        mesa: upgrade 23.0.0 -> 23.0.2
        systemd: upgrade 253.1 -> 253.3
        libgit2: upgrade 1.6.3 -> 1.6.4
        libsolv: upgrade 0.7.23 -> 0.7.24
        libxml2: upgrade 2.10.3 -> 2.10.4
        boost: upgrade 1.81.0 -> 1.82.0
        ofono: upgrade 2.0 -> 2.1
        python3-dtschema: upgrade 2023.1 -> 2023.4
        python3-packaging: upgrade 23.0 -> 23.1
        python3-pytest: upgrade 7.2.2 -> 7.3.1
        stress-ng: upgrade 0.15.06 -> 0.15.07
        gdb: Fix conflict of sframe-spec.info

  Wentao Zhang (1):
        python3: Fix failing sysconfig.py test on x86(64 bit) using lib64 as baselib by updating test_sysconfig for posix_user purelib

  Xiangyu Chen (1):
        shadow: backport patch to fix CVE-2023-29383

  Yoann Congal (4):
        cve-extra-exclusions: ignore inapplicable linux-yocto CVEs
        cve-exclusions_6.1: ignore patched CVE-2022-38457 & CVE-2022-40133
        cve-extra-exclusion: ignore disputed CVE-2023-23005
        cve-extra-exclusions: linux-yocto: ignore fixed CVE-2023-1652 & CVE-2023-1829

  Zhixiong Chi (1):
        libpam: Fix the xtests/tst-pam_motd[1|3] failures

  bkylerussell@gmail.com (1):
        kernel-devsrc: depend on python3-core instead of python3

meta-raspberrypi: 3afdbbf782..bf948e0aa8:
  Jesse Visser (2):
        recipe-bsp: Add support for Raspberry Pi Camera Module v3
        docs: Update extra build config Raspberry Pi Camera Module section

  Rodrigo M. Duarte (1):
        python3-adafruit-blinka: Fix the correct python recipes path in dynamic-layer sub-dir

meta-arm: 9b6c8c95e4..c60d7865dd:
  Adam Johnston (3):
        arm-bsp/optee: Update OP-TEE TA devkit to 3.20 for N1SDP
        CI: Remove ts-smm-gateway from N1SDP
        arm-bsp/trusted-firmware-a: Update N1SDP to v2.8.0

  Denys Dmytriyenko (4):
        optee-os-tadevkit: remove old unused patches
        optee-client: add 3.20.0 version
        optee-test: add 3.20.0 version
        optee-examples: add 3.20.0 version

  Emekcan Aras (4):
        arm-bsp/trusted-firmware-m: apply patches correctly from external repos
        arm-bsp/trusted-firmware-m: Switch to TF-M BL1 in Corstone1000
        arm-bsp/corstone1000: add OTP config for fvp
        arm-bsp/trusted-firmware-m: Increase assets number for corstone1000

  Jon Mason (8):
        CI: dev kernel allow failure
        arm/linux-yocto: remove IP_VS config fragment
        CI: update to the latest kas version
        CI: track mickledore branch
        arm-bsp/tc1: Fix signed u-boot
        arm-bsp/tc1: Add FVP support
        arm/trusted-firmware-m-scripts: relocate to tfm directory
        arm-bsp/tc1: disable signed kernel image

  Peter Hoyes (1):
        arm/scp-firmware: Add support for components other than SCP, MCP

  Ross Burton (8):
        arm/scp-firmware: add recipe for 2.11
        arm-bsp/scp-firmware: move all machines to SCP 2.11
        arm/scp-firmware: remove 2.10 recipe
        arm/trusted-firmware-m: add the tf-m-extras repository that some machines need
        arm/trusted-firmware-m: clean up environment flags
        arm/trusted-firmware-m: package .elf files in PN-dbg
        arm-bsp/trusted-firmware-m: enable for Total Compute on RSS
        CI: add TF-M to TC build

  Rui Miguel Silva (1):
        arm-bsp/corstone1000: tf-m set/get fwu, private metadata using gpt

  Xueliang Zhong (3):
        arm-bsp/n1sdp-board-firmware: update to newer SHA
        arm-bsp/optee-os: N1SDP support for optee-os 3.20
        arm-bsp/n1sdp: use edk2-firmware 202211 version

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I68eb48f27b781da34c4a7636f9b3bb1507b46416
diff --git a/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0006-Platform-ARM-N1Sdp-NOR-flash-Dxe-Driver-for-N1Sdp.patch b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0006-Platform-ARM-N1Sdp-NOR-flash-Dxe-Driver-for-N1Sdp.patch
new file mode 100644
index 0000000..1db94e4
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-bsp/uefi/files/edk2-platforms/0006-Platform-ARM-N1Sdp-NOR-flash-Dxe-Driver-for-N1Sdp.patch
@@ -0,0 +1,2538 @@
+From 726f4505970c82db1822b127059519044dc496c8 Mon Sep 17 00:00:00 2001
+From: sahil <sahil@arm.com>
+Date: Mon, 2 May 2022 19:00:40 +0530
+Subject: [PATCH] Platform/ARM/N1Sdp: NOR flash Dxe Driver for N1Sdp
+
+Add NOR flash DXE driver, this brings up NV storage on
+QSPI's flash device using FVB protocol.
+
+Upstream-Status: Pending
+Signed-off-by: Xueliang Zhong <xueliang.zhong@arm.com>
+Signed-off-by: sahil <sahil@arm.com>
+Change-Id: Ica383c2be6d1805daa19afd98d28b943816218dd
+---
+ .../Drivers/CadenceQspiDxe/CadenceQspiDxe.c   | 366 +++++++
+ .../Drivers/CadenceQspiDxe/CadenceQspiDxe.inf |  70 ++
+ .../Drivers/CadenceQspiDxe/CadenceQspiReg.h   |  31 +
+ .../N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c   | 930 ++++++++++++++++++
+ .../N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h   | 484 +++++++++
+ .../Drivers/CadenceQspiDxe/NorFlashFvb.c      | 573 +++++++++++
+ Platform/ARM/N1Sdp/N1SdpPlatform.dec          |   5 +-
+ 7 files changed, 2458 insertions(+), 1 deletion(-)
+ create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c
+ create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf
+ create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h
+ create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c
+ create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h
+ create mode 100644 Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c
+
+diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c
+new file mode 100644
+index 00000000..fb1dff3e
+--- /dev/null
++++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.c
+@@ -0,0 +1,366 @@
++/** @file
++  NOR flash DXE
++
++  Copyright (c) 2023, ARM Limited. All rights reserved.<BR>
++
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++
++**/
++
++#include <Library/BaseMemoryLib.h>
++#include <Library/DxeServicesTableLib.h>
++#include <Library/HobLib.h>
++#include <Library/MemoryAllocationLib.h>
++#include <Library/NorFlashInfoLib.h>
++#include <Library/PcdLib.h>
++#include <Library/UefiBootServicesTableLib.h>
++#include <Library/UefiLib.h>
++#include <Library/UefiRuntimeLib.h>
++#include <Library/UefiRuntimeServicesTableLib.h>
++
++#include "NorFlash.h"
++
++STATIC NOR_FLASH_INSTANCE   **mNorFlashInstances;
++STATIC UINT32               mNorFlashDeviceCount;
++
++STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
++
++/**
++  Install Fv block onto variable store region
++
++  @param[in]   Instance         Instance of Nor flash variable region.
++
++  @retval      EFI_SUCCESS      The entry point is executed successfully.
++**/
++EFI_STATUS
++EFIAPI
++NorFlashFvbInitialize (
++  IN NOR_FLASH_INSTANCE* Instance
++  )
++{
++  EFI_STATUS      Status;
++  UINT32          FvbNumLba;
++  EFI_BOOT_MODE   BootMode;
++  UINTN           RuntimeMmioRegionSize;
++  UINTN           RuntimeMmioDeviceSize;
++  UINTN           BlockSize;
++
++  DEBUG ((DEBUG_INFO,"NorFlashFvbInitialize\n"));
++
++  BlockSize = Instance->BlockSize;
++
++  // FirmwareVolumeHeader->FvLength is declared to have the Variable area
++  // AND the FTW working area AND the FTW Spare contiguous.
++  ASSERT (PcdGet32 (PcdFlashNvStorageVariableBase) +
++         PcdGet32 (PcdFlashNvStorageVariableSize) ==
++         PcdGet32 (PcdFlashNvStorageFtwWorkingBase));
++  ASSERT (PcdGet32 (PcdFlashNvStorageFtwWorkingBase) +
++         PcdGet32 (PcdFlashNvStorageFtwWorkingSize) ==
++         PcdGet32 (PcdFlashNvStorageFtwSpareBase));
++
++  // Check if the size of the area is at least one block size.
++  ASSERT ((PcdGet32 (PcdFlashNvStorageVariableSize) > 0) &&
++         (PcdGet32 (PcdFlashNvStorageVariableSize) / BlockSize > 0));
++  ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) &&
++         (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) / BlockSize > 0));
++  ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) &&
++         (PcdGet32 (PcdFlashNvStorageFtwSpareSize) / BlockSize > 0));
++
++  // Ensure the Variable areas are aligned on block size boundaries.
++  ASSERT ((PcdGet32 (PcdFlashNvStorageVariableBase) % BlockSize) == 0);
++  ASSERT ((PcdGet32 (PcdFlashNvStorageFtwWorkingBase) % BlockSize) == 0);
++  ASSERT ((PcdGet32 (PcdFlashNvStorageFtwSpareBase) % BlockSize) == 0);
++
++  Instance->Initialized = TRUE;
++  mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase);
++
++  // Set the index of the first LBA for the FVB.
++  Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) -
++                        Instance->RegionBaseAddress) / BlockSize;
++
++  BootMode = GetBootModeHob ();
++  if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
++    Status = EFI_INVALID_PARAMETER;
++  } else {
++    // Determine if there is a valid header at the beginning of the NorFlash.
++    Status = ValidateFvHeader (Instance);
++  }
++
++  // Install the Default FVB header if required.
++  if (EFI_ERROR(Status)) {
++    // There is no valid header, so time to install one.
++    DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));
++    DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this volume.\n",
++      __FUNCTION__));
++
++    // Erase all the NorFlash that is reserved for variable storage.
++    FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) +
++                 PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
++                 PcdGet32 (PcdFlashNvStorageFtwSpareSize)) /
++                 Instance->BlockSize;
++
++    Status = FvbEraseBlocks (
++               &Instance->FvbProtocol,
++               (EFI_LBA)0,
++               FvbNumLba,
++               EFI_LBA_LIST_TERMINATOR
++               );
++    if (EFI_ERROR(Status)) {
++      return Status;
++    }
++
++    // Install all appropriate headers.
++    Status = InitializeFvAndVariableStoreHeaders (Instance);
++    if (EFI_ERROR(Status)) {
++      return Status;
++    }
++
++    // validate FV header again if FV was created successfully.
++    Status = ValidateFvHeader (Instance);
++    if (EFI_ERROR(Status)) {
++      DEBUG ((DEBUG_ERROR, "ValidateFvHeader is failed \n"));
++      return Status;
++    }
++  }
++
++  // The driver implementing the variable read service can now be dispatched;
++  // the varstore headers are in place.
++  Status = gBS->InstallProtocolInterface (
++                  &gImageHandle,
++                  &gEdkiiNvVarStoreFormattedGuid,
++                  EFI_NATIVE_INTERFACE,
++                  NULL
++                  );
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR,
++      "%a: Failed to install gEdkiiNvVarStoreFormattedGuid\n",
++      __FUNCTION__));
++    return Status;
++  }
++
++  // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME.
++  RuntimeMmioRegionSize = Instance->Size;
++  RuntimeMmioDeviceSize = Instance->RegionBaseAddress - Instance->DeviceBaseAddress;
++
++  Status = gDS->AddMemorySpace (
++                  EfiGcdMemoryTypeMemoryMappedIo,
++                  Instance->RegionBaseAddress,
++                  RuntimeMmioRegionSize,
++                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
++                  );
++  ASSERT_EFI_ERROR (Status);
++
++  Status = gDS->AddMemorySpace (
++                  EfiGcdMemoryTypeMemoryMappedIo,
++                  Instance->DeviceBaseAddress,
++                  RuntimeMmioDeviceSize,
++                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
++                  );
++  ASSERT_EFI_ERROR (Status);
++
++  Status = gDS->SetMemorySpaceAttributes (
++                  Instance->RegionBaseAddress,
++                  RuntimeMmioRegionSize,
++                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
++                  );
++  ASSERT_EFI_ERROR (Status);
++
++  Status = gDS->SetMemorySpaceAttributes (
++                  Instance->DeviceBaseAddress,
++                  RuntimeMmioDeviceSize,
++                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
++                  );
++  ASSERT_EFI_ERROR (Status);
++
++  return Status;
++}
++
++/**
++  Fixup internal data so that EFI can be called in virtual mode.
++  convert any pointers in lib to virtual mode.
++
++  @param[in]    Event   The Event that is being processed
++  @param[in]    Context Event Context
++**/
++STATIC
++VOID
++EFIAPI
++NorFlashVirtualNotifyEvent (
++  IN EFI_EVENT        Event,
++  IN VOID             *Context
++  )
++{
++  UINTN Index;
++
++  EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
++
++  for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->HostRegisterBaseAddress);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->DeviceBaseAddress);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->RegionBaseAddress);
++
++    // Convert Fvb.
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Read);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
++    EfiConvertPointer (0x0,
++      (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Write);
++
++    if (mNorFlashInstances[Index]->ShadowBuffer != NULL) {
++      EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->ShadowBuffer);
++    }
++  }
++}
++
++/**
++  Entrypoint of Platform Nor flash DXE driver
++
++  @param[in]  ImageHandle       The firmware allocated handle for the EFI image.
++  @param[in]  SystemTable       A pointer to the EFI System Table.
++
++  @retval     EFI_SUCCESS       The entry point is executed successfully.
++**/
++EFI_STATUS
++EFIAPI
++NorFlashInitialise (
++  IN EFI_HANDLE           ImageHandle,
++  IN EFI_SYSTEM_TABLE     *SystemTable
++  )
++{
++  EFI_STATUS              Status;
++  EFI_PHYSICAL_ADDRESS    HostRegisterBaseAddress;
++  UINT32                  Index;
++  NOR_FLASH_DESCRIPTION*  NorFlashDevices;
++  BOOLEAN                 ContainVariableStorage;
++
++  HostRegisterBaseAddress = PcdGet32 (PcdCadenceQspiDxeRegBaseAddress);
++
++  Status = gDS->AddMemorySpace (
++                  EfiGcdMemoryTypeMemoryMappedIo,
++                  HostRegisterBaseAddress,
++                  SIZE_64KB,
++                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
++                  );
++  ASSERT_EFI_ERROR (Status);
++
++  Status = gDS->SetMemorySpaceAttributes (
++                  HostRegisterBaseAddress,
++                  SIZE_64KB,
++                  EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
++                  );
++  ASSERT_EFI_ERROR (Status);
++
++  // Initialize NOR flash instances.
++  Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR,"NorFlashInitialise: Fail to get Nor Flash devices\n"));
++    return Status;
++  }
++
++  mNorFlashInstances = AllocateRuntimePool (sizeof (NOR_FLASH_INSTANCE*) *
++                                            mNorFlashDeviceCount);
++
++  if(mNorFlashInstances == NULL) {
++    DEBUG ((DEBUG_ERROR,
++      "NorFlashInitialise: Failed to allocate mem for NorFlashInstance\n"));
++    return EFI_OUT_OF_RESOURCES;
++  }
++
++  for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
++    // Check if this NOR Flash device contain the variable storage region.
++    ContainVariableStorage =
++        (NorFlashDevices[Index].RegionBaseAddress <=
++         PcdGet32 (PcdFlashNvStorageVariableBase)) &&
++        (PcdGet32 (PcdFlashNvStorageVariableBase) +
++         PcdGet32 (PcdFlashNvStorageVariableSize) <=
++        NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
++
++    Status = NorFlashCreateInstance (
++               HostRegisterBaseAddress,
++               NorFlashDevices[Index].DeviceBaseAddress,
++               NorFlashDevices[Index].RegionBaseAddress,
++               NorFlashDevices[Index].Size,
++               Index,
++               NorFlashDevices[Index].BlockSize,
++               ContainVariableStorage,
++               &mNorFlashInstances[Index]
++               );
++    if (EFI_ERROR (Status)) {
++      DEBUG ((DEBUG_ERROR,
++        "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n",
++        Index));
++      continue;
++    }
++    Status = gBS->InstallMultipleProtocolInterfaces (
++                    &mNorFlashInstances[Index]->Handle,
++                    &gEfiDevicePathProtocolGuid,
++                    &mNorFlashInstances[Index]->DevicePath,
++                    &gEfiFirmwareVolumeBlockProtocolGuid,
++                    &mNorFlashInstances[Index]->FvbProtocol,
++                    NULL
++                    );
++    ASSERT_EFI_ERROR (Status);
++  }
++  // Register for the virtual address change event.
++  Status = gBS->CreateEventEx (
++                  EVT_NOTIFY_SIGNAL,
++                  TPL_NOTIFY,
++                  NorFlashVirtualNotifyEvent,
++                  NULL,
++                  &gEfiEventVirtualAddressChangeGuid,
++                  &mNorFlashVirtualAddrChangeEvent
++                  );
++  ASSERT_EFI_ERROR (Status);
++
++  return Status;
++}
++
++/**
++  Lock all pending read/write to Nor flash device
++
++  @param[in]     Context     Nor flash device context structure.
++**/
++VOID
++EFIAPI
++NorFlashLock (
++  IN NOR_FLASH_LOCK_CONTEXT    *Context
++  )
++{
++  if (!EfiAtRuntime ()) {
++    // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
++    Context->OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
++  } else {
++    Context->InterruptsEnabled = SaveAndDisableInterrupts ();
++  }
++}
++
++/**
++  Unlock all pending read/write to Nor flash device
++
++  @param[in]     Context     Nor flash device context structure.
++**/
++VOID
++EFIAPI
++NorFlashUnlock (
++  IN NOR_FLASH_LOCK_CONTEXT    *Context
++  )
++{
++  if (!EfiAtRuntime ()) {
++    // Interruptions can resume.
++    gBS->RestoreTPL (Context->OriginalTPL);
++  } else if (Context->InterruptsEnabled) {
++    SetInterruptState (TRUE);
++  }
++}
+diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf
+new file mode 100644
+index 00000000..4f20c3ba
+--- /dev/null
++++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiDxe.inf
+@@ -0,0 +1,70 @@
++## @file
++#  NOR flash DXE
++#
++#  Copyright (c) 2023, ARM Limited. All rights reserved.<BR>
++#
++#  SPDX-License-Identifier: BSD-2-Clause-Patent
++#
++##
++
++[Defines]
++  INF_VERSION                    = 0x0001001B
++  BASE_NAME                      = CadenceQspiDxe
++  FILE_GUID                      = CC8A9713-4442-4A6C-B389-8B46490A0641
++  MODULE_TYPE                    = DXE_RUNTIME_DRIVER
++  VERSION_STRING                 = 0.1
++  ENTRY_POINT                    = NorFlashInitialise
++
++[Sources]
++  CadenceQspiDxe.c
++  NorFlash.c
++  NorFlash.h
++  NorFlashFvb.c
++
++[Packages]
++  EmbeddedPkg/EmbeddedPkg.dec
++  MdeModulePkg/MdeModulePkg.dec
++  MdePkg/MdePkg.dec
++  Platform/ARM/ARM.dec
++  Platform/ARM/N1Sdp/N1SdpPlatform.dec
++
++[LibraryClasses]
++  BaseLib
++  BaseMemoryLib
++  DebugLib
++  DevicePathLib
++  DxeServicesTableLib
++  HobLib
++  IoLib
++  MemoryAllocationLib
++  NorFlashInfoLib
++  NorFlashPlatformLib
++  UefiBootServicesTableLib
++  UefiDriverEntryPoint
++  UefiLib
++  UefiRuntimeLib
++  UefiRuntimeServicesTableLib
++
++[Guids]
++  gEdkiiNvVarStoreFormattedGuid
++  gEfiAuthenticatedVariableGuid
++  gEfiEventVirtualAddressChangeGuid
++  gEfiSystemNvDataFvGuid
++  gEfiVariableGuid
++  gEfiGlobalVariableGuid
++
++[Protocols]
++  gEfiDevicePathProtocolGuid
++  gEfiFirmwareVolumeBlockProtocolGuid
++
++[FixedPcd]
++  gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress
++  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
++  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
++  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
++  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
++  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
++  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
++
++[Depex]
++  gEfiCpuArchProtocolGuid
+diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h
+new file mode 100644
+index 00000000..fe3b327c
+--- /dev/null
++++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/CadenceQspiReg.h
+@@ -0,0 +1,31 @@
++/** @file
++
++  Copyright (c) 2023, ARM Limited. All rights reserved.<BR>
++
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++
++**/
++
++#ifndef CADENCE_QSPI_REG_H_
++#define CADENCE_QSPI_REG_H_
++
++// QSPI Controller defines
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET               0x90
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE              0x01
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE          0x01
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS         19
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS    16
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT           0x02
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_4B         0x03
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B         0x02
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS       24
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE          0x01
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_BYTE_3B         0x02
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS       23
++#define CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS     20
++
++#define CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET          0xA0
++
++#define CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET               0x94
++
++#endif /* CADENCE_QSPI_REG_H_ */
+diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c
+new file mode 100644
+index 00000000..188c75e2
+--- /dev/null
++++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.c
+@@ -0,0 +1,930 @@
++/** @file
++
++  Copyright (c) 2023 ARM Limited. All rights reserved.<BR>
++
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++
++**/
++
++#include <Library/BaseMemoryLib.h>
++#include <Library/MemoryAllocationLib.h>
++#include <Library/NorFlashInfoLib.h>
++#include <Library/PcdLib.h>
++#include <Library/UefiBootServicesTableLib.h>
++#include <Library/UefiLib.h>
++
++#include "NorFlash.h"
++
++STATIC CONST NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
++  NOR_FLASH_SIGNATURE, // Signature
++  NULL, // Handle
++
++  FALSE, // Initialized
++  NULL, // Initialize
++
++  0, // HostRegisterBaseAddress
++  0, // DeviceBaseAddress
++  0, // RegionBaseAddress
++  0, // Size
++  0, // BlockSize
++  0, // LastBlock
++  0, // StartLba
++  0, // OffsetLba
++
++  {
++    FvbGetAttributes, // GetAttributes
++    FvbSetAttributes, // SetAttributes
++    FvbGetPhysicalAddress,  // GetPhysicalAddress
++    FvbGetBlockSize,  // GetBlockSize
++    FvbRead,  // Read
++    FvbWrite, // Write
++    FvbEraseBlocks, // EraseBlocks
++    NULL, //ParentHandle
++  }, //  FvbProtoccol;
++  NULL, // ShadowBuffer
++
++  {
++    {
++      {
++        HARDWARE_DEVICE_PATH,
++        HW_VENDOR_DP,
++        {
++          (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),
++          (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)
++        }
++      },
++    { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } },
++  },
++  0,  // Index
++
++  {
++    END_DEVICE_PATH_TYPE,
++    END_ENTIRE_DEVICE_PATH_SUBTYPE,
++    { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
++  }
++
++  }, // DevicePath
++  0 // Flags
++};
++
++/**
++  Execute Flash cmd ctrl and Read Status.
++
++  @param[in]      Instance         NOR flash Instance.
++  @param[in]      Val              Value to be written to Flash cmd ctrl Register.
++
++  @retval         EFI_SUCCESS      Request is executed successfully.
++
++**/
++STATIC
++EFI_STATUS
++CdnsQspiExecuteCommand (
++  IN  NOR_FLASH_INSTANCE    *Instance,
++  IN  UINT32                Val
++  )
++{
++  // Set the command
++  MmioWrite32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET,
++                Val);
++  // Execute the command
++  MmioWrite32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET,
++                Val | CDNS_QSPI_FLASH_CMD_CTRL_REG_EXECUTE);
++
++  // Wait until command has been executed
++  while ((MmioRead32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_CTRL_REG_OFFSET)
++          & CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT) == CDNS_QSPI_FLASH_CMD_CTRL_REG_STATUS_BIT)
++    continue;
++
++  return EFI_SUCCESS;
++}
++
++/**
++  Create Nor flash Instance for given region.
++
++  @param[in]    HostRegisterBase      Base address of Nor flash controller.
++  @param[in]    NorFlashDeviceBase    Base address of flash device.
++  @param[in]    NorFlashRegionBase    Base address of flash region on device.
++  @param[in]    NorFlashSize          Size of flash region.
++  @param[in]    Index                 Index of given flash region.
++  @param[in]    BlockSize             Block size of NOR flash device.
++  @param[in]    HasVarStore           Boolean set for VarStore on given region.
++  @param[out]   NorFlashInstance      Instance of given flash region.
++
++  @retval       EFI_SUCCESS           On successful creation of NOR flash instance.
++**/
++EFI_STATUS
++NorFlashCreateInstance (
++  IN UINTN                  HostRegisterBase,
++  IN UINTN                  NorFlashDeviceBase,
++  IN UINTN                  NorFlashRegionBase,
++  IN UINTN                  NorFlashSize,
++  IN UINT32                 Index,
++  IN UINT32                 BlockSize,
++  IN BOOLEAN                HasVarStore,
++  OUT NOR_FLASH_INSTANCE**  NorFlashInstance
++  )
++{
++  EFI_STATUS Status;
++  NOR_FLASH_INSTANCE* Instance;
++  NOR_FLASH_INFO *FlashInfo;
++  UINT8 JedecId[3];
++
++  ASSERT(NorFlashInstance != NULL);
++  Instance = AllocateRuntimeCopyPool (sizeof (mNorFlashInstanceTemplate),
++                                      &mNorFlashInstanceTemplate);
++  if (Instance == NULL) {
++    return EFI_OUT_OF_RESOURCES;
++  }
++
++  Instance->HostRegisterBaseAddress = HostRegisterBase;
++  Instance->DeviceBaseAddress       = NorFlashDeviceBase;
++  Instance->RegionBaseAddress       = NorFlashRegionBase;
++  Instance->Size                    = NorFlashSize;
++  Instance->BlockSize               = BlockSize;
++  Instance->LastBlock               = (NorFlashSize / BlockSize) - 1;
++
++  Instance->OffsetLba = (NorFlashRegionBase - NorFlashDeviceBase) / BlockSize;
++
++  CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);
++  Instance->DevicePath.Index = (UINT8)Index;
++
++  Status = NorFlashReadID (Instance, JedecId);
++  if (EFI_ERROR (Status)) {
++    goto FreeInstance;
++  }
++
++  Status = NorFlashGetInfo (JedecId, &FlashInfo, TRUE);
++  if (EFI_ERROR (Status)) {
++    goto FreeInstance;
++  }
++
++  NorFlashPrintInfo (FlashInfo);
++
++  Instance->Flags = 0;
++  if (FlashInfo->Flags & NOR_FLASH_WRITE_FSR) {
++    Instance->Flags = NOR_FLASH_POLL_FSR;
++  }
++
++  Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);
++  if (Instance->ShadowBuffer == NULL) {
++    Status = EFI_OUT_OF_RESOURCES;
++    goto FreeInstance;
++  }
++
++  if (HasVarStore) {
++    Instance->Initialize = NorFlashFvbInitialize;
++  }
++
++  *NorFlashInstance = Instance;
++  FreePool (FlashInfo);
++  return EFI_SUCCESS;
++
++FreeInstance:
++  FreePool (Instance);
++  return Status;
++}
++
++/**
++  Check whether NOR flash opertions are Locked.
++
++  @param[in]     Instance         NOR flash Instance.
++  @param[in]     BlockAddress     BlockAddress in NOR flash device.
++
++  @retval        FALSE            If NOR flash is not locked.
++**/
++STATIC
++BOOLEAN
++NorFlashBlockIsLocked (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN UINTN                  BlockAddress
++  )
++{
++  return FALSE;
++}
++
++/**
++  Unlock NOR flash operations on given block.
++
++  @param[in]      Instance         NOR flash instance.
++  @param[in]      BlockAddress     BlockAddress in NOR flash device.
++
++  @retval         EFI_SUCCESS      NOR flash operations is unlocked.
++**/
++STATIC
++EFI_STATUS
++NorFlashUnlockSingleBlock (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN UINTN                  BlockAddress
++  )
++{
++  return EFI_SUCCESS;
++}
++
++/**
++  Unlock NOR flash operations if it is necessary.
++
++  @param[in]      Instance         NOR flash instance.
++  @param[in]      BlockAddress     BlockAddress in NOR flash device.
++
++  @retval         EFI_SUCCESS      Request is executed successfully.
++**/
++STATIC
++EFI_STATUS
++NorFlashUnlockSingleBlockIfNecessary (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN UINTN                  BlockAddress
++  )
++{
++  EFI_STATUS Status;
++
++  Status = EFI_SUCCESS;
++
++  if (!NorFlashBlockIsLocked (Instance, BlockAddress)) {
++    Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
++  }
++
++  return Status;
++}
++
++/**
++  Enable write to NOR flash device.
++
++  @param[in]      Instance         NOR flash instance.
++
++  @retval         EFI_SUCCESS      Request is executed successfully.
++**/
++STATIC
++EFI_STATUS
++NorFlashEnableWrite (
++  IN  NOR_FLASH_INSTANCE    *Instance
++  )
++{
++
++  UINT32          val;
++
++  DEBUG ((DEBUG_INFO, "NorFlashEnableWrite()\n"));
++  val = (SPINOR_OP_WREN << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS);
++  if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) {
++    return EFI_DEVICE_ERROR;
++  }
++
++  return EFI_SUCCESS;
++}
++
++/**
++  The following function presumes that the block has already been unlocked.
++
++  @param[in]      Instance         NOR flash instance.
++  @param[in]      BlockAddress     Block address within the variable region.
++
++  @retval         EFI_SUCCESS      Request is executed successfully.
++ **/
++EFI_STATUS
++NorFlashEraseSingleBlock (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN UINTN                  BlockAddress
++  )
++{
++
++  UINT32 DevConfigVal;
++  UINT32 EraseOffset;
++
++  EraseOffset = 0x0;
++
++  DEBUG ((DEBUG_INFO, "NorFlashEraseSingleBlock(BlockAddress=0x%08x)\n",
++    BlockAddress));
++
++  if (EFI_ERROR (NorFlashEnableWrite (Instance))) {
++    return EFI_DEVICE_ERROR;
++  }
++
++  EraseOffset = BlockAddress - Instance->DeviceBaseAddress;
++
++  MmioWrite32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_ADDR_REG_OFFSET,
++                EraseOffset);
++
++  DevConfigVal = SPINOR_OP_BE_4K << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS |
++                 CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BIT_POS |
++                 CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B << CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_BIT_POS;
++
++  if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, DevConfigVal))) {
++    return EFI_DEVICE_ERROR;
++  }
++
++  return EFI_SUCCESS;
++}
++
++/**
++  This function unlock and erase an entire NOR Flash block.
++
++  @param[in]     Instance       NOR flash Instance of variable store region.
++  @param[in]     BlockAddress   Block address within the variable store region.
++
++  @retval        EFI_SUCCESS    The erase and unlock successfully completed.
++**/
++EFI_STATUS
++NorFlashUnlockAndEraseSingleBlock (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN UINTN                  BlockAddress
++  )
++{
++  EFI_STATUS              Status;
++  UINTN                   Index;
++  NOR_FLASH_LOCK_CONTEXT  Lock;
++  NorFlashLock (&Lock);
++
++  Index = 0;
++  do {
++    // Unlock the block if we have to
++    Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
++    if (EFI_ERROR (Status)) {
++      break;
++    }
++    Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
++    if (EFI_ERROR (Status)) {
++      break;
++    }
++    Index++;
++  } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
++
++  if (Index == NOR_FLASH_ERASE_RETRY) {
++    DEBUG ((DEBUG_ERROR,
++      "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n",
++      BlockAddress,Index));
++  }
++
++  NorFlashUnlock (&Lock);
++
++  return Status;
++}
++
++/**
++  Write a single word to given location.
++
++  @param[in]    Instance     NOR flash Instance of variable store region.
++  @param[in]    WordAddress  The address in NOR flash to write given word.
++  @param[in]    WriteData    The data to write into NOR flash location.
++
++  @retval       EFI_SUCCESS  The write is completed.
++**/
++STATIC
++EFI_STATUS
++NorFlashWriteSingleWord (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN UINTN                  WordAddress,
++  IN UINT32                 WriteData
++  )
++{
++  DEBUG ((DEBUG_INFO,
++    "NorFlashWriteSingleWord(WordAddress=0x%08x, WriteData=0x%08x)\n",
++    WordAddress, WriteData));
++
++  if (EFI_ERROR (NorFlashEnableWrite (Instance))) {
++    return EFI_DEVICE_ERROR;
++  }
++  MmioWrite32 (WordAddress, WriteData);
++  return EFI_SUCCESS;
++}
++
++/**
++  Write a full block to given location.
++
++  @param[in]    Instance           NOR flash Instance of variable store region.
++  @param[in]    Lba                The logical block address in NOR flash.
++  @param[in]    DataBuffer         The data to write into NOR flash location.
++  @param[in]    BlockSizeInWords   The number of bytes to write.
++
++  @retval       EFI_SUCCESS        The write is completed.
++**/
++STATIC
++EFI_STATUS
++NorFlashWriteFullBlock (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN EFI_LBA                Lba,
++  IN UINT32                 *DataBuffer,
++  IN UINT32                 BlockSizeInWords
++  )
++{
++  EFI_STATUS              Status;
++  UINTN                   WordAddress;
++  UINT32                  WordIndex;
++  UINTN                   BlockAddress;
++  NOR_FLASH_LOCK_CONTEXT  Lock;
++
++  Status = EFI_SUCCESS;
++
++  // Get the physical address of the block
++  BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba,
++                   BlockSizeInWords * 4);
++
++  // Start writing from the first address at the start of the block
++  WordAddress = BlockAddress;
++
++  NorFlashLock (&Lock);
++
++  Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR,
++      "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n",
++      BlockAddress));
++    goto EXIT;
++  }
++
++  for (WordIndex=0;
++       WordIndex < BlockSizeInWords;
++       WordIndex++, DataBuffer++, WordAddress += 4) {
++    Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
++    if (EFI_ERROR (Status)) {
++      goto EXIT;
++    }
++  }
++
++EXIT:
++  NorFlashUnlock (&Lock);
++
++  if (EFI_ERROR (Status)) {
++    DEBUG ((DEBUG_ERROR,
++      "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = %r.\n",
++      WordAddress, Status));
++  }
++  return Status;
++}
++
++/**
++  Write a full  block.
++
++  @param[in]    Instance           NOR flash Instance of variable store region.
++  @param[in]    Lba                The starting logical block index.
++  @param[in]    BufferSizeInBytes  The number of bytes to read.
++  @param[in]    Buffer             The pointer to a caller-allocated buffer that
++                                   contains the source for the write.
++
++  @retval       EFI_SUCCESS        The write is completed.
++**/
++EFI_STATUS
++NorFlashWriteBlocks (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN EFI_LBA                Lba,
++  IN UINTN                  BufferSizeInBytes,
++  IN VOID                   *Buffer
++  )
++{
++  UINT32          *pWriteBuffer;
++  EFI_STATUS      Status;
++  EFI_LBA         CurrentBlock;
++  UINT32          BlockSizeInWords;
++  UINT32          NumBlocks;
++  UINT32          BlockCount;
++
++  Status = EFI_SUCCESS;
++  // The buffer must be valid
++  if (Buffer == NULL) {
++    return EFI_INVALID_PARAMETER;
++  }
++
++  // We must have some bytes to read
++  DEBUG ((DEBUG_INFO, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n",
++    BufferSizeInBytes));
++  if (BufferSizeInBytes == 0) {
++    return EFI_BAD_BUFFER_SIZE;
++  }
++
++  // The size of the buffer must be a multiple of the block size
++  DEBUG ((DEBUG_INFO, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n",
++    Instance->BlockSize));
++  if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
++    return EFI_BAD_BUFFER_SIZE;
++  }
++
++  // All blocks must be within the device
++  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
++
++  DEBUG ((DEBUG_INFO,
++    "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks,
++    Instance->LastBlock, Lba));
++
++  if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
++    DEBUG ((DEBUG_ERROR,
++      "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
++    return EFI_INVALID_PARAMETER;
++  }
++
++  ASSERT (((UINTN)Buffer % sizeof (UINT32)) == 0);
++
++  BlockSizeInWords = Instance->BlockSize / 4;
++
++  // Because the target *Buffer is a pointer to VOID, we must put
++  // all the data into a pointer to a proper data type, so use *ReadBuffer
++  pWriteBuffer = (UINT32 *)Buffer;
++
++  CurrentBlock = Lba;
++  for (BlockCount = 0;
++       BlockCount < NumBlocks;
++       BlockCount++, CurrentBlock++, pWriteBuffer += BlockSizeInWords) {
++
++    DEBUG ((DEBUG_INFO, "NorFlashWriteBlocks: Writing block #%d\n",
++      (UINTN)CurrentBlock));
++
++    Status = NorFlashWriteFullBlock (
++               Instance,
++               CurrentBlock,
++               pWriteBuffer,
++               BlockSizeInWords
++               );
++
++    if (EFI_ERROR (Status)) {
++      break;
++    }
++  }
++
++  DEBUG ((DEBUG_INFO, "NorFlashWriteBlocks: Exit Status = %r.\n", Status));
++  return Status;
++}
++
++/**
++  Read a full  block.
++
++  @param[in]     Instance           NOR flash Instance of variable store region.
++  @param[in]     Lba                The starting logical block index to read from.
++  @param[in]     BufferSizeInBytes  The number of bytes to read.
++  @param[out]    Buffer             The pointer to a caller-allocated buffer that
++                                    should be copied with read data.
++
++  @retval        EFI_SUCCESS        The read is completed.
++**/
++EFI_STATUS
++NorFlashReadBlocks (
++  IN NOR_FLASH_INSTANCE   *Instance,
++  IN EFI_LBA              Lba,
++  IN UINTN                BufferSizeInBytes,
++  OUT VOID                *Buffer
++  )
++{
++  UINT32              NumBlocks;
++  UINTN               StartAddress;
++  DEBUG ((DEBUG_INFO,
++    "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
++    BufferSizeInBytes, Instance->BlockSize, Instance->LastBlock,
++    Lba));
++
++  // The buffer must be valid
++  if (Buffer == NULL) {
++    return EFI_INVALID_PARAMETER;
++  }
++
++  // Return if we do not have any byte to read
++  if (BufferSizeInBytes == 0) {
++    return EFI_SUCCESS;
++  }
++
++  // The size of the buffer must be a multiple of the block size
++  if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
++    return EFI_BAD_BUFFER_SIZE;
++  }
++
++  NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
++
++  if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
++    DEBUG ((DEBUG_ERROR,
++      "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
++    return EFI_INVALID_PARAMETER;
++  }
++
++  // Get the address to start reading from
++  StartAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba,
++                                        Instance->BlockSize);
++
++  // Readout the data
++  CopyMem(Buffer, (UINTN *)StartAddress, BufferSizeInBytes);
++
++  return EFI_SUCCESS;
++}
++
++/**
++  Read from nor flash.
++
++  @param[in]     Instance           NOR flash Instance of variable store region.
++  @param[in]     Lba                The starting logical block index to read from.
++  @param[in]     Offset             Offset into the block at which to begin reading.
++  @param[in]     BufferSizeInBytes  The number of bytes to read.
++  @param[out]    Buffer             The pointer to a caller-allocated buffer that
++                                    should copied with read data.
++
++  @retval        EFI_SUCCESS        The read is completed.
++**/
++EFI_STATUS
++NorFlashRead (
++  IN NOR_FLASH_INSTANCE   *Instance,
++  IN EFI_LBA              Lba,
++  IN UINTN                Offset,
++  IN UINTN                BufferSizeInBytes,
++  OUT VOID                *Buffer
++  )
++{
++  UINTN  StartAddress;
++  // The buffer must be valid
++  if (Buffer == NULL) {
++    return EFI_INVALID_PARAMETER;
++  }
++
++  // Return if we do not have any byte to read
++  if (BufferSizeInBytes == 0) {
++    return EFI_SUCCESS;
++  }
++
++  if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) >
++      Instance->Size) {
++    DEBUG ((DEBUG_ERROR,
++      "NorFlashRead: ERROR - Read will exceed device size.\n"));
++    return EFI_INVALID_PARAMETER;
++  }
++
++  // Get the address to start reading from
++  StartAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba,
++                                        Instance->BlockSize);
++
++  // Readout the data
++  CopyMem (Buffer, (UINTN *)(StartAddress + Offset), BufferSizeInBytes);
++
++  return EFI_SUCCESS;
++}
++
++/**
++  Write a full or portion of a block.
++
++  @param[in]         Instance     NOR flash Instance of variable store region.
++  @param[in]         Lba          The starting logical block index to write to.
++  @param[in]         Offset       Offset into the block at which to begin writing.
++  @param[in, out]    NumBytes     The total size of the buffer.
++  @param[in]         Buffer       The pointer to a caller-allocated buffer that
++                                  contains the source for the write.
++
++  @retval            EFI_SUCCESS  The write is completed.
++**/
++EFI_STATUS
++NorFlashWriteSingleBlock (
++  IN        NOR_FLASH_INSTANCE   *Instance,
++  IN        EFI_LBA               Lba,
++  IN        UINTN                 Offset,
++  IN OUT    UINTN                *NumBytes,
++  IN        UINT8                *Buffer
++  )
++{
++  EFI_STATUS  Status;
++  UINT32      Tmp;
++  UINT32      TmpBuf;
++  UINT32      WordToWrite;
++  UINT32      Mask;
++  BOOLEAN     DoErase;
++  UINTN       BytesToWrite;
++  UINTN       CurOffset;
++  UINTN       WordAddr;
++  UINTN       BlockSize;
++  UINTN       BlockAddress;
++  UINTN       PrevBlockAddress;
++
++  if (Buffer == NULL) {
++    DEBUG ((DEBUG_ERROR,
++      "NorFlashWriteSingleBlock: ERROR - Buffer is invalid\n" ));
++    return EFI_OUT_OF_RESOURCES;
++  }
++
++  PrevBlockAddress = 0;
++  if (!Instance->Initialized && Instance->Initialize) {
++    Instance->Initialize(Instance);
++  }
++
++  DEBUG ((DEBUG_INFO,
++    "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n",
++    Lba, Offset, *NumBytes, Buffer));
++
++  // Localise the block size to avoid de-referencing pointers all the time
++  BlockSize = Instance->BlockSize;
++
++  // The write must not span block boundaries.
++  // We need to check each variable individually because adding two large
++  // values together overflows.
++  if (Offset               >= BlockSize ||
++      *NumBytes            >  BlockSize ||
++      (Offset + *NumBytes) >  BlockSize) {
++    DEBUG ((DEBUG_ERROR,
++      "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n",
++      Offset, *NumBytes, BlockSize ));
++    return EFI_BAD_BUFFER_SIZE;
++  }
++
++  // We must have some bytes to write
++  if (*NumBytes == 0) {
++    DEBUG ((DEBUG_ERROR,
++      "NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n",
++      Offset, *NumBytes, BlockSize ));
++    return EFI_BAD_BUFFER_SIZE;
++  }
++
++  // Pick 128bytes as a good start for word operations as opposed to erasing the
++  // block and writing the data regardless if an erase is really needed.
++  // It looks like most individual NV variable writes are smaller than 128bytes.
++  if (*NumBytes <= 128) {
++    // Check to see if we need to erase before programming the data into NOR.
++    // If the destination bits are only changing from 1s to 0s we can just write.
++    // After a block is erased all bits in the block is set to 1.
++    // If any byte requires us to erase we just give up and rewrite all of it.
++    DoErase      = FALSE;
++    BytesToWrite = *NumBytes;
++    CurOffset    = Offset;
++
++    while (BytesToWrite > 0) {
++      // Read full word from NOR, splice as required. A word is the smallest
++      // unit we can write.
++      Status = NorFlashRead (
++                 Instance,
++                 Lba,
++                 CurOffset & ~(0x3),
++                 sizeof(Tmp),
++                 &Tmp
++                 );
++      if (EFI_ERROR (Status)) {
++        return EFI_DEVICE_ERROR;
++      }
++
++      // Physical address of word in NOR to write.
++      WordAddr = (CurOffset & ~(0x3)) +
++                 GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba,
++                   BlockSize);
++
++      // The word of data that is to be written.
++      TmpBuf = ReadUnaligned32 ((UINT32 *)(Buffer + (*NumBytes - BytesToWrite)));
++
++      // First do word aligned chunks.
++      if ((CurOffset & 0x3) == 0) {
++        if (BytesToWrite >= 4) {
++          // Is the destination still in 'erased' state?
++          if (~Tmp != 0) {
++            // Check to see if we are only changing bits to zero.
++            if ((Tmp ^ TmpBuf) & TmpBuf) {
++              DoErase = TRUE;
++              break;
++            }
++          }
++          // Write this word to NOR
++          WordToWrite = TmpBuf;
++          CurOffset += sizeof(TmpBuf);
++          BytesToWrite -= sizeof(TmpBuf);
++        } else {
++          // BytesToWrite < 4. Do small writes and left-overs
++          Mask = ~((~0) << (BytesToWrite * 8));
++          // Mask out the bytes we want.
++          TmpBuf &= Mask;
++          // Is the destination still in 'erased' state?
++          if ((Tmp & Mask) != Mask) {
++            // Check to see if we are only changing bits to zero.
++            if ((Tmp ^ TmpBuf) & TmpBuf) {
++              DoErase = TRUE;
++              break;
++            }
++          }
++          // Merge old and new data. Write merged word to NOR
++          WordToWrite = (Tmp & ~Mask) | TmpBuf;
++          CurOffset += BytesToWrite;
++          BytesToWrite = 0;
++        }
++      } else {
++        // Do multiple words, but starting unaligned.
++        if (BytesToWrite > (4 - (CurOffset & 0x3))) {
++          Mask = ((~0) << ((CurOffset & 0x3) * 8));
++          // Mask out the bytes we want.
++          TmpBuf &= Mask;
++          // Is the destination still in 'erased' state?
++          if ((Tmp & Mask) != Mask) {
++            // Check to see if we are only changing bits to zero.
++            if ((Tmp ^ TmpBuf) & TmpBuf) {
++              DoErase = TRUE;
++              break;
++            }
++          }
++          // Merge old and new data. Write merged word to NOR
++          WordToWrite = (Tmp & ~Mask) | TmpBuf;
++          BytesToWrite -= (4 - (CurOffset & 0x3));
++          CurOffset += (4 - (CurOffset & 0x3));
++        } else {
++          // Unaligned and fits in one word.
++          Mask = (~((~0) << (BytesToWrite * 8))) << ((CurOffset & 0x3) * 8);
++          // Mask out the bytes we want.
++          TmpBuf = (TmpBuf << ((CurOffset & 0x3) * 8)) & Mask;
++          // Is the destination still in 'erased' state?
++          if ((Tmp & Mask) != Mask) {
++            // Check to see if we are only changing bits to zero.
++            if ((Tmp ^ TmpBuf) & TmpBuf) {
++              DoErase = TRUE;
++              break;
++            }
++          }
++          // Merge old and new data. Write merged word to NOR
++          WordToWrite = (Tmp & ~Mask) | TmpBuf;
++          CurOffset += BytesToWrite;
++          BytesToWrite = 0;
++        }
++      }
++
++      BlockAddress = GET_NOR_BLOCK_ADDRESS (
++                       Instance->RegionBaseAddress,
++                       Lba,
++                       BlockSize
++                       );
++      if (BlockAddress != PrevBlockAddress) {
++        Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
++        if (EFI_ERROR (Status)) {
++          return EFI_DEVICE_ERROR;
++        }
++        PrevBlockAddress = BlockAddress;
++      }
++      Status = NorFlashWriteSingleWord (Instance, WordAddr, WordToWrite);
++      if (EFI_ERROR (Status)) {
++        return EFI_DEVICE_ERROR;
++      }
++    }
++    // Exit if we got here and could write all the data. Otherwise do the
++    // Erase-Write cycle.
++    if (!DoErase) {
++      return EFI_SUCCESS;
++    }
++  }
++
++  // Check we did get some memory. Buffer is BlockSize.
++  if (Instance->ShadowBuffer == NULL) {
++    DEBUG ((DEBUG_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
++    return EFI_DEVICE_ERROR;
++  }
++
++  // Read NOR Flash data into shadow buffer
++  Status = NorFlashReadBlocks (
++             Instance,
++             Lba,
++             BlockSize,
++             Instance->ShadowBuffer
++             );
++  if (EFI_ERROR (Status)) {
++    // Return one of the pre-approved error statuses
++    return EFI_DEVICE_ERROR;
++  }
++
++  // Put the data at the appropriate location inside the buffer area
++  CopyMem ((VOID*)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
++
++  // Write the modified buffer back to the NorFlash
++  Status = NorFlashWriteBlocks (
++             Instance,
++             Lba,
++             BlockSize,
++             Instance->ShadowBuffer
++             );
++  if (EFI_ERROR (Status)) {
++    // Return one of the pre-approved error statuses
++    return EFI_DEVICE_ERROR;
++  }
++
++  return EFI_SUCCESS;
++}
++
++/**
++  Read JEDEC ID of NOR flash device.
++
++  @param[in]     Instance     NOR flash Instance of variable store region.
++  @param[out]    JedecId      JEDEC ID of NOR flash device.
++
++  @retval        EFI_SUCCESS  The write is completed.
++**/
++EFI_STATUS
++NorFlashReadID (
++  IN  NOR_FLASH_INSTANCE  *Instance,
++  OUT UINT8               JedecId[3]
++  )
++{
++  UINT32 val;
++  if (Instance == NULL || JedecId == NULL) {
++    return EFI_INVALID_PARAMETER;
++  }
++
++  val = SPINOR_OP_RDID << CDNS_QSPI_FLASH_CMD_CTRL_REG_OPCODE_BIT_POS |
++        CDNS_QSPI_FLASH_CMD_CTRL_REG_READ_ENABLE << CDNS_QSPI_FLASH_CMD_CTRL_REG_READEN_BIT_POS |
++        CDNS_QSPI_FLASH_CMD_CTRL_REG_ADDR_BYTE_3B << CDNS_QSPI_FLASH_CMD_CTRL_REG_READBYTE_BIT_POS;
++
++  if (EFI_ERROR (CdnsQspiExecuteCommand (Instance, val))) {
++    return EFI_DEVICE_ERROR;
++  }
++
++  val = MmioRead32 (Instance->HostRegisterBaseAddress + CDNS_QSPI_FLASH_CMD_READ_DATA_REG_OFFSET);
++
++  // Manu.ID field
++  JedecId[0] = (UINT8) val;
++  // Type field
++  JedecId[1] = (UINT8) (val >> 8);
++  // Capacity field
++  JedecId[2] = (UINT8) (val >> 16);
++
++  DEBUG ((DEBUG_INFO,
++    "Nor flash detected, Jedec ID, Manu.Id=%x Type=%x Capacity=%x \n",
++    JedecId[0],JedecId[1],JedecId[2]));
++
++  return EFI_SUCCESS;
++}
+diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h
+new file mode 100644
+index 00000000..e720937e
+--- /dev/null
++++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlash.h
+@@ -0,0 +1,484 @@
++/** @file
++
++  Copyright (c) 2023, ARM Limited. All rights reserved.<BR>
++
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++
++**/
++
++#ifndef NOR_FLASH_DXE_H_
++#define NOR_FLASH_DXE_H_
++
++#include <Guid/EventGroup.h>
++#include <Library/DebugLib.h>
++#include <Library/IoLib.h>
++#include <Library/NorFlashPlatformLib.h>
++#include <PiDxe.h>
++#include <Protocol/BlockIo.h>
++#include <Protocol/DiskIo.h>
++#include <Protocol/FirmwareVolumeBlock.h>
++
++#include "CadenceQspiReg.h"
++
++#define NOR_FLASH_ERASE_RETRY                     10
++
++#define GET_NOR_BLOCK_ADDRESS(BaseAddr, Lba, LbaSize) \
++                                      ((BaseAddr) + (UINTN)((Lba) * (LbaSize)))
++
++#define NOR_FLASH_SIGNATURE          SIGNATURE_32('S', 'n', 'o', 'r')
++#define INSTANCE_FROM_FVB_THIS(a)    CR(a, NOR_FLASH_INSTANCE, FvbProtocol, \
++                                        NOR_FLASH_SIGNATURE)
++
++#define NOR_FLASH_POLL_FSR      BIT0
++
++typedef struct _NOR_FLASH_INSTANCE                NOR_FLASH_INSTANCE;
++
++typedef EFI_STATUS (*NOR_FLASH_INITIALIZE)        (NOR_FLASH_INSTANCE* Instance);
++
++#pragma pack(1)
++typedef struct {
++  VENDOR_DEVICE_PATH                  Vendor;
++  UINT8                               Index;
++  EFI_DEVICE_PATH_PROTOCOL            End;
++} NOR_FLASH_DEVICE_PATH;
++#pragma pack()
++
++struct _NOR_FLASH_INSTANCE {
++  UINT32                              Signature;
++  EFI_HANDLE                          Handle;
++
++  BOOLEAN                             Initialized;
++  NOR_FLASH_INITIALIZE                Initialize;
++
++  UINTN                               HostRegisterBaseAddress;
++  UINTN                               DeviceBaseAddress;
++  UINTN                               RegionBaseAddress;
++  UINTN                               Size;
++  UINTN                               BlockSize;
++  UINTN                               LastBlock;
++  EFI_LBA                             StartLba;
++  EFI_LBA                             OffsetLba;
++
++  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
++  VOID*                               ShadowBuffer;
++
++  NOR_FLASH_DEVICE_PATH               DevicePath;
++
++  UINT32                              Flags;
++};
++
++typedef struct {
++  EFI_TPL         OriginalTPL;
++  BOOLEAN         InterruptsEnabled;
++} NOR_FLASH_LOCK_CONTEXT;
++
++/**
++  Lock all pending read/write to Nor flash device
++
++  @param[in]     Context     Nor flash device context structure.
++**/
++VOID
++EFIAPI
++NorFlashLock (
++  IN NOR_FLASH_LOCK_CONTEXT    *Context
++  );
++
++/**
++  Unlock all pending read/write to Nor flash device
++
++  @param[in]     Context     Nor flash device context structure.
++**/
++VOID
++EFIAPI
++NorFlashUnlock (
++  IN NOR_FLASH_LOCK_CONTEXT    *Context
++  );
++
++extern UINTN     mFlashNvStorageVariableBase;
++
++/**
++  Create Nor flash Instance for given region.
++
++  @param[in]    HostRegisterBase      Base address of Nor flash controller.
++  @param[in]    NorFlashDeviceBase    Base address of flash device.
++  @param[in]    NorFlashRegionBase    Base address of flash region on device.
++  @param[in]    NorFlashSize          Size of flash region.
++  @param[in]    Index                 Index of given flash region.
++  @param[in]    BlockSize             Block size of NOR flash device.
++  @param[in]    HasVarStore           Boolean set for VarStore on given region.
++  @param[out]   NorFlashInstance      Instance of given flash region.
++
++  @retval       EFI_SUCCESS           On successful creation of NOR flash instance.
++**/
++EFI_STATUS
++NorFlashCreateInstance (
++  IN UINTN                  HostRegisterBase,
++  IN UINTN                  NorFlashDeviceBase,
++  IN UINTN                  NorFlashRegionBase,
++  IN UINTN                  NorFlashSize,
++  IN UINT32                 Index,
++  IN UINT32                 BlockSize,
++  IN BOOLEAN                HasVarStore,
++  OUT NOR_FLASH_INSTANCE**  NorFlashInstance
++  );
++
++/**
++  Install Fv block on to variable store region
++
++  @param[in]   Instance         Instance of Nor flash variable region.
++
++  @retval      EFI_SUCCESS      The entry point is executed successfully.
++**/
++EFI_STATUS
++EFIAPI
++NorFlashFvbInitialize (
++  IN NOR_FLASH_INSTANCE* Instance
++  );
++
++/**
++  Check the integrity of firmware volume header.
++
++  @param[in]  Instance        Instance of Nor flash variable region.
++
++  @retval     EFI_SUCCESS     The firmware volume is consistent.
++  @retval     EFI_NOT_FOUND   The firmware volume has been corrupted.
++
++**/
++EFI_STATUS
++ValidateFvHeader (
++  IN  NOR_FLASH_INSTANCE *Instance
++  );
++
++/**
++  Initialize the FV Header and Variable Store Header
++  to support variable operations.
++
++  @param[in]  Instance      Location to Initialize the headers
++
++  @retval     EFI_SUCCESS   Fv init is done
++
++**/
++EFI_STATUS
++InitializeFvAndVariableStoreHeaders (
++  IN NOR_FLASH_INSTANCE *Instance
++  );
++
++/**
++ Retrieves the attributes and current settings of the block.
++
++ @param[in]   This         Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[out]  Attributes   Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
++                           current settings are returned.
++                           Type EFI_FVB_ATTRIBUTES_2 is defined in
++                           EFI_FIRMWARE_VOLUME_HEADER.
++
++ @retval      EFI_SUCCESS  The firmware volume attributes were returned.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbGetAttributes(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL     *This,
++  OUT       EFI_FVB_ATTRIBUTES_2                    *Attributes
++  );
++
++/**
++ Sets configurable firmware volume attributes and returns the
++ new settings of the firmware volume.
++
++
++ @param[in]         This                     EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in, out]    Attributes               On input, Attributes is a pointer to
++                                             EFI_FVB_ATTRIBUTES_2 that contains the desired
++                                             firmware volume settings.
++                                             On successful return, it contains the new
++                                             settings of the firmware volume.
++
++ @retval            EFI_UNSUPPORTED          The firmware volume attributes are not supported.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbSetAttributes(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL     *This,
++  IN OUT    EFI_FVB_ATTRIBUTES_2                    *Attributes
++  );
++
++/**
++ Retrieves the base address of a memory-mapped firmware volume.
++ This function should be called only for memory-mapped firmware volumes.
++
++ @param[in]     This               EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[out]    Address            Pointer to a caller-allocated
++                                   EFI_PHYSICAL_ADDRESS that, on successful
++                                   return from GetPhysicalAddress(), contains the
++                                   base address of the firmware volume.
++
++ @retval        EFI_SUCCESS        The firmware volume base address was returned.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbGetPhysicalAddress(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL     *This,
++  OUT       EFI_PHYSICAL_ADDRESS                    *Address
++  );
++
++/**
++ Retrieves the size of the requested block.
++ It also returns the number of additional blocks with the identical size.
++ The GetBlockSize() function is used to retrieve the block map
++ (see EFI_FIRMWARE_VOLUME_HEADER).
++
++
++ @param[in]     This                     EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in]     Lba                      Indicates the block whose size to return
++
++ @param[out]    BlockSize                Pointer to a caller-allocated UINTN in which
++                                         the size of the block is returned.
++
++ @param[out]    NumberOfBlocks           Pointer to a caller-allocated UINTN in
++                                         which the number of consecutive blocks,
++                                         starting with Lba, is returned. All
++                                         blocks in this range have a size of
++                                         BlockSize.
++
++ @retval        EFI_SUCCESS              The firmware volume base address was returned.
++
++ @retval        EFI_INVALID_PARAMETER    The requested LBA is out of range.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbGetBlockSize(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL     *This,
++  IN        EFI_LBA                                 Lba,
++  OUT       UINTN                                   *BlockSize,
++  OUT       UINTN                                   *NumberOfBlocks
++  );
++
++/**
++ Reads the specified number of bytes into a buffer from the specified block.
++
++ The Read() function reads the requested number of bytes from the
++ requested block and stores them in the provided buffer.
++
++ @param[in]       This                 EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in]       Lba                  The starting logical block index from which to read
++
++ @param[in]       Offset               Offset into the block at which to begin reading.
++
++ @param[in, out]  NumBytes             Pointer to a UINTN.
++                                       At entry, *NumBytes contains the total size of the
++                                       buffer. *NumBytes should have a non zero value.
++                                       At exit, *NumBytes contains the total number of
++                                       bytes read.
++
++ @param[in out]   Buffer               Pointer to a caller-allocated buffer that will be
++                                       used to hold the data that is read.
++
++ @retval          EFI_SUCCESS          The firmware volume was read successfully, and
++                                       contents are in Buffer.
++
++ @retval          EFI_BAD_BUFFER_SIZE  Read attempted across an LBA boundary.
++
++ @retval          EFI_DEVICE_ERROR     The block device is not functioning correctly and
++                                       could not be read.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbRead(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL     *This,
++  IN        EFI_LBA                                 Lba,
++  IN        UINTN                                   Offset,
++  IN OUT    UINTN                                   *NumBytes,
++  IN OUT    UINT8                                   *Buffer
++  );
++
++/**
++ Writes the specified number of bytes from the input buffer to the block.
++
++ @param[in]        This                 EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in]        Lba                  The starting logical block index to write to.
++
++ @param[in]        Offset               Offset into the block at which to begin writing.
++
++ @param[in, out]   NumBytes             The pointer to a UINTN.
++                                        At entry, *NumBytes contains the total size of the
++                                        buffer.
++                                        At exit, *NumBytes contains the total number of
++                                        bytes actually written.
++
++ @param[in]        Buffer               The pointer to a caller-allocated buffer that
++                                        contains the source for the write.
++
++ @retval           EFI_SUCCESS          The firmware volume was written successfully.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbWrite(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL     *This,
++  IN        EFI_LBA                                 Lba,
++  IN        UINTN                                   Offset,
++  IN OUT    UINTN                                   *NumBytes,
++  IN        UINT8                                   *Buffer
++  );
++
++/**
++ Erases and initialises a firmware volume block.
++
++ @param[in]   This                     EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
++
++ @param[in]   ...                      The variable argument list is a list of tuples.
++                                       Each tuple describes a range of LBAs to erase
++                                       and consists of the following:
++                                       - An EFI_LBA that indicates the starting LBA
++                                       - A UINTN that indicates the number of blocks
++                                       to erase.
++
++                                       The list is terminated with an
++                                       EFI_LBA_LIST_TERMINATOR.
++
++ @retval      EFI_SUCCESS              The erase request successfully completed.
++
++ @retval      EFI_ACCESS_DENIED        The firmware volume is in the WriteDisabled
++                                       state.
++
++ @retval      EFI_DEVICE_ERROR         The block device is not functioning correctly
++                                       and could not be written.
++                                       The firmware device may have been partially
++                                       erased.
++
++ @retval      EFI_INVALID_PARAMETER    One or more of the LBAs listed in the variable
++                                       argument list do not exist in the firmware
++                                       volume.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbEraseBlocks(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL     *This,
++  ...
++  );
++
++/**
++  This function unlock and erase an entire NOR Flash block.
++
++  @param[in]     Instance       NOR flash Instance of variable store region.
++  @param[in]     BlockAddress   Block address within the variable store region.
++
++  @retval        EFI_SUCCESS    The erase and unlock successfully completed.
++**/
++EFI_STATUS
++NorFlashUnlockAndEraseSingleBlock (
++  IN NOR_FLASH_INSTANCE     *Instance,
++  IN UINTN                  BlockAddress
++  );
++
++/**
++  Write a full or portion of a block.
++
++  @param[in]        Instance     NOR flash Instance of variable store region.
++  @param[in]        Lba          The starting logical block index to write to.
++  @param[in]        Offset       Offset into the block at which to begin writing.
++  @param[in,out]    NumBytes     The total size of the buffer.
++  @param[in]        Buffer       The pointer to a caller-allocated buffer that
++                                 contains the source for the write.
++
++  @retval           EFI_SUCCESS  The write is completed.
++**/
++EFI_STATUS
++NorFlashWriteSingleBlock (
++  IN        NOR_FLASH_INSTANCE   *Instance,
++  IN        EFI_LBA               Lba,
++  IN        UINTN                 Offset,
++  IN OUT    UINTN                *NumBytes,
++  IN        UINT8                *Buffer
++  );
++
++/**
++  Write a full  block.
++
++  @param[in]    Instance             NOR flash Instance of variable store region.
++  @param[in]    Lba                  The starting logical block index to write to.
++  @param[in]    BufferSizeInBytes    The number of bytes to write.
++  @param[in]    Buffer               The pointer to a caller-allocated buffer that
++                                     contains the source for the write.
++
++  @retval       EFI_SUCCESS          The write is completed.
++**/
++EFI_STATUS
++NorFlashWriteBlocks (
++  IN  NOR_FLASH_INSTANCE *Instance,
++  IN  EFI_LBA            Lba,
++  IN  UINTN              BufferSizeInBytes,
++  IN  VOID               *Buffer
++  );
++
++/**
++  Read a full  block.
++
++  @param[in]     Instance           NOR flash Instance of variable store region.
++  @param[in]     Lba                The starting logical block index to read from.
++  @param[in]     BufferSizeInBytes  The number of bytes to read.
++  @param[out]    Buffer             The pointer to a caller-allocated buffer that
++                                    should be copied with read data.
++
++  @retval        EFI_SUCCESS        The read is completed.
++**/
++EFI_STATUS
++NorFlashReadBlocks (
++  IN NOR_FLASH_INSTANCE   *Instance,
++  IN EFI_LBA              Lba,
++  IN UINTN                BufferSizeInBytes,
++  OUT VOID                *Buffer
++  );
++
++/**
++  Read from nor flash.
++
++  @param[in]     Instance           NOR flash Instance of variable store region.
++  @param[in]     Lba                The starting logical block index to read from.
++  @param[in]     Offset             Offset into the block at which to begin reading.
++  @param[in]     BufferSizeInBytes  The number of bytes to read.
++  @param[out]    Buffer             The pointer to a caller-allocated buffer that
++                                    should copied with read data.
++
++  @retval        EFI_SUCCESS        The read is completed.
++**/
++EFI_STATUS
++NorFlashRead (
++  IN NOR_FLASH_INSTANCE   *Instance,
++  IN EFI_LBA              Lba,
++  IN UINTN                Offset,
++  IN UINTN                BufferSizeInBytes,
++  OUT VOID                *Buffer
++  );
++
++/**
++  Read JEDEC ID of NOR flash device.
++
++  @param[in]     Instance     NOR flash Instance of variable store region.
++  @param[out]    JedecId      JEDEC ID of NOR flash device.
++
++  @retval        EFI_SUCCESS  The write is completed.
++**/
++EFI_STATUS
++NorFlashReadID (
++  IN  NOR_FLASH_INSTANCE  *Instance,
++  OUT UINT8               JedecId[3]
++  );
++
++#define SPINOR_OP_WREN                0x06  // Write enable
++#define SPINOR_OP_BE_4K               0x20  // Erase 4KiB block
++#define SPINOR_OP_RDID                0x9f  // Read JEDEC ID
++
++#endif /* NOR_FLASH_DXE_H_ */
+diff --git a/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c
+new file mode 100644
+index 00000000..edd84c07
+--- /dev/null
++++ b/Platform/ARM/N1Sdp/Drivers/CadenceQspiDxe/NorFlashFvb.c
+@@ -0,0 +1,573 @@
++/** @file
++
++  Copyright (c) 2023, ARM Limited. All rights reserved.<BR>
++
++  SPDX-License-Identifier: BSD-2-Clause-Patent
++
++**/
++
++#include <Guid/VariableFormat.h>
++#include <Guid/SystemNvDataGuid.h>
++
++#include <Library/BaseLib.h>
++#include <Library/BaseMemoryLib.h>
++#include <Library/MemoryAllocationLib.h>
++#include <Library/PcdLib.h>
++#include <Library/UefiBootServicesTableLib.h>
++#include <Library/UefiLib.h>
++
++#include <PiDxe.h>
++
++#include "NorFlash.h"
++
++UINTN     mFlashNvStorageVariableBase;
++
++/**
++  Initialize the FV Header and Variable Store Header
++  to support variable operations.
++
++  @param[in]  Instance      Location to initialise the headers.
++
++  @retval     EFI_SUCCESS   Fv init is done.
++
++**/
++EFI_STATUS
++InitializeFvAndVariableStoreHeaders (
++  IN NOR_FLASH_INSTANCE *Instance
++  )
++{
++  EFI_STATUS                          Status;
++  VOID*                               Headers;
++  UINTN                               HeadersLength;
++  EFI_FIRMWARE_VOLUME_HEADER          *FirmwareVolumeHeader;
++  VARIABLE_STORE_HEADER               *VariableStoreHeader;
++
++  if (!Instance->Initialized && Instance->Initialize) {
++    Instance->Initialize (Instance);
++  }
++
++  HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) +
++                  sizeof (EFI_FV_BLOCK_MAP_ENTRY) +
++                  sizeof (VARIABLE_STORE_HEADER);
++  Headers = AllocateZeroPool (HeadersLength);
++
++  FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
++  CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
++  FirmwareVolumeHeader->FvLength =
++      PcdGet32 (PcdFlashNvStorageVariableSize) +
++      PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
++      PcdGet32 (PcdFlashNvStorageFtwSpareSize);
++  FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
++  FirmwareVolumeHeader->Attributes = EFI_FVB2_READ_ENABLED_CAP |
++                                     EFI_FVB2_READ_STATUS |
++                                     EFI_FVB2_STICKY_WRITE |
++                                     EFI_FVB2_MEMORY_MAPPED |
++                                     EFI_FVB2_ERASE_POLARITY |
++                                     EFI_FVB2_WRITE_STATUS |
++                                     EFI_FVB2_WRITE_ENABLED_CAP;
++
++  FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) +
++                                       sizeof (EFI_FV_BLOCK_MAP_ENTRY);
++  FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
++  FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->LastBlock + 1;
++  FirmwareVolumeHeader->BlockMap[0].Length    = Instance->BlockSize;
++  FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
++  FirmwareVolumeHeader->BlockMap[1].Length    = 0;
++  FirmwareVolumeHeader->Checksum = CalculateCheckSum16 (
++                                     (UINT16*)FirmwareVolumeHeader,
++                                     FirmwareVolumeHeader->HeaderLength);
++
++  VariableStoreHeader = (VOID *)((UINTN)Headers +
++                                 FirmwareVolumeHeader->HeaderLength);
++  CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
++  VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) -
++                              FirmwareVolumeHeader->HeaderLength;
++  VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
++  VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
++
++  // Install the combined super-header in the NorFlash
++  Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
++
++  FreePool (Headers);
++  return Status;
++}
++
++/**
++  Check the integrity of firmware volume header.
++
++  @param[in]  Instance        Instance of Nor flash variable region.
++
++  @retval     EFI_SUCCESS     The firmware volume is consistent.
++  @retval     EFI_NOT_FOUND   The firmware volume has been corrupted.
++
++**/
++EFI_STATUS
++ValidateFvHeader (
++  IN  NOR_FLASH_INSTANCE *Instance
++  )
++{
++  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader;
++  VARIABLE_STORE_HEADER       *VariableStoreHeader;
++  UINTN                       VariableStoreLength;
++  UINTN                       FvLength;
++
++  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Instance->RegionBaseAddress;
++
++  FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) +
++             PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
++             PcdGet32 (PcdFlashNvStorageFtwSpareSize);
++
++  if ((FwVolHeader->Revision  != EFI_FVH_REVISION)
++      || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
++      || (FwVolHeader->FvLength  != FvLength)
++      )
++  {
++    DEBUG ((DEBUG_ERROR, "%a: No Firmware Volume header present\n",
++      __FUNCTION__));
++    return EFI_NOT_FOUND;
++  }
++
++  // Check the Firmware Volume Guid
++  if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid)) {
++    DEBUG ((DEBUG_ERROR, "%a: Firmware Volume Guid non-compatible\n",
++      __FUNCTION__));
++    return EFI_NOT_FOUND;
++  }
++
++  VariableStoreHeader = (VOID *)((UINTN)FwVolHeader +
++                                 FwVolHeader->HeaderLength);
++
++  // Check the Variable Store Guid
++  if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) &&
++      !CompareGuid (&VariableStoreHeader->Signature,
++        &gEfiAuthenticatedVariableGuid)) {
++    DEBUG ((DEBUG_ERROR, "%a: Variable Store Guid non-compatible\n",
++      __FUNCTION__));
++    return EFI_NOT_FOUND;
++  }
++
++  VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) -
++                        FwVolHeader->HeaderLength;
++  if (VariableStoreHeader->Size != VariableStoreLength) {
++    DEBUG ((DEBUG_ERROR, "%a: Variable Store Length does not match\n",
++      __FUNCTION__));
++    return EFI_NOT_FOUND;
++  }
++  return EFI_SUCCESS;
++}
++
++/**
++ Retrieves the attributes and current settings of the block.
++
++ @param[in]   This         Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[out]  Attributes   Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
++                           current settings are returned.
++                           Type EFI_FVB_ATTRIBUTES_2 is defined in
++                           EFI_FIRMWARE_VOLUME_HEADER.
++
++ @retval      EFI_SUCCESS  The firmware volume attributes were returned.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbGetAttributes(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL    *This,
++  OUT       EFI_FVB_ATTRIBUTES_2                   *Attributes
++  )
++{
++  EFI_FVB_ATTRIBUTES_2  FlashFvbAttributes;
++
++  FlashFvbAttributes = EFI_FVB2_READ_ENABLED_CAP | EFI_FVB2_READ_STATUS |
++                       EFI_FVB2_WRITE_ENABLED_CAP | EFI_FVB2_WRITE_STATUS |
++                       EFI_FVB2_STICKY_WRITE | EFI_FVB2_MEMORY_MAPPED |
++                       EFI_FVB2_ERASE_POLARITY;
++
++  *Attributes = FlashFvbAttributes;
++
++  DEBUG ((DEBUG_INFO, "FvbGetAttributes(0x%X)\n", *Attributes));
++
++  return EFI_SUCCESS;
++}
++
++/**
++ Sets configurable firmware volume attributes and returns the
++ new settings of the firmware volume.
++
++
++ @param[in]         This                     EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in, out]    Attributes               On input, Attributes is a pointer to
++                                             EFI_FVB_ATTRIBUTES_2 that contains the desired
++                                             firmware volume settings.
++                                             On successful return, it contains the new
++                                             settings of the firmware volume.
++
++ @retval            EFI_UNSUPPORTED          The firmware volume attributes are not supported.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbSetAttributes(
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL  *This,
++  IN OUT    EFI_FVB_ATTRIBUTES_2                 *Attributes
++  )
++{
++  DEBUG ((DEBUG_INFO, "FvbSetAttributes(0x%X) is not supported\n",
++    *Attributes));
++  return EFI_UNSUPPORTED;
++}
++
++/**
++ Retrieves the base address of a memory-mapped firmware volume.
++ This function should be called only for memory-mapped firmware volumes.
++
++ @param[in]     This               EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[out]    Address            Pointer to a caller-allocated
++                                   EFI_PHYSICAL_ADDRESS that, on successful
++                                   return from GetPhysicalAddress(), contains the
++                                   base address of the firmware volume.
++
++ @retval        EFI_SUCCESS        The firmware volume base address was returned.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbGetPhysicalAddress (
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL  *This,
++  OUT       EFI_PHYSICAL_ADDRESS                 *Address
++  )
++{
++  NOR_FLASH_INSTANCE *Instance;
++
++  Instance = INSTANCE_FROM_FVB_THIS (This);
++
++  DEBUG ((DEBUG_INFO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n",
++    Instance->RegionBaseAddress));
++
++  ASSERT(Address != NULL);
++
++  *Address = Instance->RegionBaseAddress;
++  return EFI_SUCCESS;
++}
++
++/**
++ Retrieves the size of the requested block.
++ It also returns the number of additional blocks with the identical size.
++ The GetBlockSize() function is used to retrieve the block map
++ (see EFI_FIRMWARE_VOLUME_HEADER).
++
++
++ @param[in]     This                     EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in]     Lba                      Indicates the block whose size to return
++
++ @param[out]    BlockSize                Pointer to a caller-allocated UINTN in which
++                                         the size of the block is returned.
++
++ @param[out]    NumberOfBlocks           Pointer to a caller-allocated UINTN in
++                                         which the number of consecutive blocks,
++                                         starting with Lba, is returned. All
++                                         blocks in this range have a size of
++                                         BlockSize.
++
++ @retval        EFI_SUCCESS              The firmware volume base address was returned.
++
++ @retval        EFI_INVALID_PARAMETER    The requested LBA is out of range.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbGetBlockSize (
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL  *This,
++  IN        EFI_LBA                              Lba,
++  OUT       UINTN                                *BlockSize,
++  OUT       UINTN                                *NumberOfBlocks
++  )
++{
++  EFI_STATUS Status;
++  NOR_FLASH_INSTANCE *Instance;
++
++  Instance = INSTANCE_FROM_FVB_THIS (This);
++
++  DEBUG ((DEBUG_INFO,
++    "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba,
++    Instance->BlockSize, Instance->LastBlock));
++
++  if (Lba > Instance->LastBlock) {
++    DEBUG ((DEBUG_ERROR,
++      "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n",
++      Lba, Instance->LastBlock));
++    Status = EFI_INVALID_PARAMETER;
++  } else {
++    // This is easy because in this platform each NorFlash device has equal sized blocks.
++    *BlockSize = (UINTN) Instance->BlockSize;
++    *NumberOfBlocks = (UINTN) (Instance->LastBlock - Lba + 1);
++
++    DEBUG ((DEBUG_INFO,
++      "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize,
++      *NumberOfBlocks));
++
++    Status = EFI_SUCCESS;
++  }
++
++  return Status;
++}
++
++/**
++ Reads the specified number of bytes into a buffer from the specified block.
++
++ The Read() function reads the requested number of bytes from the
++ requested block and stores them in the provided buffer.
++
++ @param[in]       This                 EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in]       Lba                  The starting logical block index from which to read
++
++ @param[in]       Offset               Offset into the block at which to begin reading.
++
++ @param[in, out]  NumBytes             Pointer to a UINTN.
++                                       At entry, *NumBytes contains the total size of the
++                                       buffer. *NumBytes should have a non zero value.
++                                       At exit, *NumBytes contains the total number of
++                                       bytes read.
++
++ @param[in, out]  Buffer               Pointer to a caller-allocated buffer that will be
++                                       used to hold the data that is read.
++
++ @retval          EFI_SUCCESS          The firmware volume was read successfully, and
++                                       contents are in Buffer.
++
++ @retval          EFI_BAD_BUFFER_SIZE  Read attempted across an LBA boundary.
++
++ @retval          EFI_DEVICE_ERROR     The block device is not functioning correctly and
++                                       could not be read.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbRead (
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL   *This,
++  IN        EFI_LBA                               Lba,
++  IN        UINTN                                 Offset,
++  IN OUT    UINTN                                 *NumBytes,
++  IN OUT    UINT8                                 *Buffer
++  )
++{
++  EFI_STATUS    Status;
++  UINTN         BlockSize;
++  NOR_FLASH_INSTANCE *Instance;
++
++  Instance = INSTANCE_FROM_FVB_THIS (This);
++
++  DEBUG ((DEBUG_INFO,
++    "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n",
++    Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
++
++  if (!Instance->Initialized && Instance->Initialize) {
++    Instance->Initialize(Instance);
++  }
++
++  BlockSize = Instance->BlockSize;
++
++  DEBUG ((DEBUG_INFO,
++    "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n",
++    Offset, *NumBytes, BlockSize ));
++
++  // The read must not span block boundaries.
++  // We need to check each variable individually because adding two large
++  // values together overflows.
++  if (Offset               >= BlockSize ||
++      *NumBytes            >  BlockSize ||
++      (Offset + *NumBytes) >  BlockSize) {
++    DEBUG ((DEBUG_ERROR,
++      "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n",
++      Offset, *NumBytes, BlockSize ));
++    return EFI_BAD_BUFFER_SIZE;
++  }
++
++  // We must have some bytes to read
++  if (*NumBytes == 0) {
++    return EFI_BAD_BUFFER_SIZE;
++  }
++
++  // Decide if we are doing full block reads or not.
++  if (*NumBytes % BlockSize != 0) {
++    Status = NorFlashRead (Instance, Instance->StartLba + Lba, Offset,
++                   *NumBytes, Buffer);
++  } else {
++    // Read NOR Flash data into shadow buffer
++    Status = NorFlashReadBlocks (Instance, Instance->StartLba + Lba,
++                   BlockSize, Buffer);
++  }
++  if (EFI_ERROR (Status)) {
++    // Return one of the pre-approved error statuses
++    return EFI_DEVICE_ERROR;
++  }
++  return EFI_SUCCESS;
++}
++
++/**
++ Writes the specified number of bytes from the input buffer to the block.
++
++ @param[in]        This                 EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
++
++ @param[in]        Lba                  The starting logical block index to write to.
++
++ @param[in]        Offset               Offset into the block at which to begin writing.
++
++ @param[in, out]   NumBytes             The pointer to a UINTN.
++                                        At entry, *NumBytes contains the total size of the
++                                        buffer.
++                                        At exit, *NumBytes contains the total number of
++                                        bytes actually written.
++
++ @param[in]        Buffer               The pointer to a caller-allocated buffer that
++                                        contains the source for the write.
++
++ @retval           EFI_SUCCESS          The firmware volume was written successfully.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbWrite (
++  IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL   *This,
++  IN        EFI_LBA                               Lba,
++  IN        UINTN                                 Offset,
++  IN OUT    UINTN                                 *NumBytes,
++  IN        UINT8                                 *Buffer
++  )
++{
++  NOR_FLASH_INSTANCE *Instance;
++
++  Instance = INSTANCE_FROM_FVB_THIS (This);
++
++  return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset,
++           NumBytes, Buffer);
++}
++
++/**
++ Erases and initialises a firmware volume block.
++
++ @param[in]   This                     EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
++
++ @param[in]   ...                      The variable argument list is a list of tuples.
++                                       Each tuple describes a range of LBAs to erase
++                                       and consists of the following:
++                                       - An EFI_LBA that indicates the starting LBA
++                                       - A UINTN that indicates the number of blocks
++                                       to erase.
++
++                                       The list is terminated with an
++                                       EFI_LBA_LIST_TERMINATOR.
++
++ @retval      EFI_SUCCESS              The erase request successfully completed.
++
++ @retval      EFI_ACCESS_DENIED        The firmware volume is in the WriteDisabled
++                                       state.
++
++ @retval      EFI_DEVICE_ERROR         The block device is not functioning correctly
++                                       and could not be written.
++                                       The firmware device may have been partially
++                                       erased.
++
++ @retval      EFI_INVALID_PARAMETER   One or more of the LBAs listed in the variable
++                                      argument list do not exist in the firmware
++                                      volume.
++
++**/
++EFI_STATUS
++EFIAPI
++FvbEraseBlocks (
++  IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
++  ...
++  )
++{
++  EFI_STATUS  Status;
++  VA_LIST     Args;
++  UINTN       BlockAddress; // Physical address of Lba to erase
++  EFI_LBA     StartingLba;  // Lba from which we start erasing
++  UINTN       NumOfLba;     // Number of Lba blocks to erase
++  NOR_FLASH_INSTANCE *Instance;
++
++  Instance = INSTANCE_FROM_FVB_THIS (This);
++
++  DEBUG ((DEBUG_INFO, "FvbEraseBlocks()\n"));
++
++  Status = EFI_SUCCESS;
++
++  // Before erasing, check the entire list of parameters to ensure
++  // all specified blocks are valid
++
++  VA_START (Args, This);
++  do {
++    // Get the Lba from which we start erasing
++    StartingLba = VA_ARG (Args, EFI_LBA);
++
++    // Have we reached the end of the list?
++    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
++      break;
++    }
++
++    // How many Lba blocks are we requested to erase?
++    NumOfLba = VA_ARG (Args, UINT32);
++
++    // All blocks must be within range
++    DEBUG ((DEBUG_INFO,
++      "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%d - 1 ) > LastBlock=%ld.\n",
++      Instance->StartLba + StartingLba, NumOfLba, Instance->LastBlock));
++    if (NumOfLba == 0 ||
++        (Instance->StartLba + StartingLba + NumOfLba - 1) >
++        Instance->LastBlock) {
++      VA_END (Args);
++      DEBUG ((DEBUG_ERROR,
++        "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
++      return EFI_INVALID_PARAMETER;
++    }
++  } while (TRUE);
++  VA_END (Args);
++
++  VA_START (Args, This);
++  do {
++    // Get the Lba from which we start erasing
++    StartingLba = VA_ARG (Args, EFI_LBA);
++
++    // Have we reached the end of the list?
++    if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
++      // Exit the while loop
++      break;
++    }
++
++    // How many Lba blocks are we requested to erase?
++    NumOfLba = VA_ARG (Args, UINT32);
++
++    // Go through each one and erase it
++    while (NumOfLba > 0) {
++
++      // Get the physical address of Lba to erase
++      BlockAddress = GET_NOR_BLOCK_ADDRESS (
++                       Instance->RegionBaseAddress,
++                       Instance->StartLba + StartingLba,
++                       Instance->BlockSize
++                       );
++
++      // Erase it
++      DEBUG ((DEBUG_INFO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n",
++        Instance->StartLba + StartingLba, BlockAddress));
++      Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
++      if (EFI_ERROR(Status)) {
++        VA_END (Args);
++        return EFI_DEVICE_ERROR;
++      }
++
++      // Move to the next Lba
++      StartingLba++;
++      NumOfLba--;
++    }
++  } while (TRUE);
++  VA_END (Args);
++
++  return Status;
++
++}
+diff --git a/Platform/ARM/N1Sdp/N1SdpPlatform.dec b/Platform/ARM/N1Sdp/N1SdpPlatform.dec
+index 16937197..986a078f 100644
+--- a/Platform/ARM/N1Sdp/N1SdpPlatform.dec
++++ b/Platform/ARM/N1Sdp/N1SdpPlatform.dec
+@@ -1,7 +1,7 @@
+ ## @file

+ #  Describes the N1Sdp configuration.

+ #

+-#  Copyright (c) 2021, ARM Limited. All rights reserved.<BR>

++#  Copyright (c) 2021-2022, ARM Limited. All rights reserved.<BR>

+ #

+ #  SPDX-License-Identifier: BSD-2-Clause-Patent

+ ##

+@@ -89,3 +89,6 @@
+   # unmapped reserved region results in a DECERR response.

+   #

+   gArmN1SdpTokenSpaceGuid.PcdCsComponentSize|0x1000|UINT32|0x00000049

++

++  # Base address of Cadence QSPI controller configuration registers

++  gArmN1SdpTokenSpaceGuid.PcdCadenceQspiDxeRegBaseAddress|0x1C0C0000|UINT32|0x0000004A