Skip to content

Commit 82b9c65

Browse files
committed
fel: Make the SPL load address configurable instead of hardcoded 0x0
Add a new field 'spl_addr' to the SoC description structure and adjust the code to honor it. This is needed for supporting Allwinner A80. Tested on Allwinner A20 by changing the 'spl_addr' to 0x28000 in the 'fel' tool and using a custom build of U-Boot (CONFIG_SPL_TEXT_BASE changed from 0x20 to 0x28020). Signed-off-by: Siarhei Siamashka <siarhei.siamashka@gmail.com> Acked-by: Hans de Goede <hdegoede@redhat.com>
1 parent a69bbe9 commit 82b9c65

File tree

3 files changed

+81
-70
lines changed

3 files changed

+81
-70
lines changed

fel-to-spl-thunk.S

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ SWAPTBL .req r4
6969
FULLSIZE .req r5
7070
BUFSIZE .req r6
7171
CHECKSUM .req r7
72+
SPL_ADDR .req r8
7273

7374
entry_point:
7475
b setup_stack
@@ -87,7 +88,7 @@ stack_end:
8788

8889
/* A function, which walks the table and swaps all buffers */
8990
swap_all_buffers:
90-
adr SWAPTBL, swaptbl_start
91+
adr SWAPTBL, appended_data + 4
9192
swap_next_buffer:
9293
ldr BUF1, [SWAPTBL], #4
9394
ldr BUF2, [SWAPTBL], #4
@@ -104,6 +105,7 @@ swap_next_word:
104105
b swap_next_buffer
105106

106107
setup_stack: /* Save the original SP, LR and CPSR to stack */
108+
ldr SPL_ADDR, appended_data
107109
adr BUF1, stack_end
108110
str sp, [BUF1, #-4]!
109111
mov sp, BUF1
@@ -125,47 +127,43 @@ setup_stack: /* Save the original SP, LR and CPSR to stack */
125127
verify_checksum:
126128
movw CHECKSUM, #0x6c39
127129
movt CHECKSUM, #0x5f0a
128-
mov BUF1, #0
130+
mov BUF1, SPL_ADDR
129131
ldr FULLSIZE, [BUF1, #16]
130132
check_next_word:
131133
ldr TMP1, [BUF1], #4
132134
subs FULLSIZE, FULLSIZE, #4
133135
add CHECKSUM, CHECKSUM, TMP1
134136
bne check_next_word
135137

136-
mov BUF1, #0
137-
ldr TMP1, [BUF1, #12]
138+
ldr TMP1, [SPL_ADDR, #12]
138139
subs CHECKSUM, CHECKSUM, TMP1, lsl #1
139140
bne checksum_is_bad
140141

141142
/* Change 'eGON.BT0' -> 'eGON.FEL' */
142-
mov BUF1, #0
143143
movw TMP1, (('F' << 8) + '.')
144144
movt TMP1, (('L' << 8) + 'E')
145-
str TMP1, [BUF1, #8]
145+
str TMP1, [SPL_ADDR, #8]
146146

147147
/* Call the SPL code */
148148
dsb
149149
isb
150-
blx BUF1
150+
blx SPL_ADDR
151151

152152
/* Return back to FEL */
153153
b return_to_fel
154154

155155
cache_is_unsupported:
156156
/* Bail out if cache is enabled and change 'eGON.BT0' -> 'eGON.???' */
157-
mov BUF1, #0
158157
movw TMP1, (('?' << 8) + '.')
159158
movt TMP1, (('?' << 8) + '?')
160-
str TMP1, [BUF1, #8]
159+
str TMP1, [SPL_ADDR, #8]
161160
b return_to_fel_noswap
162161

163162
checksum_is_bad:
164163
/* The checksum test failed, so change 'eGON.BT0' -> 'eGON.BAD' */
165-
mov BUF1, #0
166164
movw TMP1, (('B' << 8) + '.')
167165
movt TMP1, (('D' << 8) + 'A')
168-
str TMP1, [BUF1, #8]
166+
str TMP1, [SPL_ADDR, #8]
169167

170168
return_to_fel:
171169
bl swap_all_buffers
@@ -175,4 +173,15 @@ return_to_fel_noswap:
175173
ldr sp, [sp]
176174
bx lr
177175

178-
swaptbl_start:
176+
appended_data:
177+
/*
178+
* The appended data uses the following format:
179+
*
180+
* struct {
181+
* uint32_t spl_addr;
182+
* sram_swap_buffers swaptbl[];
183+
* };
184+
*
185+
* More details about the 'spl_addr' variable and the 'sram_swap_buffers'
186+
* struct can be found in the 'fel.c' source file.
187+
*/

fel-to-spl-thunk.h

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
0xe1a00000, /* 1c: nop */
99
0xe1a00000, /* 20: nop */
1010
0xe1a00000, /* 24: nop */
11-
0xe28f40e4, /* 28: add r4, pc, #228 */
11+
0xe28f40dc, /* 28: add r4, pc, #220 */
1212
0xe4940004, /* 2c: ldr r0, [r4], #4 */
1313
0xe4941004, /* 30: ldr r1, [r4], #4 */
1414
0xe4946004, /* 34: ldr r6, [r4], #4 */
@@ -21,49 +21,46 @@
2121
0xe4803004, /* 50: str r3, [r0], #4 */
2222
0x1afffff9, /* 54: bne 40 <swap_next_word> */
2323
0xeafffff3, /* 58: b 2c <swap_next_buffer> */
24-
0xe24f0040, /* 5c: sub r0, pc, #64 */
25-
0xe520d004, /* 60: str sp, [r0, #-4]! */
26-
0xe1a0d000, /* 64: mov sp, r0 */
27-
0xe10f2000, /* 68: mrs r2, CPSR */
28-
0xe92d4004, /* 6c: push {r2, lr} */
29-
0xe38220c0, /* 70: orr r2, r2, #192 */
30-
0xe121f002, /* 74: msr CPSR_c, r2 */
31-
0xee112f10, /* 78: mrc 15, 0, r2, cr1, cr0, {0} */
32-
0xe3013004, /* 7c: movw r3, #4100 */
33-
0xe1120003, /* 80: tst r2, r3 */
34-
0x1a000014, /* 84: bne dc <cache_is_unsupported> */
35-
0xebffffe6, /* 88: bl 28 <swap_all_buffers> */
36-
0xe3067c39, /* 8c: movw r7, #27705 */
37-
0xe3457f0a, /* 90: movt r7, #24330 */
38-
0xe3a00000, /* 94: mov r0, #0 */
39-
0xe5905010, /* 98: ldr r5, [r0, #16] */
40-
0xe4902004, /* 9c: ldr r2, [r0], #4 */
41-
0xe2555004, /* a0: subs r5, r5, #4 */
42-
0xe0877002, /* a4: add r7, r7, r2 */
43-
0x1afffffb, /* a8: bne 9c <check_next_word> */
44-
0xe3a00000, /* ac: mov r0, #0 */
45-
0xe590200c, /* b0: ldr r2, [r0, #12] */
24+
0xe59f80a4, /* 5c: ldr r8, [pc, #164] */
25+
0xe24f0044, /* 60: sub r0, pc, #68 */
26+
0xe520d004, /* 64: str sp, [r0, #-4]! */
27+
0xe1a0d000, /* 68: mov sp, r0 */
28+
0xe10f2000, /* 6c: mrs r2, CPSR */
29+
0xe92d4004, /* 70: push {r2, lr} */
30+
0xe38220c0, /* 74: orr r2, r2, #192 */
31+
0xe121f002, /* 78: msr CPSR_c, r2 */
32+
0xee112f10, /* 7c: mrc 15, 0, r2, cr1, cr0, {0} */
33+
0xe3013004, /* 80: movw r3, #4100 */
34+
0xe1120003, /* 84: tst r2, r3 */
35+
0x1a000012, /* 88: bne d8 <cache_is_unsupported> */
36+
0xebffffe5, /* 8c: bl 28 <swap_all_buffers> */
37+
0xe3067c39, /* 90: movw r7, #27705 */
38+
0xe3457f0a, /* 94: movt r7, #24330 */
39+
0xe1a00008, /* 98: mov r0, r8 */
40+
0xe5905010, /* 9c: ldr r5, [r0, #16] */
41+
0xe4902004, /* a0: ldr r2, [r0], #4 */
42+
0xe2555004, /* a4: subs r5, r5, #4 */
43+
0xe0877002, /* a8: add r7, r7, r2 */
44+
0x1afffffb, /* ac: bne a0 <check_next_word> */
45+
0xe598200c, /* b0: ldr r2, [r8, #12] */
4646
0xe0577082, /* b4: subs r7, r7, r2, lsl #1 */
47-
0x1a00000c, /* b8: bne f0 <checksum_is_bad> */
48-
0xe3a00000, /* bc: mov r0, #0 */
49-
0xe304262e, /* c0: movw r2, #17966 */
50-
0xe3442c45, /* c4: movt r2, #19525 */
51-
0xe5802008, /* c8: str r2, [r0, #8] */
52-
0xf57ff04f, /* cc: dsb sy */
53-
0xf57ff06f, /* d0: isb sy */
54-
0xe12fff30, /* d4: blx r0 */
55-
0xea000008, /* d8: b 100 <return_to_fel> */
56-
0xe3a00000, /* dc: mov r0, #0 */
57-
0xe3032f2e, /* e0: movw r2, #16174 */
58-
0xe3432f3f, /* e4: movt r2, #16191 */
59-
0xe5802008, /* e8: str r2, [r0, #8] */
60-
0xea000004, /* ec: b 104 <return_to_fel_noswap> */
61-
0xe3a00000, /* f0: mov r0, #0 */
62-
0xe304222e, /* f4: movw r2, #16942 */
63-
0xe3442441, /* f8: movt r2, #17473 */
64-
0xe5802008, /* fc: str r2, [r0, #8] */
65-
0xebffffc8, /* 100: bl 28 <swap_all_buffers> */
66-
0xe8bd4004, /* 104: pop {r2, lr} */
67-
0xe121f002, /* 108: msr CPSR_c, r2 */
68-
0xe59dd000, /* 10c: ldr sp, [sp] */
69-
0xe12fff1e, /* 110: bx lr */
47+
0x1a00000a, /* b8: bne e8 <checksum_is_bad> */
48+
0xe304262e, /* bc: movw r2, #17966 */
49+
0xe3442c45, /* c0: movt r2, #19525 */
50+
0xe5882008, /* c4: str r2, [r8, #8] */
51+
0xf57ff04f, /* c8: dsb sy */
52+
0xf57ff06f, /* cc: isb sy */
53+
0xe12fff38, /* d0: blx r8 */
54+
0xea000006, /* d4: b f4 <return_to_fel> */
55+
0xe3032f2e, /* d8: movw r2, #16174 */
56+
0xe3432f3f, /* dc: movt r2, #16191 */
57+
0xe5882008, /* e0: str r2, [r8, #8] */
58+
0xea000003, /* e4: b f8 <return_to_fel_noswap> */
59+
0xe304222e, /* e8: movw r2, #16942 */
60+
0xe3442441, /* ec: movt r2, #17473 */
61+
0xe5882008, /* f0: str r2, [r8, #8] */
62+
0xebffffcb, /* f4: bl 28 <swap_all_buffers> */
63+
0xe8bd4004, /* f8: pop {r2, lr} */
64+
0xe121f002, /* fc: msr CPSR_c, r2 */
65+
0xe59dd000, /* 100: ldr sp, [sp] */
66+
0xe12fff1e, /* 104: bx lr */

fel.c

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,7 @@ typedef struct {
349349
*/
350350
typedef struct {
351351
uint32_t soc_id; /* ID of the SoC */
352+
uint32_t spl_addr; /* SPL load address */
352353
uint32_t scratch_addr; /* A safe place to upload & run code */
353354
uint32_t thunk_addr; /* Address of the thunk code */
354355
uint32_t thunk_size; /* Maximal size of the thunk code */
@@ -695,7 +696,7 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb,
695696
uint32_t sp, sp_irq;
696697
uint32_t spl_checksum, spl_len, spl_len_limit = SPL_LEN_LIMIT;
697698
uint32_t *buf32 = (uint32_t *)buf;
698-
uint32_t written = 0;
699+
uint32_t cur_addr = sram_info->spl_addr;
699700
uint32_t *tt = NULL;
700701

701702
if (!sram_info || !sram_info->swap_buffers) {
@@ -737,23 +738,24 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb,
737738

738739
swap_buffers = sram_info->swap_buffers;
739740
for (i = 0; swap_buffers[i].size; i++) {
740-
if (swap_buffers[i].buf2 < spl_len_limit)
741-
spl_len_limit = swap_buffers[i].buf2;
742-
if (len > 0 && written < swap_buffers[i].buf1) {
743-
uint32_t tmp = swap_buffers[i].buf1 - written;
741+
if ((swap_buffers[i].buf2 >= sram_info->spl_addr) &&
742+
(swap_buffers[i].buf2 < sram_info->spl_addr + spl_len_limit))
743+
spl_len_limit = swap_buffers[i].buf2 - sram_info->spl_addr;
744+
if (len > 0 && cur_addr < swap_buffers[i].buf1) {
745+
uint32_t tmp = swap_buffers[i].buf1 - cur_addr;
744746
if (tmp > len)
745747
tmp = len;
746-
aw_fel_write(usb, buf, written, tmp);
747-
written += tmp;
748+
aw_fel_write(usb, buf, cur_addr, tmp);
749+
cur_addr += tmp;
748750
buf += tmp;
749751
len -= tmp;
750752
}
751-
if (len > 0 && written == swap_buffers[i].buf1) {
753+
if (len > 0 && cur_addr == swap_buffers[i].buf1) {
752754
uint32_t tmp = swap_buffers[i].size;
753755
if (tmp > len)
754756
tmp = len;
755757
aw_fel_write(usb, buf, swap_buffers[i].buf2, tmp);
756-
written += tmp;
758+
cur_addr += tmp;
757759
buf += tmp;
758760
len -= tmp;
759761
}
@@ -771,9 +773,10 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb,
771773

772774
/* Write the remaining part of the SPL */
773775
if (len > 0)
774-
aw_fel_write(usb, buf, written, len);
776+
aw_fel_write(usb, buf, cur_addr, len);
775777

776-
thunk_size = sizeof(fel_to_spl_thunk) + (i + 1) * sizeof(*swap_buffers);
778+
thunk_size = sizeof(fel_to_spl_thunk) + sizeof(sram_info->spl_addr) +
779+
(i + 1) * sizeof(*swap_buffers);
777780

778781
if (thunk_size > sram_info->thunk_size) {
779782
fprintf(stderr, "SPL: bad thunk size (need %d, have %d)\n",
@@ -784,6 +787,8 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb,
784787
thunk_buf = malloc(thunk_size);
785788
memcpy(thunk_buf, fel_to_spl_thunk, sizeof(fel_to_spl_thunk));
786789
memcpy(thunk_buf + sizeof(fel_to_spl_thunk) / sizeof(uint32_t),
790+
&sram_info->spl_addr, sizeof(sram_info->spl_addr));
791+
memcpy(thunk_buf + sizeof(fel_to_spl_thunk) / sizeof(uint32_t) + 1,
787792
swap_buffers, (i + 1) * sizeof(*swap_buffers));
788793

789794
for (i = 0; i < thunk_size / sizeof(uint32_t); i++)
@@ -800,7 +805,7 @@ void aw_fel_write_and_execute_spl(libusb_device_handle *usb,
800805
usleep(250000);
801806

802807
/* Read back the result and check if everything was fine */
803-
aw_fel_read(usb, 4, header_signature, 8);
808+
aw_fel_read(usb, sram_info->spl_addr + 4, header_signature, 8);
804809
if (strcmp(header_signature, "eGON.FEL") != 0) {
805810
fprintf(stderr, "SPL: failure code '%s'\n",
806811
header_signature);

0 commit comments

Comments
 (0)