wiki:Android/HTC/Vision/BootProcess

Boot Process

For the complete list of my articles on Android devices and software, including analysis of devices and system firmware, lists of external resources and tools, and How-To instructions, check the front page of this wiki under the Android heading.

An examination of how the  Qualcomm Mobile Station Modem (MSM) Snapdragon 7x30 system-on-chip boot-straps the processors into an operating system.

There are two processors in the MSM 7x30, an ARM9 for the radio and an ARM11 auxiliary applications processor. Each processor has its own  JTAG and can be independently controlled using it.

ARM9 Boot Process

The ARM9 is the primary processor. It boots first, executing the Primary Boot Loader (PBL) from on-board ROM at 0xFFFF0000 .

The MSM platform has the facility to force Secure Boot using the status of the FORCE_TRUSTED_BOOT Qfuse on-chip or a high-state BOOT_SCUR pin connected to GPIO95. In this mode the PBL verifies the signature of the SBL/OSBL before executing it,which verifies the REX/AMMS signature in the same way.

After some hardware initialisation the PBL reads the Device Boot Loader (DBL) from the first partition of the flash memory device (In Linux, mmcblk0p1).

DBL is part of Qualcomm's SecureBoot, which uses cryptography to guarantee that the boot-loader images haven't been tampered with. DBL configures the Cryptographic Look-aside Processor (CLP), a dedicated cryptographic co-processor, and other hardware sufficient to load and execute the Secondary Boot Loader (SBL) from a Flash memory device on EBI2 (External Bus Interface 2) from partition 3 (Linux mmcblk0p3).

The SBL, also known as the Operating System Boot Loader (OSBL), is loaded into memory at 0x8000000 (IMEM - Internal Memory, the MSM7230 package-on-package (PoP) RAM). This is the ARM9 Monitor (AMON). It provides an Extensible Firmware Interface (EFI) -like environment for controlling the boot process. After doing more hardware configuration including UARTs and USB (for potential remote console connections to the monitor) it loads the Applications processor Secondary Boot Loader (APPSBL a.k.a. hboot) on the ARM11 applications processor from partition 18 (Linux mmcblk0p18) into memory @ 0x8D000000 virtual, 0x00000000 physical.

It then loads and executes the combined REX/AMSS from partition 5 (Linux mmcblk0p5). The image contains the REX (Real-time EXecutive) which is an  L4A Pistachio embedded micro-kernel and  Iguana operating system combination, with extensive Qualcomm and HTC modifications and extensions.

REX is responsible for loading the firmware into the ancillary micro-controller (microP), digital signal processor and voice processor and initialising them. It runs in Security Domain 0 (SD0).

When the ARM11 starts REX unloads/disconnects its eMMC driver and from then on relies on remote procedure calls (RPC) via shared memory (SMEM) to the ARM11 application processor to read and write the eMMC. On the ARM11 side the Linux operating system uses the rmt_storage (remote storage) driver to handle such requests.

Finally on the ARM9 REX executes the Advanced Mobile Subscriber Software (AMSS). AMSS runs in Security Domain 1 (SD1).

ARM11 Boot Process

The ARM9 running REX loads the eMMC "hboot" partition into memory at 0x8D00000 (virtual) and starts the ARM11 auxiliary applications processor executing at this location. It runs in Security Domain 3 (SD3). The core of the boot-loader can be found in the  Android source-code repository in the  platform/bootable/bootloader/legacy.git project. This source-code maps well to current hboot images when they are reverse-engineered; allowing the libc and core functions and structures to be identified.

HBoot

This secondary boot-loader is responsible for configuring, loading, and passing execution to the applications operating system which in this case is Linux. It is also responsible for updating the firmware for the entire device by writing binary images contained in compressed ZIP archives that are distributed via Firmware Over The Air (FOTA) or manual methods, or resetting the device to the same state as when it left the factory. It has several modes of operation:

  1. Fastboot restart
  2. Chain operating system
  3. Chain recovery system
  4. HBoot menu and remote command parser
  5. Fastboot menu and remote command parser
  6. Remote Update Utility (RUU) file transfer mode

Fast Boot Restart

I had previously missed mention of HTC's "fast-boot" functionality which is part of the HTC Sense customisations. From power-off it gets the device ready to make a call in about six seconds (A regular start will take upwards of a minute). From what information is out there it's an ultra-low-power sleep state - something in the PC world we'd call S3 or Suspend-to-RAM. Cyanogen has already replicated it in the 6.1 series.

Without more information it's difficult to be certain how this functions technically but my educated guess is this: When selecting power-off in the user interface the Sense/kernel sends a particular oem-XX code or calls an RPC function to tell the radio to shutdown and remove power from the ARM11 applications processor. I'd suspect the ARM9 radio continues running REX/AMSS but turns off power to almost everything. When the power button is pressed REX brings up the power to devices and restarts the ARM11. Now, the question is, did the ARM11 register state get saved by REX/AMSS so it can be restored and execution restarted where it left off, or does it restart via hboot. If it goes the hboot route then hboot will detect it's a fast-boot and restore contexts and then jump back into the kernel where it'll unfreeze itself.

Update: Having tested this on a U.K. HTC Desire Z it looks likely that hboot isn't re-executed. The green-on-white "htc" splash screen appears briefly (1/2 second maybe) then the Android lock-screen appears. The time take to be ready is less than two seconds. Holding down key-combinations that usually cause hboot to enter special modes are not recognised.

Sources:

 New HTC Fast Boot Technology Already Present On Desire Z/HD Offers 5 Second Boot Times. Smarts, Trickery, Or Both?

 Cyanogen Demos HTC Fast-Boot-A-Like On Nexus One

Chain operating system

Hboot loads the image contained in the eMMC "boot" partition into memory and then passes execution to it. This is the Linux kernel (the compressed vmlinux file found at arch/arm/boot/compressed/ in the kernel build location) and an attached initial RAM-disk - the initrd - which is responsible for configuring the operating system and starting the Android services and graphical user interface (GUI).

Chain recovery system

The boot-loader loads the image contained in the eMMC "recovery" partition into memory and passes execution to it. This is the Linux kernel and an attached initial RAM-disk containing the recovery executable. This reads commands from /recovery/command in the eMMC "cache" partition and performs tasks. It communicates with the boot-loader via the eMMC "misc" partition, which is a raw data image written from, and read into, memory and treated as a character array.

HBoot menu and Remote Command Parser

Using HBoot commands over the serial interface

To set-up a Linux host see Connecting using serial-over-USB to talk to Radio or HBoot

Use the screen utility to connect to the port and talk to the device (before using screen be sure to read the manual carefully especially in relation to the cryptic key-presses required to exit it!):

screen /dev/ttyUSB0

The terminal will be blank to begin with so press Enter. You should see:

hboot>

Commands

Be careful in issuing commands since some can be destructive, such as task 29, which can start a format of critical areas of the device without awaiting further confirmation. Some commands may not be available on all devices - many of them are part of the engineering HBoot which isn't usually installed on retail devices).

battcheck <param1>                                              // battery check
bdaddress <param1>:<param2>:<param3>:<param4>:<param5>:<param6> // set bluetooth address (the bluetooth MAC)
bkflash2emmc                                                    // ?
btrouter                                                        // USB blue-tooth router?
emapi
emapiBand
emapiChannel
emapiCountryID                                                  // display country signature and ID
emapiCounters
emapiCrsuprs <channel>                                          // set carrier suppression mode (channel is 1-14 or 0 to stop test)
emapiDown
emapiEtheradd
emapiFqacurcy
emapiInit
emapiMpc
emapinRate
emapiOut
emapiPkteng_start
emapiPkteng_stop
emapiRate
emapiRateset "default" | "all" | <arbitrary rateset>            // determine the WiFi rates to use
emapiReadCal                                                    // read the WiFi calibration configuration
emapiSetDefCal                                                  // set default WiFi calibration
emapiSetIrqPin
emapiTest
emapiTXpwr1
emapiUp
emapiVersion
emapiWlanMac                                                    // display the WLAN MAC address and where it is stored in non-volatile storage
emptypagecheck                                                  // check empty pages (of what - memory, cache?)
erase <partition_name>                                          // erase data in <partition_name>
erasebcid                                                       // erase back-up CID
eraseconfig <param1>                                            // erase the config fields
erasesd ?                                                       // erase micro SD-card
eraseWifiFlash                                                  // erase WiFi flash memory
fmrouter                                                        // modem AT command shell to switch audio path (for FM radio) and start bt_router
fmtx                                                            // FM transmitter ?
gotofastboot                                                    // switch to fastboot mode
gotohboot                                                       // switch to hboot mode
heap                                                            // report heap memory usage
heaptable                                                       // display the Free and Allocated heap tables
imgcrc                                                          // calculate checksums on hboot, recovery, boot and system partitions
jump                                                            // immediately continue booting the device into the operating system
keytest                                                         // enter key-test mode: displays names of keys being pressed. Exits after 5 presses.
listpartition                                                   // list partition names
partition_test <name> [auto_mark_bad_flag]                      // test a partition
powerdown                                                       // immediately powers down the device
ram_test <start address> <length> <count> <mode>                // test RAM with or without cache
rbchk [partition | block]                                       // read bad-block (artition = <all|recovery|boot|system|cache|userdata>, block id in HEX format)
rebootRUU                                                       // immediately reboot in Remote Update Utility mode (boots with white-on-black HTC logo and waits for update)
readbcid                                                        // read back-up CID
readconfig                                                      // read the config fields
readmbserialno                                                  // read main-board serial number
readserialno                                                    // read device serial number
readsku                                                         // read the SKU fields (PCBID and others)
resetautoimage                                                  // ?
resetpreferdiag                                                 // ?
reset                                                           // immediately reset the device (reboots)
resetuP                                                         // reset microP ?
rflash <param1>                                                 // read NAND flash
rMfgTp                                                          // read manufacturers test points
rtask
savefb2sd <file name> [main|ruu]                                // save frame buffer to SD-card
savemem2sd <memory offset> <length> <file name>                 // save memory region to SD-card
saveprt2sd <partition name> <-n> <file name> <-a>               // save partition to SD-card
sdtest                                                          // test the micro SD-card
task <task number>
tflash                                                          // test NAND flash
tick                                                            // report clock tick
usbspeed ?
usbtestmode <value>
wMfgTp <param1> <...>                                           // write manufacturer test points 
writebcid <param1>                                              // write back-up CID
writeconfig ?
writemid <param1>                                               // write model ID
writeserialno <param1>                                          // write serial number
writesku <param1> <param2>                                      // write SKU field with value 

An example of the emapiReadCal command:

hboot>emapiReadCal
Wlan data header ++++++++++++++++++++
Signature : 0xEE4329
UpdateStatus : 0x1
UpdateCount : 0x1
BodyLength : 0x2B8
BodyCRC : 0xE9B44279
aDieId(0) : 0x0
aDieId(1) : 0x0
aDieId(2) : 0x0
aDieId(3) : 0x0
countryID : 0x10
Wlan data len: 696
Wlan data body --------------------------
macaddr=00:23:76:D4:E0:44
sromrev=3
vendid=0x14e4
devid=0x432f
boardtype=0x4b9
boardrev=0x32
boardflags=0x200
xtalfreq=37400
aa2g=1
aa5g=0
ag0=255
pa0b0=6003
pa0b1=64086
pa0b2=65195
pa0itssit=62
pa0maxpwr=78
opo=20
mcs2gpo0=0xCCCC
mcs2gpo1=0xCCCC
rssismf2g=0xa
rssismc2g=0xb
rssisav2g=0x3
bxa2g=0
ccode=ALL
cctl=0x0
cckdigfilttype=0
ofdmdigfilttype=1
rxpo2g=0
boardnum=1
nocrc=1
otpimagesize=182
hwhdr=0x05ffff031030031003100000
RAW1=80 32 fe 21 02 0c 00 22 2a 01 01 00 00 c5 0 e6 00 00 00 00 00 40 00 00 ff ff 80 00 00 00 00 00 00 00 00 00 00 c8 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 20 04 D0 2 29 43 21 02 0c 00 22 04 00 20 00 5A
sd_gpout=0
sd_oobonly=1

OEM Reboot Codes

Adam (teferi) did some tests on a T-Mobile G2 with the known OEM reboot codes. Here's the results:

--reboot=oem-1F Regular reboot
--reboot=oem-42 HBoot menu
--reboot=oem-74 In some indeterminate state, for all intents and purposes powered off or just plain dead
--reboot=oem-76 Wipe data and cache (factory reset) Amber and Green LEDs flash whilst it is doing it, then the device reboots
--reboot=oem-78 ??

These codes and others are sent to REX/AMMS on the ARM9 radio processor in arch/arm/mach-msm/pm.c. This is a summary of the code that touches restart_reason:

static uint32_t restart_reason = 0x776655AA;

static void msm_pm_restart(char str, const char *cmd)
{
	msm_pm_flush_console();

	/*  always reboot device through proc comm */
	if (restart_reason == 0x6f656d99)
		msm_proc_comm(PCOM_RESET_CHIP_IMM, &restart_reason, 0);
	else
		msm_proc_comm(PCOM_RESET_CHIP, &restart_reason, 0);

#if defined(CONFIG_MSM_RMT_STORAGE_SERVER)
	printk(KERN_INFO "from %s\r\n", __func__);
	wait_rmt_final_call_back(10);
	printk(KERN_INFO "back %s\r\n", __func__);
	/* wait 2 seconds to let radio reset device after the final EFS sync*/
	mdelay(2000);
#else
	/* In case Radio is dead, reset device after notify Radio 5 seconds */
	mdelay(5000);
#endif

	/* hard reboot if possible */
	if (msm_hw_reset_hook) {
		printk(KERN_INFO "%s : Do HW_RESET by APP not by RADIO\r\n", __func__);
		msm_hw_reset_hook();
	}

	for (;;) ;
}

static int msm_reboot_call(struct notifier_block *this, unsigned long code, void *_cmd)
{
	if((code == SYS_RESTART) && _cmd) {
		char *cmd = _cmd;
		if (!strcmp(cmd, "bootloader")) {
			restart_reason = 0x77665500;
		} else if (!strcmp(cmd, "recovery")) {
			restart_reason = 0x77665502;
		} else if (!strcmp(cmd, "eraseflash")) {
			restart_reason = 0x776655EF;
		} else if (!strncmp(cmd, "oem-", 4)) {
			unsigned code = simple_strtoul(cmd + 4, 0, 16) & 0xff;
			restart_reason = 0x6f656d00 | code;
		} else if (!strcmp(cmd, "force-hard")) {
			restart_reason = 0x776655AA;
		} else {
			restart_reason = 0x77665501;
		}
	}
	return NOTIFY_DONE;
}

static struct notifier_block msm_reboot_notifier =
{
	.notifier_call = msm_reboot_call,
};

External Analysis

From the now-deleted QC BQS Analyzer: Booting Sequence Explained

[ 1. QBL (OTP)------------Check of QCSBL header and Config Bits (30 Bit) -> Value hardcoded (Func at FFFF0674)
Load of QCSBL header and Config Bits (Func at FFFF0396)
Check of PBL (SHA1) -> Value hardcoded (Func at FFFF03A0)
Load of PBL (Func at FFFF0260), Entrypoint : 0x0, with given QCSBL Header 2. PBL -------Check of QCSBL (SHA1 + RSA-2048-SHA1 Signature Decryption from QCSBL) (Func at 0xBC)
Load of QCSBL (Func at 0x2FC), Entrypoint : 0x02D4C01C 3. QCSBL--------Check of OEMSBL (SHA1 + RSA-2048-SHA1 Signature Decryption from OEMSBL) (Func at 02D4C118)
Init of OEMSBL (Func at 0x2D4C2A0), Entrypoint : 0x02D9C354
Loading of OEMSBL (Func not yet found)
Check of AMSS (SHA1 + RSA-2048-SHA1 Signature Decryption from AMSS)(Func at 02D4C15C)
Loading of AMSS (Func at 0x02D4C060), Entrypoint : 0x0]