We found the start of RedBoot at 0×300058 in our device. By dumping ram at this location you can see if your device is even remotely related to ours. If not, then use the general techniques described in this article to determine the correct calls for your device.
RedBoot> x -b 0×30058
00030058: 00 00 A0 E3 18 14 9F E5 08 20 91 E5 08 20 80 E5 |……… … ..|
00030068: 00 00 A0 E3 E4 13 9F E5 28 20 91 E5 28 20 80 E5 |……..( ..( ..|
Seeing that data is good. Not seeing that data probably means that you should dump the first 0×100000 bytes of DRAM using the RedBoot x command and start looking around.
To tell you the truth, you should probably be disassembling your own dump to learn how this first stage (well, third-stage actually) bootloader named RedBoot really works. For example, let’s see how the startup looks in disassembly. If you’ve dumped the whole first 2MB of memory, then just load the whole file into your disassembler and begin searching for the start of RedBoot. To make it easy for those without disassemblers, just search for the following sequence of bytes: 00 00 A0 E3 18 14 9F E5 08 20 91 E5 08 20 80 E5
You’ll find the startup routine where you find those bytes. Here’s how it looks in the disassembler.
00 00 A0 E3 MOV R0, #0
18 14 9F E5 LDR R1, =__exception_handlers
08 20 91 E5 LDR R2, [R1,#8]
08 20 80 E5 STR R2, [R0,#8]
00 00 A0 E3 MOV R0, #0
E4 13 9F E5 LDR R1, =__exception_handlers ; From /hal/arch/arm/v2_0/src/vectors.S
To find the printf statement, simply look for a string that is being printed. Chances are the next function call (BL) after that string is loaded will be your printf. Here’s an example of an easy one.
RAM:00046C78 LDR R0, =aRedboot ; “RedBoot> ”
RAM:00046C7C BL rb_diag_printf
The serial port printf is named diag_printf in the RedBoot source code. We’ve named it rb_diag_printf to indicate that it’s a RedBoot-owned function we will be calling. You can use the offset encoded into the instructions, or just double-click the BL operand to go to the start of the printf statement. Again, for those without disasemblers: you can search the following sequence of bytes: 0D C0 A0 E1 0F 00 2D E9 00 D8 2D E9 14 B0 4C E2
And here is how those bytes (the start of printf) looks in the disassembler:
RAM:00045968 0D C0 A0 E1 MOV R12, SP
RAM:0004596C 0F 00 2D E9 STMFD SP!, {R0-R3}
RAM:00045970 00 D8 2D E9 STMFD SP!, {R11,R12,LR,PC}
RAM:00045974 14 B0 4C E2 SUB R11, R12, #0×14
And here’s now it looks being dumped in the RedBoot console.
RedBoot> x -b 0×45968
0045968: 0D C0 A0 E1 0F 00 2D E9 00 D8 2D E9 14 B0 4C E2 |……-…-…L.|
0045978: 28 30 9F E5 00 30 93 E5 00 00 53 E3 01 00 A0 03 |(0…0….S…..|
RedBoot>
diag_printf is located in RAM at 45F08 in BOOT_V15. It’s at 45968 in BOOT_V16. We have not checked any of the other versions, so you really should search your RAM dump to verify that you have the location correctly before trying to call it.
It would also be nice to find a way to take input from the user and process it. RedBoot takes commands – let’s borrow his functions again! The function that we will use is gets - get input until the user presses enter. This particular gets function has a timeout, which is interesting to us. I guess that even if the user falls over dead, the device would like to continue processing, perhaps? Such a dedicated device!
Actually, we already saw this timeout ala “Executing boot script in 0.010 seconds – enter ^C to abort”. So the timeout has some usefulness, we admit. Trace the function back or use the RedBoot source code to tell you where to look, and you shall find the memory address of the good old target function. We found it at 484E0 in V15 and 47F58 in V16. The hex dump for the disasm-imparied is:
RedBoot> x -b 0x47f58
0047F58: 0D C0 A0 E1 00 D8 2D E9 04 B0 4C E2 00 30 A0 E3 |……-…L..0.|
0047F68: 00 30 C0 E5 E8 FD FF EB 00 A8 9D E8 0D C0 A0 E1 |.0…………..|
RedBoot>
Ok, good on finding the functions? Next, you must tell your C compiler the prototype of each of these functions. We can get the definition of diag_printf from the redboot source code, namely
int rb_diag_printf(char* format, …);
int rb_gets(char *line, uint32_t len, uint32_t timeout);
Pretty standard stuff. Again, we’ve prefixed these functions with “rb_” to indicate that they are RedBoot functions and not stuff we’ve written ourselves. OK – Once you know the function prototypes and memory locations, you’re good to go. Either define your prototypes right in your C file, or make another header file to put all that junk in.
Continued on Next Page…




Recent Comments