changeset 276:85c65bc1d033

leo-obj/bootloader/Notes: bootloader blob reverse-engineered
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 21 Sep 2018 23:08:32 +0000
parents cbd944ebeff0
children 5c47d916255e
files leo-obj/bootloader/Notes
diffstat 1 files changed, 105 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/leo-obj/bootloader/Notes	Fri Sep 21 23:08:32 2018 +0000
@@ -0,0 +1,105 @@
+The present bootloader.lib blob contains not one but two bootloaders inside,
+speaking different protocols.  There is the original TI GSM bootloader, and
+then there is the so-called FLUID bootloader.  The original TI GSM bootloader
+initializes both UARTs at what was intended to be 115200 baud, but will actually
+result in 230400 baud on 26 MHz hardware, as there is no VCLKOUT_DIV2 or
+VTCXO_DIV2 setting done anywhere.  Then it provides a certain time window
+during which it listens on both UARTs for a bootloader command packet, and if
+it gets a COM_GET_MONITOR_ID command, it will respond to it and stop the normal
+flash boot process.  It will then listen for further command packets without a
+timeout.  It appears that this bootloader was originally designed with commands
+that write directly to flash, but the present version no longer has any of those
+commands, and instead it has commands to load a code image into RAM and to jump
+to it.
+
+The so-called FLUID bootloader is a separate beast with its own self-contained
+code and its own serial protocol.  There is one special command packet that can
+be sent to the first bootloader that will cause it to call fluid_bootloader(),
+and the latter function never returns.  The FLUID bootloader reinitializes both
+UARTs again (same baud rate, and same bogosity on 26 MHz platforms), and then
+it sends out a continuous stream of 'H' (hello) characters on both UARTs until
+it hears a response, telling it which UART it should use for further
+communication.
+
+Commands for the original (pre-FLUID) bootloader are binary strings or packets
+of the following format:
+
+* begin with 0xAA byte
+* the byte after the initial 0xAA is the number of bytes to follow,
+  including stuffing bytes
+* the payload bytes follow, if there is 0xAA in the payload, it is duplicated
+
+The command to enter the FLUID bootloader is just 0xDD (one byte) before
+string encoding, or 0xAA 0x01 0xDD in the full packet form which the host
+needs to send.  The native commands for the first bootloader are:
+
+0x00 = COM_GET_MONITOR_ID
+0x09 = COM_LOAD_APPLICATION
+0x0A = COM_SEND_RUN_ADDRESS
+
+COM_GET_MONITOR_ID and COM_LOAD_APPLICATION take no arguments, i.e., just
+0xAA 0x01 and the opcode.  After receiving COM_LOAD_APPLICATION, the bootloader
+will switch to expecting S-records: you need to send it a complete S-record
+image consisting of an S0 header record, one or more S3 payload records and a
+terminating S7 record.  Each S-record is sent as follows: the 'S' character and
+the record type digit are sent literally in ASCII, then the rest of the record
+(starting with the length byte and ending with the checksum) is sent as binary
+bytes.  No CR or LF characters are sent over the wire.  The code is designed to
+take *.m0 S-record images produced by TI's hex470: the S0 and S7 records must
+be exactly as produced by that tool, no variations allowed, and the data format
+is 16-bit word-oriented with the upper byte first, i.e., byte-reversed relative
+to the natural ARM little-endian byte order.
+
+COM_SEND_RUN_ADDRESS opcode is followed by 4 bytes of address in MSB-first byte
+order, for a total pre-stuffing command packet length of 5 bytes.  This command
+packet is the only one in the present version for which 0xAA escaping may be
+needed.  The transfer of control is done with BX.
+
+cmdboot.obj:
+
+cmd_check_application_in_flash(): checks the 32-bit word in flash where the
+IRQ vector branch points, returns 1 if the word is not all-1s (good image)
+or 0 otherwise (bad image).
+
+convert.obj:
+
+This module has 0x10 bytes of purely local (static) bss.
+
+con_initialize_conversion(): sets 32-bit words at .bss+4 and .bss+0xC to 0.
+
+serial.obj:
+
+.bss+4: byte var initialized to 0 in ser_initialize_flash_data_detection()
+appears to be a boolean flag indicating if the S0 header record
+has already been received or not
+
+.bss+5: S-record checksum accumulator
+
+.bss+7: byte var initialized to 0 in ser_initialize_flash_data_detection()
+used to decide if we are looking for the 'S' character or for the digit
+immediately after the 'S'
+
+.bss+0xC: 32-bit var initialized to 1 in ser_initialize_flash_data_detection()
+0 = receiving payload data bytes
+1 = expect beginning of S-record
+2 = expect the bytes after S0
+3 = expect the bytes after S7
+4 = expect the bytes after S3
+5 = state after the S3 record length byte (receiving address bytes)
+6 = expect S3 record checksum byte
+
+ser_initialize_serial_link(): both UARTs are initialized sensibly, the baud
+rate divisor is set to 7.
+
+start.obj:
+
+static function at 0x0: an init function called immediately at the beginning
+by sta_select_application().  This function disables all interrupts, stops the
+watchdog timer, and puts the DPLL into bypass mode with the external clock
+pass-thru, removing the division by 2 set by the bogus code in bootloader.s.
+
+sta_select_application():
+calls the static function at 0x0
+calls ser_initialize_serial_link()
+calls con_initialize_conversion()
+calls cmd_check_application_in_flash()