meta-ampere: mtjade: flash UEFI firmware at 4MB offset

UEFI firmware for Ampere Altra-based platform starts at offset 0x400000
but currently the firmware image is flashed start at offset 0. This
makes the Host fail to boot.
This commit supports offset option for the mtd-util's flashcp utility
and update the script to flash UEFI firmware starting at offset
0x400000.

Tested:
1. Turn on the Host.
2. Flash UEFI firmware. Wait for the flash complete and check if Host
   can boot successfully.
4. Turn off the Host.
5. Flash UEFI firmware. Wait for the flash complete.
6. Turn on the Host and check if Host can boot successfully.

Signed-off-by: Tung Nguyen <tung.nguyen@amperecomputing.com>
Signed-off-by: Thang Q. Nguyen <thang@os.amperecomputing.com>
Change-Id: I0d48bfd0a7b7350b46a98bf10fe4de3887f09f02
diff --git a/meta-ampere/meta-common/recipes-devtools/mtd/mtd-utils/0001-flashcp-support-offset-option.patch b/meta-ampere/meta-common/recipes-devtools/mtd/mtd-utils/0001-flashcp-support-offset-option.patch
new file mode 100644
index 0000000..174a1cd
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-devtools/mtd/mtd-utils/0001-flashcp-support-offset-option.patch
@@ -0,0 +1,143 @@
+From e29268bb252b4eec5830816912817a2650b04ee9 Mon Sep 17 00:00:00 2001
+From: Tung Nguyen <tung.nguyen@amperecomputing.com>
+Date: Tue, 20 Jul 2021 15:32:32 +0700
+Subject: [PATCH] flashcp support offset option
+
+The flashcp command from mtd-utils just support to flash from offset 0.
+Add offset option to specify the start offset so that firmware can be
+flashed correctly
+
+Signed-off-by: Tung Nguyen <tung.nguyen@amperecomputing.com>
+
+%% original patch: 0001-support-flash-offset.patch
+---
+ misc-utils/flashcp.c | 50 +++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 47 insertions(+), 3 deletions(-)
+
+diff --git a/misc-utils/flashcp.c b/misc-utils/flashcp.c
+index d7b0a59..d1ef79c 100644
+--- a/misc-utils/flashcp.c
++++ b/misc-utils/flashcp.c
+@@ -90,7 +90,7 @@ static NORETURN void showusage(bool error)
+ 			"\n"
+ 			"Flash Copy - Written by Abraham van der Merwe <abraham@2d3d.co.za>\n"
+ 			"\n"
+-			"usage: %1$s [ -v | --verbose | -A | --erase-all ] <filename> <device>\n"
++			"usage: %1$s [ -v | --verbose | -A | --erase-all ] <filename> <device> <offset>\n"
+ 			"       %1$s -h | --help\n"
+ 			"       %1$s -V | --version\n"
+ 			"\n"
+@@ -100,6 +100,7 @@ static NORETURN void showusage(bool error)
+ 			"   -V | --version   Show version information and exit\n"
+ 			"   <filename>       File which you want to copy to flash\n"
+ 			"   <device>         Flash device to write to (e.g. /dev/mtd0, /dev/mtd1, etc.)\n"
++			"   <offset>         The start offset. Optional, default: 0\n"
+ 			"\n",
+ 			PROGRAM_NAME);
+ 
+@@ -154,6 +155,16 @@ static void safe_rewind (int fd,const char *filename)
+ 	}
+ }
+ 
++static int safe_rewind_offset(int fd, const char *filename, off_t offset)
++{
++	if (lseek(fd, offset, SEEK_SET) < 0) {
++		log_printf(LOG_ERROR, "While seeking to start of %s: %m\n", filename);
++		return EXIT_FAILURE;
++	}
++
++	return EXIT_SUCCESS;
++}
++
+ /******************************************************************************/
+ 
+ static int dev_fd = -1,fil_fd = -1;
+@@ -167,6 +178,8 @@ static void cleanup (void)
+ int main (int argc,char *argv[])
+ {
+ 	const char *filename = NULL,*device = NULL;
++	off_t offset;
++
+ 	int i,flags = FLAG_NONE;
+ 	ssize_t result;
+ 	size_t size,written;
+@@ -218,6 +231,20 @@ int main (int argc,char *argv[])
+ 				showusage(true);
+ 		}
+ 	}
++
++	if (optind + 3 == argc) {
++		flags |= FLAG_FILENAME;
++		filename = argv[optind];
++		DEBUG("Got filename: %s\n", filename);
++
++		flags |= FLAG_DEVICE;
++		device = argv[optind + 1];
++		DEBUG("Got device: %s\n", device);
++
++		offset = strtoul(argv[optind + 2], NULL, 16);
++		DEBUG("Got offset: 0x%x\n", offset);
++	}
++
+ 	if (optind+2 == argc) {
+ 		flags |= FLAG_FILENAME;
+ 		filename = argv[optind];
+@@ -226,6 +253,8 @@ int main (int argc,char *argv[])
+ 		flags |= FLAG_DEVICE;
+ 		device = argv[optind+1];
+ 		DEBUG("Got device: %s\n",device);
++
++		offset = 0;
+ 	}
+ 
+ 	if (flags & FLAG_HELP || device == NULL)
+@@ -257,6 +286,12 @@ int main (int argc,char *argv[])
+ 		exit (EXIT_FAILURE);
+ 	}
+ 
++	/* does offset is out of the mtd */
++	if (offset > mtd.size) {
++		log_printf(LOG_ERROR, "%s offset won't fit into %s!\n", offset, device);
++		exit(EXIT_FAILURE);
++	}
++
+ 	/*****************************************************
+ 	 * erase enough blocks so that we can write the file *
+ 	 *****************************************************/
+@@ -271,6 +306,8 @@ int main (int argc,char *argv[])
+ 	}
+ 	else
+ 	{
++		/* Erase from the offset */
++		erase.start = offset;
+ 		erase.length = (filestat.st_size + mtd.erasesize - 1) / mtd.erasesize;
+ 		erase.length *= mtd.erasesize;
+ 	}
+@@ -317,6 +354,12 @@ int main (int argc,char *argv[])
+ 	size = filestat.st_size;
+ 	i = BUFSIZE;
+ 	written = 0;
++
++	/* if offset is greater than 0 */
++	if (offset)
++		if (safe_rewind_offset(dev_fd, device, offset) != EXIT_SUCCESS)
++			return EXIT_FAILURE;
++
+ 	while (size)
+ 	{
+ 		if (size < BUFSIZE) i = size;
+@@ -361,8 +404,9 @@ int main (int argc,char *argv[])
+ 	 * verify that flash == file data *
+ 	 **********************************/
+ 
+-	safe_rewind (fil_fd,filename);
+-	safe_rewind (dev_fd,device);
++	safe_rewind(fil_fd, filename);
++	safe_rewind_offset(dev_fd, device, offset);
++
+ 	size = filestat.st_size;
+ 	i = BUFSIZE;
+ 	written = 0;
+-- 
+2.17.1
+
diff --git a/meta-ampere/meta-common/recipes-devtools/mtd/mtd-utils_%.bbappend b/meta-ampere/meta-common/recipes-devtools/mtd/mtd-utils_%.bbappend
new file mode 100644
index 0000000..08aa3ce
--- /dev/null
+++ b/meta-ampere/meta-common/recipes-devtools/mtd/mtd-utils_%.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI += "file://0001-flashcp-support-offset-option.patch "
diff --git a/meta-ampere/meta-jade/conf/machine/mtjade.conf b/meta-ampere/meta-jade/conf/machine/mtjade.conf
index 171a023..e749af6 100644
--- a/meta-ampere/meta-jade/conf/machine/mtjade.conf
+++ b/meta-ampere/meta-jade/conf/machine/mtjade.conf
@@ -15,6 +15,10 @@
 
 OBMC_POWER_SUPPLY_INSTANCES = "0 1"
 
+IMAGE_INSTALL += " \
+                  mtd-utils \
+                 "
+
 OBMC_MACHINE_FEATURES += "\
         obmc-phosphor-chassis-mgmt \
         obmc-phosphor-flash-mgmt \
diff --git a/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh b/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh
index 876671c..7a9ace3 100755
--- a/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh
+++ b/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh
@@ -15,6 +15,8 @@
 # limitations under the License.
 
 do_flash () {
+        OFFSET=$1
+
 	# Check the PNOR partition available
 	HOST_MTD=$(cat /proc/mtd | grep "pnor" | sed -n 's/^\(.*\):.*/\1/p')
 	if [ -z "$HOST_MTD" ];
@@ -30,18 +32,10 @@
 			echo "Fail to probe Host SPI-NOR device"
 			exit 1
 		fi
-
-		echo "--- Flashing firmware to @/dev/$HOST_MTD"
-		flash_eraseall /dev/$HOST_MTD
-		flashcp -v $IMAGE /dev/$HOST_MTD
-
-		echo "--- Unbind the ASpeed SMC driver"
-		echo 1e630000.spi > /sys/bus/platform/drivers/aspeed-smc/unbind
-	else
-		echo "--- Flashing firmware to @/dev/$HOST_MTD"
-		flash_eraseall /dev/$HOST_MTD
-		flashcp -v $IMAGE /dev/$HOST_MTD
 	fi
+
+	echo "--- Flashing firmware to @/dev/$HOST_MTD offset=$OFFSET"
+	flashcp -v $IMAGE /dev/$HOST_MTD $OFFSET
 }
 
 
@@ -84,7 +78,7 @@
 fi
 
 # Flash the firmware
-do_flash
+do_flash 0x400000
 
 # Switch the host SPI bus to HOST."
 echo "--- Switch the host SPI bus to HOST."
@@ -99,5 +93,5 @@
 then
 	sleep 5
 	echo "Turn on the Host"
-	obmcutil chassison
+	obmcutil poweron
 fi