From bc4d6108f4d43996e3d7a74e026fb4f2c4e25ca5 Mon Sep 17 00:00:00 2001
From: Anup Patel <anup.patel@wdc.com>
Date: Wed, 19 Dec 2018 18:32:49 +0530
Subject: blob: payload: Add FW_PAYLOAD_FDT_PATH option

This patch extends fw_payload blob to provide FW_PAYLOAD_FDT_PATH
option using which we can embed custom FDT in .text section of
fw_payload blob. In other words, FW_PAYLOAD_FDT_PATH is an option
to forcefully override FDT passed by previous booting stage in
a1 register.

Signed-off-by: Anup Patel <anup.patel@wdc.com>
---
 blob/fw_common.S  | 19 +++++++++++++++++--
 blob/fw_jump.S    | 11 +++++++++--
 blob/fw_payload.S | 25 ++++++++++++++++++++++---
 blob/objects.mk   |  3 +++
 4 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/blob/fw_common.S b/blob/fw_common.S
index 7faa59a..25bdd55 100644
--- a/blob/fw_common.S
+++ b/blob/fw_common.S
@@ -27,15 +27,30 @@ _bss_zero:
 	add	a4, a4, __SIZEOF_POINTER__
 	blt	a4, a5, _bss_zero
 
+	/* Override pervious arg1 */
+	add	s0, a0, zero
+	add	s1, a1, zero
+	call	fw_prev_arg1
+	add	t1, a0, zero
+	add	a0, s0, zero
+	add	a1, s1, zero
+	beqz	t1, _prev_arg1_override_done
+	add	a1, t1, zero
+_prev_arg1_override_done:
+
 	/*
 	 * Relocate FDT
+	 * source FDT address = previous arg1
+	 * destination FDT address = next arg1
+	 *
 	 * Note: We will preserve a0 and a1 passed by
 	 * previous booting stage.
 	 */
+	beqz	a1, _fdt_reloc_done
 	/* Mask values in a3 and a4 */
 	li	a3, ~0xf
 	li	a4, 0xff
-	/* t1 = destinetion FDT start address */
+	/* t1 = destination FDT start address */
 	add	s0, a0, zero
 	add	s1, a1, zero
 	call	fw_next_arg1
@@ -70,7 +85,7 @@ _bss_zero:
 	or	t2, t2, t3
 	or	t2, t2, t4
 	or	t2, t2, t5
-	/* t2 = destinetion FDT end address */
+	/* t2 = destination FDT end address */
 	add	t2, t1, t2
 	/* FDT copy loop */
 	ble	t2, t1, _fdt_reloc_done
diff --git a/blob/fw_jump.S b/blob/fw_jump.S
index e11a8a9..d05d87f 100644
--- a/blob/fw_jump.S
+++ b/blob/fw_jump.S
@@ -9,13 +9,20 @@
 
 #include "fw_common.S"
 
+	.align 3
+	.section .entry, "ax", %progbits
+	.global fw_prev_arg1
+fw_prev_arg1:
+	/* We return previous arg1 in 'a0' */
+	add	a0, zero, zero
+	ret
+
 	.align 3
 	.section .entry, "ax", %progbits
 	.global fw_next_arg1
 fw_next_arg1:
-	/* We return FDT destination address in 'a0' */
+	/* We return next arg1 in 'a0' */
 #ifdef FW_JUMP_FDT_ADDR
-	/* a0 = destination FDT start address */
 	li	a0, FW_JUMP_FDT_ADDR
 #else
 	add	a0, zero, zero
diff --git a/blob/fw_payload.S b/blob/fw_payload.S
index c601529..b6f3cb9 100644
--- a/blob/fw_payload.S
+++ b/blob/fw_payload.S
@@ -9,13 +9,24 @@
 
 #include "fw_common.S"
 
+	.align 3
+	.section .entry, "ax", %progbits
+	.global fw_prev_arg1
+fw_prev_arg1:
+	/* We return previous arg1 in 'a0' */
+#ifdef FW_PAYLOAD_FDT_PATH
+	la	a0, fdt_bin
+#else
+	add	a0, zero, zero
+#endif
+	ret
+
 	.align 3
 	.section .entry, "ax", %progbits
 	.global fw_next_arg1
 fw_next_arg1:
-	/* We return FDT destination address in 'a0' */
+	/* We return next arg1 in 'a0' */
 #ifdef FW_PAYLOAD_FDT_ADDR
-	/* a0 = destination FDT start address */
 	li	a0, FW_PAYLOAD_FDT_ADDR
 #else
 	add	a0, zero, zero
@@ -33,8 +44,16 @@ fw_next_addr:
 #define	str(s)		#s
 #define	stringify(s)	str(s)
 
+#ifdef FW_PAYLOAD_FDT_PATH
+	.align 3
+	.section .text, "ax", %progbits
+	.globl fdt_bin
+fdt_bin:
+	.incbin	stringify(FW_PAYLOAD_FDT_PATH)
+#endif
+
 	.section .payload, "ax", %progbits
-	.globl	payload_bin
+	.globl payload_bin
 payload_bin:
 #ifndef FW_PAYLOAD_PATH
 	wfi
diff --git a/blob/objects.mk b/blob/objects.mk
index 57ed467..717f455 100644
--- a/blob/objects.mk
+++ b/blob/objects.mk
@@ -31,6 +31,9 @@ endif
 ifdef FW_PAYLOAD_OFFSET
 blob-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_OFFSET=$(FW_PAYLOAD_OFFSET)
 endif
+ifdef FW_PAYLOAD_FDT_PATH
+blob-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_PATH=$(FW_PAYLOAD_FDT_PATH)
+endif
 ifdef FW_PAYLOAD_FDT_ADDR
 blob-cppflags-$(FW_PAYLOAD) += -DFW_PAYLOAD_FDT_ADDR=$(FW_PAYLOAD_FDT_ADDR)
 endif
-- 
cgit v1.2.3