summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiang W <wxjstz@126.com>2019-06-13 10:23:12 +0300
committerAnup Patel <anup@brainfault.org>2019-06-17 09:23:42 +0300
commita5b37bd7d275fc65d8fd0b19bd3a08edfe4e6096 (patch)
treecc57dd82905d20bbe983481559dd99b789010d3f
parent331f291e4cff8f0b7b35edded21132c2fa69fb97 (diff)
downloadopensbi-a5b37bd7d275fc65d8fd0b19bd3a08edfe4e6096.tar.xz
firmware: Handle overlapping load and link addresses in relocation
This patch extends relocation to handle overlapping load and link addresses. The updated relocation will work fine in most cases except when the relocate copy loop itself falls in overlapping load and link addresses. Signed-off-by: Xiang W <wxjstz@126.com> Signed-off-by: Anup Patel <anup.patel@wdc.com>
-rw-r--r--firmware/fw_base.S44
1 files changed, 42 insertions, 2 deletions
diff --git a/firmware/fw_base.S b/firmware/fw_base.S
index 1a3c760..6270bbc 100644
--- a/firmware/fw_base.S
+++ b/firmware/fw_base.S
@@ -27,6 +27,17 @@
add \__d4, \__s4, zero
.endm
+/*
+ * If __start_reg <= __check_reg and __check_reg < __end_reg then
+ * jump to __pass
+ */
+.macro BRANGE __start_reg, __end_reg, __check_reg, __jump_lable
+ blt \__check_reg, \__start_reg, 999f
+ bge \__check_reg, \__end_reg, 999f
+ j \__jump_lable
+999:
+.endm
+
.align 3
.section .entry, "ax", %progbits
.globl _start
@@ -45,22 +56,51 @@ _start:
REG_S t1, 0(t0)
/* Relocate if load address != link address */
+_relocate:
la t0, _link_start
REG_L t0, 0(t0)
la t1, _link_end
REG_L t1, 0(t1)
la t2, _load_start
REG_L t2, 0(t2)
+ sub t3, t1, t0
+ add t3, t3, t2
beq t0, t2, _relocate_done
la t4, _relocate_done
sub t4, t4, t2
add t4, t4, t0
-_relocate_copy:
+ blt t2, t0, _relocate_copy_to_upper
+_relocate_copy_to_lower:
+ ble t1, t2, _relocate_copy_to_lower_loop
+ la t3, _boot_hart_done
+ BRANGE t2, t1, t3, _start_hang
+ la t3, _relocate
+ la t5, _relocate_done
+ BRANGE t2, t1, t3, _start_hang
+ BRANGE t2, t1, t5, _start_hang
+ BRANGE t3, t5, t2, _start_hang
+_relocate_copy_to_lower_loop:
REG_L t3, 0(t2)
REG_S t3, 0(t0)
add t0, t0, __SIZEOF_POINTER__
add t2, t2, __SIZEOF_POINTER__
- blt t0, t1, _relocate_copy
+ blt t0, t1, _relocate_copy_to_lower_loop
+ jr t4
+_relocate_copy_to_upper:
+ ble t3, t0, _relocate_copy_to_upper_loop
+ la t2, _boot_hart_done
+ BRANGE t0, t3, t2, _start_hang
+ la t2, _relocate
+ la t5, _relocate_done
+ BRANGE t0, t3, t2, _start_hang
+ BRANGE t0, t3, t5, _start_hang
+ BRANGE t2, t5, t0, _start_hang
+_relocate_copy_to_upper_loop:
+ add t3, t3, -__SIZEOF_POINTER__
+ add t1, t1, -__SIZEOF_POINTER__
+ REG_L t2, 0(t3)
+ REG_S t2, 0(t1)
+ blt t0, t1, _relocate_copy_to_upper_loop
jr t4
_relocate_done: