FreeCalypso > hg > freecalypso-reveng
view leo-obj/bootloader/Notes @ 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 | |
children |
line wrap: on
line source
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()