forked from linux-sunxi/sunxi-tools
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fel: New command for loading U-Boot SPL binaries in eGON format
Now it is possible to load and execute the same U-Boot SPL, as used for booting from SD cards. Just a different delivery method (a USB OTG cable instead of an SD card) for handling exactly the same content. The only argument for this new command is the name of the SPL binary file (with a eGON header generated by the 'mksunxiboot' tool). Now the 'fel' tool can be run as: fel spl u-boot-sunxi-with-spl.bin Before this change, the SPL was only able to use the memory between addresses 0x2000 and ~0x5D00, totalling to something like ~15 KiB. This is the biggest contiguous area in SRAM, which is not used by the FEL code from the BROM. Unfortunately, it is rather small. And also the unusual starting offset was making it difficult to use the same SPL binary for booting from the SD card and via FEL. There are surely more unused parts of SRAM, but they are scattered across multiple locations, primarily because the FEL code from the BROM sets up two stacks at inconvenient locations (the IRQ handler stack at 0x2000, and a regular stack at 0x7000). Essentially, the problem to solve here is to ensure a sufficiently large and consistent SRAM address space for the SPL without any potentially SoC specific holes in the case of booting over USB via FEL. This is achieved by injecting special entry/exit thunk code, which is moving the data in SRAM to provide a contiguous space for the SPL at the beginning of SRAM, while still preserving the the data from the BROM elsewhere. When the SPL tries to return control back to the FEL code in the BROM, the thunk code moves the data back to its original place. Additionally, the eGON checksum is verified to ensure that no data corruption has happened due to some unexpected clash with the FEL protocol code from the BROM. So the thunk code takes care of the address space allocation uglyness and provides the U-Boot SPL with a somewhat nicer abstraction. Now the FEL booted SPL on A10/A13/A20/A31 can use up to 32 KiB of SRAM because the BROM data is saved to different SRAM section. There is also generic code, which does not rely on extra SRAM sections, but just glues together the unused free space from both BROM FEL stacks to provide something like ~21 KiB to the SPL. Signed-off-by: Siarhei Siamashka <siarhei.siamashka@gmail.com>
- Loading branch information
Showing
3 changed files
with
479 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* | ||
* Copyright © 2015 Siarhei Siamashka <siarhei.siamashka@gmail.com> | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a | ||
* copy of this software and associated documentation files (the "Software"), | ||
* to deal in the Software without restriction, including without limitation | ||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
* and/or sell copies of the Software, and to permit persons to whom the | ||
* Software is furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice (including the next | ||
* paragraph) shall be included in all copies or substantial portions of the | ||
* Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
* DEALINGS IN THE SOFTWARE. | ||
*/ | ||
|
||
/*************************************************************************/ | ||
/* Usage instructions: "ruby -x fel-to-spl-thunk.S > fel-to-spl-thunk.h" */ | ||
/*************************************************************************/ | ||
|
||
#if 0 | ||
#!/usr/bin/env ruby | ||
|
||
def tool_exists(tool_name) | ||
`which #{tool_name} > /dev/null 2>&1` | ||
return $?.to_i == 0 | ||
end | ||
|
||
toolchains = [ | ||
"arm-none-eabi-", | ||
"arm-linux-gnueabihf-", | ||
"arm-none-linux-gnueabi-", | ||
"armv7a-hardfloat-linux-gnueabi-", | ||
] | ||
|
||
toolchain = toolchains.find { |toolchain| tool_exists("#{toolchain}gcc") } | ||
abort "Can't find any ARM crosscompiler\n" unless toolchain | ||
|
||
system("#{toolchain}gcc -o #{$PROGRAM_NAME}.o -c #{$PROGRAM_NAME}") | ||
exit($?.to_i) if $?.to_i != 0 | ||
|
||
`#{toolchain}objdump -d #{$PROGRAM_NAME}.o`.each_line {|l| | ||
next unless l =~ /(\h+)\:\s+(\h+)\s+(\S+)\s+([^;]*)/ | ||
printf("\t0x%s, /* %8s: %-10s %-28s */\n", $2, $1, $3, $4.strip) | ||
} | ||
|
||
__END__ | ||
#endif | ||
|
||
/*************************************************************************/ | ||
|
||
BUF1 .req r0 | ||
BUF2 .req r1 | ||
TMP1 .req r2 | ||
TMP2 .req r3 | ||
SWAPTBL .req r4 | ||
FULLSIZE .req r5 | ||
BUFSIZE .req r6 | ||
CHECKSUM .req r7 | ||
|
||
entry_point: | ||
b setup_stack | ||
|
||
stack_begin: | ||
nop | ||
nop | ||
nop | ||
nop | ||
nop | ||
nop | ||
nop | ||
nop | ||
stack_end: | ||
nop | ||
|
||
/* A function, which walks the table and swaps all buffers */ | ||
swap_all_buffers: | ||
adr SWAPTBL, swaptbl_start | ||
swap_next_buffer: | ||
ldr BUF1, [SWAPTBL], #4 | ||
ldr BUF2, [SWAPTBL], #4 | ||
ldr BUFSIZE, [SWAPTBL], #4 | ||
cmp BUFSIZE, #0 | ||
bxeq lr | ||
swap_next_word: | ||
ldr TMP1, [BUF1] | ||
ldr TMP2, [BUF2] | ||
subs BUFSIZE, BUFSIZE, #4 | ||
str TMP1, [BUF2], #4 | ||
str TMP2, [BUF1], #4 | ||
bne swap_next_word | ||
b swap_next_buffer | ||
|
||
setup_stack: /* Save the original SP, LR and CPSR to stack */ | ||
adr BUF1, stack_end | ||
str sp, [BUF1, #-4]! | ||
mov sp, BUF1 | ||
mrs TMP1, cpsr | ||
push {TMP1, lr} | ||
|
||
/* Disable IRQ and FIQ */ | ||
orr TMP1, #0xc0 | ||
msr cpsr_c, TMP1 | ||
|
||
/* Check if the instructions or data cache is enabled */ | ||
mrc p15, 0, TMP1, c1, c0, 0 | ||
movw TMP2, #((1 << 12) | (1 << 2)) | ||
tst TMP1, TMP2 | ||
bne cache_is_unsupported | ||
|
||
bl swap_all_buffers | ||
|
||
verify_checksum: | ||
movw CHECKSUM, #0x6c39 | ||
movt CHECKSUM, #0x5f0a | ||
mov BUF1, #0 | ||
ldr FULLSIZE, [BUF1, #16] | ||
check_next_word: | ||
ldr TMP1, [BUF1], #4 | ||
subs FULLSIZE, FULLSIZE, #4 | ||
add CHECKSUM, CHECKSUM, TMP1 | ||
bne check_next_word | ||
|
||
mov BUF1, #0 | ||
ldr TMP1, [BUF1, #12] | ||
subs CHECKSUM, CHECKSUM, TMP1, lsl #1 | ||
bne checksum_is_bad | ||
|
||
/* Change 'eGON.BT0' -> 'eGON.FEL' */ | ||
mov BUF1, #0 | ||
movw TMP1, (('F' << 8) + '.') | ||
movt TMP1, (('L' << 8) + 'E') | ||
str TMP1, [BUF1, #8] | ||
|
||
/* Call the SPL code */ | ||
dsb | ||
isb | ||
blx BUF1 | ||
|
||
/* Return back to FEL */ | ||
b return_to_fel | ||
|
||
cache_is_unsupported: | ||
/* Bail out if cache is enabled and change 'eGON.BT0' -> 'eGON.???' */ | ||
mov BUF1, #0 | ||
movw TMP1, (('?' << 8) + '.') | ||
movt TMP1, (('?' << 8) + '?') | ||
str TMP1, [BUF1, #8] | ||
b return_to_fel | ||
|
||
checksum_is_bad: | ||
/* The checksum test failed, so change 'eGON.BT0' -> 'eGON.BAD' */ | ||
mov BUF1, #0 | ||
movw TMP1, (('B' << 8) + '.') | ||
movt TMP1, (('D' << 8) + 'A') | ||
str TMP1, [BUF1, #8] | ||
|
||
return_to_fel: | ||
bl swap_all_buffers | ||
pop {TMP1, lr} | ||
msr cpsr_c, TMP1 /* Restore the original CPSR */ | ||
ldr sp, [sp] | ||
bx lr | ||
|
||
swaptbl_start: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
0xea000015, /* 0: b 5c <setup_stack> */ | ||
0xe1a00000, /* 4: nop */ | ||
0xe1a00000, /* 8: nop */ | ||
0xe1a00000, /* c: nop */ | ||
0xe1a00000, /* 10: nop */ | ||
0xe1a00000, /* 14: nop */ | ||
0xe1a00000, /* 18: nop */ | ||
0xe1a00000, /* 1c: nop */ | ||
0xe1a00000, /* 20: nop */ | ||
0xe1a00000, /* 24: nop */ | ||
0xe28f40e4, /* 28: add r4, pc, #228 */ | ||
0xe4940004, /* 2c: ldr r0, [r4], #4 */ | ||
0xe4941004, /* 30: ldr r1, [r4], #4 */ | ||
0xe4946004, /* 34: ldr r6, [r4], #4 */ | ||
0xe3560000, /* 38: cmp r6, #0 */ | ||
0x012fff1e, /* 3c: bxeq lr */ | ||
0xe5902000, /* 40: ldr r2, [r0] */ | ||
0xe5913000, /* 44: ldr r3, [r1] */ | ||
0xe2566004, /* 48: subs r6, r6, #4 */ | ||
0xe4812004, /* 4c: str r2, [r1], #4 */ | ||
0xe4803004, /* 50: str r3, [r0], #4 */ | ||
0x1afffff9, /* 54: bne 40 <swap_next_word> */ | ||
0xeafffff3, /* 58: b 2c <swap_next_buffer> */ | ||
0xe24f0040, /* 5c: sub r0, pc, #64 */ | ||
0xe520d004, /* 60: str sp, [r0, #-4]! */ | ||
0xe1a0d000, /* 64: mov sp, r0 */ | ||
0xe10f2000, /* 68: mrs r2, CPSR */ | ||
0xe92d4004, /* 6c: push {r2, lr} */ | ||
0xe38220c0, /* 70: orr r2, r2, #192 */ | ||
0xe121f002, /* 74: msr CPSR_c, r2 */ | ||
0xee112f10, /* 78: mrc 15, 0, r2, cr1, cr0, {0} */ | ||
0xe3013004, /* 7c: movw r3, #4100 */ | ||
0xe1120003, /* 80: tst r2, r3 */ | ||
0x1a000014, /* 84: bne dc <cache_is_unsupported> */ | ||
0xebffffe6, /* 88: bl 28 <swap_all_buffers> */ | ||
0xe3067c39, /* 8c: movw r7, #27705 */ | ||
0xe3457f0a, /* 90: movt r7, #24330 */ | ||
0xe3a00000, /* 94: mov r0, #0 */ | ||
0xe5905010, /* 98: ldr r5, [r0, #16] */ | ||
0xe4902004, /* 9c: ldr r2, [r0], #4 */ | ||
0xe2555004, /* a0: subs r5, r5, #4 */ | ||
0xe0877002, /* a4: add r7, r7, r2 */ | ||
0x1afffffb, /* a8: bne 9c <check_next_word> */ | ||
0xe3a00000, /* ac: mov r0, #0 */ | ||
0xe590200c, /* b0: ldr r2, [r0, #12] */ | ||
0xe0577082, /* b4: subs r7, r7, r2, lsl #1 */ | ||
0x1a00000c, /* b8: bne f0 <checksum_is_bad> */ | ||
0xe3a00000, /* bc: mov r0, #0 */ | ||
0xe304262e, /* c0: movw r2, #17966 */ | ||
0xe3442c45, /* c4: movt r2, #19525 */ | ||
0xe5802008, /* c8: str r2, [r0, #8] */ | ||
0xf57ff04f, /* cc: dsb sy */ | ||
0xf57ff06f, /* d0: isb sy */ | ||
0xe12fff30, /* d4: blx r0 */ | ||
0xea000008, /* d8: b 100 <return_to_fel> */ | ||
0xe3a00000, /* dc: mov r0, #0 */ | ||
0xe3032f2e, /* e0: movw r2, #16174 */ | ||
0xe3432f3f, /* e4: movt r2, #16191 */ | ||
0xe5802008, /* e8: str r2, [r0, #8] */ | ||
0xea000003, /* ec: b 100 <return_to_fel> */ | ||
0xe3a00000, /* f0: mov r0, #0 */ | ||
0xe304222e, /* f4: movw r2, #16942 */ | ||
0xe3442441, /* f8: movt r2, #17473 */ | ||
0xe5802008, /* fc: str r2, [r0, #8] */ | ||
0xebffffc8, /* 100: bl 28 <swap_all_buffers> */ | ||
0xe8bd4004, /* 104: pop {r2, lr} */ | ||
0xe121f002, /* 108: msr CPSR_c, r2 */ | ||
0xe59dd000, /* 10c: ldr sp, [sp] */ | ||
0xe12fff1e, /* 110: bx lr */ |
Oops, something went wrong.