meta-nuvoton: add support to generate full flash image for npcm8xx

Nuvoton's npcm8xx full flash image includes TIP FW, Bootblock,
ATF, OPTEE and UBOOT with headers. Generating headers and merging
images are being done by Nuvoton's binary generator tool (Bingo)
which uses external parameters from XML files for that.
Thus, we need to add related fitimage and image type for npcm8xx.

However, before merge this commit, we must wait for below commits were merged.

meta-nuvoton: arm-trusted-firmware: add arm trusted firmware recipe
https://gerrit.openbmc.org/c/openbmc/openbmc/+/55234

meta-nuvoton: add npcm8xx-bootblock recipe
https://gerrit.openbmc.org/c/openbmc/openbmc/+/55117

meta-nuvoton: add npcm8xx-igps recipe
https://gerrit.openbmc.org/c/openbmc/openbmc/+/55099

meta-nuvoton: npcm7xx-bingo: upgrade latest version 0.0.5 support Arbel
https://gerrit.openbmc.org/c/openbmc/openbmc/+/55128

Signed-off-by: Tim Lee <timlee660101@gmail.com>
Change-Id: I4599e39d3873f07cde6904d0f10161964fc45c7a
diff --git a/meta-nuvoton/conf/machine/evb-npcm845.conf b/meta-nuvoton/conf/machine/evb-npcm845.conf
new file mode 100644
index 0000000..47fdff2
--- /dev/null
+++ b/meta-nuvoton/conf/machine/evb-npcm845.conf
@@ -0,0 +1,54 @@
+KMACHINE = "nuvoton"
+KERNEL_DEVICETREE = "nuvoton/${KMACHINE}-npcm845-evb.dtb"
+
+UBOOT_MACHINE = "ArbelEVB_defconfig"
+UBOOT_DEVICETREE = "nuvoton-npcm845-evb"
+
+IGPS_MACHINE = "EB"
+DEVICE_GEN = "A1"
+
+require conf/machine/include/npcm8xx.inc
+require conf/machine/include/obmc-bsp-common.inc
+
+FLASH_SIZE = "65536"
+FLASH_UBOOT_OFFSET:flash-65536 = "0"
+FLASH_KERNEL_OFFSET:flash-65536 = "2048"
+FLASH_ROFS_OFFSET:flash-65536 = "10240"
+FLASH_RWFS_OFFSET:flash-65536 = "46080"
+
+IMAGE_FSTYPES += "cpio.${INITRAMFS_CTYPE}.u-boot"
+IMAGE_FSTYPES += "${@bb.utils.contains('DISTRO_FEATURES', \
+        'phosphor-mmc', \
+        'wic.gz mmc-ext4-tar', \
+        '', d)}"
+
+MACHINE_FEATURES += "\
+        obmc-phosphor-fan-mgmt \
+        obmc-phosphor-chassis-mgmt \
+        obmc-phosphor-flash-mgmt \
+        obmc-host-ipmi \
+        obmc-host-state-mgmt \
+        obmc-chassis-state-mgmt \
+        obmc-bmc-state-mgmt \
+        "
+
+KCS_DEVICE = "ipmi-kcs1"
+
+DISTRO_FEATURES:append = " ext2"
+MACHINE_FEATURES:append = " ext2"
+
+VIRTUAL-RUNTIME_obmc-host-state-manager ?= "x86-power-control"
+VIRTUAL-RUNTIME_obmc-chassis-state-manager ?= "x86-power-control"
+
+PREFERRED_PROVIDER_virtual/obmc-chassis-mgmt = "packagegroup-evb-npcm845-apps"
+PREFERRED_PROVIDER_virtual/obmc-fan-mgmt = "packagegroup-evb-npcm845-apps"
+PREFERRED_PROVIDER_virtual/obmc-flash-mgmt = "packagegroup-evb-npcm845-apps"
+PREFERRED_PROVIDER_virtual/obmc-system-mgmt = "packagegroup-evb-npcm845-apps"
+PREFERRED_PROVIDER_virtual/obmc-host-ipmi-hw = "phosphor-ipmi-kcs"
+PREFERRED_PROVIDER_virtual/phosphor-led-manager-config-native = "evb-npcm845-led-manager-config-native"
+
+# Remove unneeded binaries from image
+IMAGE_FEATURES:remove = "obmc-fan-control"
+IMAGE_FEATURES:remove = "obmc-health-monitor"
+
+MACHINE_EXTRA_RRECOMMENDS = "kernel-modules"
diff --git a/meta-nuvoton/conf/machine/include/npcm8xx.inc b/meta-nuvoton/conf/machine/include/npcm8xx.inc
new file mode 100644
index 0000000..fafa92d
--- /dev/null
+++ b/meta-nuvoton/conf/machine/include/npcm8xx.inc
@@ -0,0 +1,48 @@
+#@TYPE: Machine
+#@NAME: Nuvoton NPCM8XX
+#@DESCRIPTION: Common machine configuration for Nuvoton NPCM8XX Chip
+
+require conf/machine/include/nuvoton.inc
+
+KERNEL_IMAGETYPE ?= "Image"
+KERNEL_EXTRA_ARGS ?= "UIMAGE_LOADADDR=0x00008000"
+
+UBOOT_MACHINE ?= "ArbelEVB_defconfig"
+UBOOT_ENTRYPOINT ?= "0"
+UBOOT_LOADADDRESS ?= "0"
+
+FLASH_SIZE ?= "32768"
+FLASH_UBOOT_OFFSET ?= "0"
+FLASH_KERNEL_OFFSET ?= "2048"
+FLASH_ROFS_OFFSET ?= "8192"
+FLASH_RWFS_OFFSET ?= "31744"
+
+# UBI volume sizes in KB unless otherwise noted.
+FLASH_UBI_RWFS_SIZE ?= "6144"
+FLASH_UBI_RWFS_TXT_SIZE ?= "6MiB"
+
+SERIAL_CONSOLES ?= "115200;ttyS0"
+
+SOC_FAMILY = "npcm8xx"
+include conf/machine/include/soc-family.inc
+MACHINEOVERRIDES .= ":npcm8xx"
+
+require conf/machine/include/arm/armv8a/tune-cortexa35.inc
+
+PREFERRED_VERSION_trusted-firmware-a = "2.6.0"
+
+UBOOT_MKIMAGE:append:npcm8xx = " -E -B 8"
+
+COMPATIBLE_MACHINE:npcm8xx = "npcm8xx"
+TFA_PLATFORM = "npcm845x"
+
+# Nuvoton prefers optee for BL32.
+TFA_SPD = "opteed"
+
+# Nuvoton prefers u-boot as BL33.
+TFA_UBOOT = "1"
+
+# Nuvoton prefers TFA default build is BL31.
+TFA_BUILD_TARGET = "bl31"
+
+OPTEEMACHINE ?= "nuvoton"
diff --git a/meta-phosphor/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass b/meta-phosphor/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass
new file mode 100644
index 0000000..93ff3e9
--- /dev/null
+++ b/meta-phosphor/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass
@@ -0,0 +1,128 @@
+UBOOT_BINARY := "u-boot.${UBOOT_SUFFIX}"
+BOOTBLOCK = "BootBlockAndHeader.bin"
+ATF_BINARY := "bl31AndHeader.bin"
+OPTEE_BINARY := "teeAndHeader.bin"
+KMT_TIPFW_BINARY := "Kmt_TipFwL0_Skmt_TipFwL1.bin"
+KMT_TIPFW_BB_BINARY = "Kmt_TipFw_BootBlock.bin"
+KMT_TIPFW_BB_BL31_BINARY = "Kmt_TipFw_BootBlock_BL31.bin"
+KMT_TIPFW_BB_BL31_TEE_BINARY = "Kmt_TipFw_BootBlock_BL31_Tee.bin"
+KMT_TIPFW_BB_UBOOT_BINARY = "u-boot.bin.merged"
+FULL_SUFFIX = "full"
+MERGED_SUFFIX = "merged"
+
+IGPS_DIR = "${STAGING_DIR_NATIVE}/${datadir}/npcm8xx-igps"
+inherit logging
+
+# Prepare the Bootblock and U-Boot images using npcm8xx-bingo
+do_prepare_bootloaders() {
+    local olddir="$(pwd)"
+    cd ${DEPLOY_DIR_IMAGE}
+
+    bingo ${IGPS_DIR}/BL31_AndHeader.xml \
+            -o ${DEPLOY_DIR_IMAGE}/${ATF_BINARY}
+
+    bingo ${IGPS_DIR}/OpTeeAndHeader.xml \
+            -o ${DEPLOY_DIR_IMAGE}/${OPTEE_BINARY}
+
+    bingo ${IGPS_DIR}/BootBlockAndHeader_${DEVICE_GEN}_${IGPS_MACHINE}.xml \
+            -o ${DEPLOY_DIR_IMAGE}/${BOOTBLOCK}
+
+    bingo ${IGPS_DIR}/UbootHeader_${DEVICE_GEN}.xml \
+            -o ${UBOOT_BINARY}.${FULL_SUFFIX}
+
+    cd "$olddir"
+}
+
+python do_merge_bootloaders() {
+
+    def Merge_bin_files_and_pad(inF1, inF2, outF, align, padding_at_end):
+        padding_size = 0
+        padding_size_end = 0
+        F1_size = os.path.getsize(inF1)
+        F2_size = os.path.getsize(inF2)
+
+        if ((F1_size % align) != 0):
+            padding_size = align - (F1_size % align)
+
+        if ((F2_size % align) != 0):
+            padding_size_end = align - (F2_size % align)
+
+        with open(outF, "wb") as file3:
+            with open(inF1, "rb") as file1:
+                data = file1.read()
+                file3.write(data)
+
+            file3.write(b'\xFF' * padding_size)
+
+            with open(inF2, "rb") as file2:
+                data = file2.read()
+                file3.write(data)
+
+            file3.write(b'\xFF' * padding_size_end)
+
+    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BOOTBLOCK',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
+        0x1000, 0x20)
+
+    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('ATF_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_BINARY',True)),
+        0x1000, 0x20)
+
+    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('OPTEE_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_TEE_BINARY',True)),
+        0x1000, 0x20)
+
+    Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_TEE_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s.full' % d.getVar('UBOOT_BINARY',True)),
+        os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_UBOOT_BINARY',True)),
+        0x1000, 0x20)
+}
+
+do_prepare_bootloaders[depends] += " \
+    npcm8xx-tip-fw:do_deploy \
+    npcm8xx-bootblock:do_deploy \
+    trusted-firmware-a:do_deploy \
+    optee-os:do_deploy \
+    npcm7xx-bingo-native:do_populate_sysroot \
+    npcm8xx-igps-native:do_populate_sysroot \
+    "
+
+# link images for we only need to flash partial image with idea name
+do_generate_ext4_tar:append() {
+    cd ${DEPLOY_DIR_IMAGE}
+    ln -sf ${UBOOT_BINARY}.${MERGED_SUFFIX} image-u-boot
+    ln -sf ${DEPLOY_DIR_IMAGE}/${FLASH_KERNEL_IMAGE} image-kernel
+    ln -sf ${S}/ext4/${IMAGE_LINK_NAME}.${FLASH_EXT4_BASETYPE}.zst image-rofs
+    ln -sf ${IMGDEPLOYDIR}/${IMAGE_LINK_NAME}.rwfs.${FLASH_EXT4_OVERLAY_BASETYPE} image-rwfs
+    ln -sf ${IMAGE_NAME}.rootfs.wic.gz image-emmc.gz
+}
+
+addtask do_prepare_bootloaders before do_generate_static after do_generate_rwfs_static
+addtask do_merge_bootloaders before do_generate_static after do_prepare_bootloaders
+addtask do_merge_bootloaders before do_generate_ext4_tar after do_prepare_bootloaders
+
+# Include the full bootblock and u-boot in the final static image
+python do_generate_static:append() {
+    _append_image(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
+                               'u-boot.%s' % d.getVar('UBOOT_SUFFIX',True)),
+                  int(d.getVar('FLASH_UBOOT_OFFSET', True)),
+                  int(d.getVar('FLASH_KERNEL_OFFSET', True)))
+}
+
+do_make_ubi:append() {
+    # Concatenate the uboot and ubi partitions
+    dd bs=1k conv=notrunc seek=${FLASH_UBOOT_OFFSET} \
+        if=${DEPLOY_DIR_IMAGE}/u-boot.${UBOOT_SUFFIX} \
+        of=${IMGDEPLOYDIR}/${IMAGE_NAME}.ubi.mtd
+}
+
+do_make_ubi[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_ubi_tar[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_ubi_tar[depends] += "${PN}:do_merge_bootloaders"
+do_generate_static_tar[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_static_tar[depends] += "${PN}:do_merge_bootloaders"
+do_generate_ext4_tar[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_ext4_tar[depends] += "${PN}:do_merge_bootloaders"
diff --git a/meta-phosphor/conf/distro/include/phosphor-base.inc b/meta-phosphor/conf/distro/include/phosphor-base.inc
index 2af46f9..13e3065 100644
--- a/meta-phosphor/conf/distro/include/phosphor-base.inc
+++ b/meta-phosphor/conf/distro/include/phosphor-base.inc
@@ -116,6 +116,7 @@
 
 IMAGE_CLASSES:append = " image_types_phosphor phosphor-rootfs-postcommands"
 IMAGE_CLASSES:append:npcm7xx = " image_types_phosphor_nuvoton"
+IMAGE_CLASSES:append:npcm8xx = " image_types_phosphor_nuvoton_npcm8xx"
 
 IMAGE_INSTALL:append = " dbus-broker libnss-systemd"