Echo & Alexa Forums

Understanding Echo's U-Boot process

0 Members and 1 Guest are viewing this topic.

gssincla

Understanding Echo's U-Boot process
« on: August 06, 2015, 09:49:11 am »
The moderator (opiette) at another Echo forum made an excellent post (http://www.piettes.com/echo/viewtopic.php?f=6&t=12&sid=57321129f04e2557e080fb595f3c81c0) describing the pin outs at the bottom of the Echo necessary to get a console as well as the console output itself. I recreated the connector using pogo pins and a custom rig I built at home and was able to get similar output from my Echo (i'll post it at the very bottom of this post). I downloaded the lasted source code form the Amazon OSS site for the echo (https://www.amazon.com/gp/help/customer/display.html?nodeId=201626480), which was v1.4 when I wrote this, and decided to figure out if there was a way to break the bootup process and what exactly is going on behind the scenes. This post is my work on that. Spoiler alert: you can't break the u-boot autoboot as it is been disabled in the code.

Let's start by pointing out two very important files within the source code:
  • u-boot\includes\configs\omap3_lab126.h
  • u-boot\board\ti\lab126\evm.h

These two files describe the configuration of the u-boot process at compile time (omap3_lab126.h) and the configuration of the GPIO (evm.h). I highly encourage anyone interested in the hardware hacking side of this to download the .tar.gz file from Amazon and look at these two files. Also, look at the u-boot\board\ti\lab126\ folder for other Echo specific initialization code.

So the start up process... By reviewing the code, starting at the arm_boot() function, I was able to determine what each of the lines spit out to console mean for the Echo's u-boot startup process. Note that the information below is derived from looking at the source code alone and I'm going to skip some steps that don't necessary print anything to screen because otherwise this post would be way too long! Also, I give the source code file locations next to a function's name. All of these files exist under the u-boot directory from the source code .tar.gz.

1. start_armboot(...) called (arch\arm\lib\board.c)
then the initialization is called... (arch\arm\lib\board.c)
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
      if ((*init_fnc_ptr)() != 0) {
         hang ();
      }
   }
   
the functions that are called are defined in init_sequence[] at the top of arch\arm\lib\board.c.
looking at the contents of include\configs\omap3_lab126.h, it is possible to determine the initialization sequence
  • arch_cpu_init (CONFIG_ARCH_CPU_INIT defined)
  • board_init
  • timer_init
  • env_init
  • init_baudrate
  • serial_init
  • console_init_f
  • display_banner (arch\arm\lib\board.c)
Quote
U-Boot 2010.06-00001-g65e5723 (Jun 22 2015 - 22:05:52)
[/list]

2. print_cpuinfo (CONFIG_DISPLAY_CPUINFO defined) (arch\arm\cpu\arm_cortexa8\omap3\sys_info.c)
Quote
OMAP34xx/35xx-GP ES2.1, CPU-OPP2 L3-165MHz

3. checkboard (CONFIG_DISPLAY_BOARDINFO defined) (arch\arm\cpu\arm_cortexa8\omap3\board.c)
Quote
OMAP3 LAB126 board + LPDDR/NAND

4. init_func_i2c (CONFIG_HARD_I2C defined) (arch\arm\lib\board.c)
Quote
I2C:   ready
note that the function call "i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);" is made. According to include\configs\omap3_lab126.h, we know the following:
#define CONFIG_I2C_MULTI_BUS   1
#define CONFIG_HARD_I2C         1
#define CONFIG_SYS_I2C_SPEED      400000
#define CONFIG_SYS_I2C_SLAVE      1
#define CONFIG_SYS_I2C_BUS      0
#define CONFIG_SYS_I2C_BUS_SELECT   1
#define CONFIG_DRIVER_OMAP34XX_I2C   1


If we can find the i2c bus, we can start playing around with those components.

5. dram_init()
6. display_dram_config() (arch\arm\lib\board.c)
Quote
DRAM:  256 MiB

7. mmc_initialize(...) (drivers\mmc\mmc.c)   
Quote
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1

8. env_relocate(...) (common\env_common.c)
Quote
Using default environment

9. console_init_r (common\console.c) calls stdio_print_current_devices() (common\console.c)
Quote
In:    serial
Out:   serial
Err:   serial
   
10. misc_init_r (board\ti\lab126\evm.c) which calls omap3_board_get_revision (board\ti\lab126\evm.c)
Quote
OMAP3 Lab126 Rev: 0x1a
   
11. misc_init_r also calls dieid_num_r (board\tc\lab126\evm.c)
Quote
Die ID #{16 byte hex number here... I removed this}
   
NOTE THAT AFTER THE dieid_num_r happens, the following code occurs which gives you some insight into how i2c is used:
if (is_cpu_family(CPU_OMAP36XX)) {
// Might need to adapt to the TPS65910 if we need to raise mpu power in u-boot
// We'll used default for now and let Linux handle it later.
//         twl4030_power_mpu_init();

      /* Mask the PWR_HOLD Interrupt
       * EVT2.1 and prior, physically connect the RST_PWR_ON to the PWR_HOLD.
       * Prevent the PWR_HOLD from keeping the device in the OFF state
       */
      byte = 0x02; /* default reset value for INT_MSK_REG */
      if (i2c_read(0x2d, 0x51, 1, &byte, 1) != 0)
         puts("Error reading the chip.\n");
      byte |= 0x10; /*PWRHOLD_IT_MASK*/
      if (i2c_write(0x2d, 0x51, 1, &byte, 1) != 0)
         puts("Error writing the chip IT mask.\n");

      /* Initialize the PMIC to desired state */
      /* 1. Set Vmmc to 3.0V */
      byte = 0x9;
      if (i2c_write(0x2d, 0x35, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */
      /* 2. Set Vaux33 to 2.0V */
      byte = 0x5;
      if (i2c_write(0x2d, 0x34, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */
      /* 3. Set Vdd3 to 5.0V */
      byte = 0x5;
      if (i2c_write(0x2d, 0x27, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      /* 4. Set Vaux1 to 2.85V */
      byte = 0xD;
      if (i2c_write(0x2d, 0x32, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */
      /* 5. Set Vaux2 to 3.0V */
      byte = 0x9;
      if (i2c_write(0x2d, 0x33, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */
      /* 6. Set Vpll to 1.8V */
      byte = 0x9;
      if (i2c_write(0x2d, 0x36, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */
      /* 7. Set Vdig1 to 1.8V */
      byte = 0x9;
      if (i2c_write(0x2d, 0x30, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */
      /* 8. Set Vdig2 to 1.8V */
      byte = 0xd;
      if (i2c_write(0x2d, 0x31, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */
      /* 9. Set Vdac to 2.85V */
      byte = 0xD;
      if (i2c_write(0x2d, 0x37, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */

      /* 10. Enable SR and DEV_ON from the control interface*/
      byte = 0x54;
      if (i2c_write(0x2d, 0x3f, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */

      /* 11. Set Vdd1 to 1.36V to allow MPU to 1Ghz*/
      byte = 0x3f;
      if (i2c_write(0x2d, 0x22, 1, &byte, 1) != 0)
         puts("Error writing the chip.\n");
      udelay(11000); /* wait ~10ms for the write to complete */

      /* power up gpio_129 (and other) */
      writel(0x40, CONTROL_WKUP_CTRL);

      /* Setup PBIAS_LITE properly even during NAND boot so that GPIO 129 is fully functional */
      writel(readl(CONTROL_PBIAS_LITE) | PBIASLITESUPPLYHIGH1 |PBIASLITEPWRDNZ1, CONTROL_PBIAS_LITE);


12. misc_init_r also calls idme_init(flash_dev) (board\ti\lab126\evm.c). idem_init (common\cmd_idme.c) calls idme_init_emmc (common\cmd_idme_emmc.c) which calls load_idme_line_data(var_buf, IDME_BOOT_FILE_NAME, IDME_PARTITION_NAME)  (common\cmd_idme_emmc.c)
Quote
76 bytes read in 6 ms (11.7 KiB/s)
   
13. misc_init_r then calls initialize_leds(get_omap3_board_rev()) (common\cmd_idme.c) calls idme_init_emmc (common\cmd_idme_emmc.c) which calls load_idme_line_data(var_buf, IDME_MFG_FILE_NAME, IDME_PARTITION_NAME)  (common\cmd_idme_emmc.c)
Quote
463 bytes read in 5 ms (89.8 KiB/s)
   
14. misc_init_r then calls initialize_leds (board\ti\lab126\led_control.c) which ultimately calls lp5523_pattern (board\ti\lab126\led_control.c) which calls lp5523_enable_boot_pattern (board\ti\lab126\led_control.c) that calls idme_get_data_store(BOOT_ANIMATION_FILE, varbuf, VARBUF_SIZE)
Quote
824 bytes read in 7 ms (114.3 KiB/s)
Animation Version = 3
   
15. board_late_init (board\ti\lab126\evm.c) is called which calls the following functions:
  • late_muxconf_regs (board\ti\lab126\evm.c) ... links gpt_11_pwm_evt to the Network LED and gpt_8_pwm_evt to the Power LED
  • check_post_mode (board\ti\lab126\evm.c) ... "Run any Power-On-Self-Tests (POST) specified"
  • idme_check_update (common\cmd_idme.c) calls idme_check_update_emmc (common\cmd_idme_emmc.c) which ultimately calls flush_to_file(g_boot_lines, IDME_BOOT_RECOVERY_FILE_NAME, RECOVERY_PARTITION_NAME) and flush_to_file(g_boot_lines, IDME_BOOT_FILE_NAME, IDME_PARTITION_NAME) (common\cmd_idme_emmc.c)
Quote
File System is consistent
file found deleting
update journal finished
File System is consistent
update journal finished
  • setup_board_info (board\ti\lab126\evm.c)  ... loads the PCB serial number and device serial numbers into memory
  • check_boot_mode (board\ti\lab126\evm.c).. calls prepare_eMMC_boot (board\ti\lab126\evm.c) "Setup boot parameters for eMMC device" Notably, the following instructions are present:
    if (mmc_get_dev(0) != 0)
    logical_mmc_dev = 1; // SD card present, prepare to boot from eMMC

    this means we can boot from a SD card if we can figure out which pins they are.
  • mmc_get_dev (drivers\mmc\mmc.c) calls mmc_init which produces this line when a SD card is not found:
Quote
Card did not respond to voltage select!
  • continuing, prepare_eMMC_boot will output:
Quote
Invalid uuid. Booting by block dev
booting ...main-A
[/list]

16. main_loop (common\main.c) is called by start_armboot ... this is wrapped in an infinite loop so it should never return. Several notable (and somewhat visible) things occur in here:
  • the ability to interrupt the boot process is disabled. abortboot (common\main.c) is called but has been configured (in includes\configs\omap3_lab126.h) via CONFIG_BOOTDELAY = 0 to disallow aborting autoboot. The prompt is shown, however:
Quote
*
  • The bootscript (found in includes\configs\omap3_lab126.h) defines the booting behavior from this point on:
         "loadaddr=0x82000000\0" \
         "kernaddr=0x280000\0" \
         "usbtty=cdc_acm\0" \
         "mmcdev=0:1\0" \
         "console=ttyO0,115200n8\0" \
         "bootdevice=nand\0" \
         "config_extra=mem=200M@0x80000000 " \
            "mpurate=1000 quiet " \
            "--default-console none\0" \
         "kernel_file=/boot/uImage\0" \
         "mmc_part=1:6\0" \
          "mount_type=ro\0" \
         "root=/dev/mmcblk0p6\0" \
         "boottype=mmcboot\0" \
         "mmcargs=setenv bootargs console=${console} " \
            "root=${root} ${mount_type} " \
            "rootfstype=ext3 rootwait " \
            "${config_extra}\0"  \
         "mmcboot=echo Booting from mmc ...; " \
            "run mmcargs; " \
            "ext4load mmc ${mmc_part} ${loadaddr} ${kernel_file};" \
            "bootm ${loadaddr}\0" \

  • Resulting in the following output before going into the kernel:
Quote
Booting from mmc ...
2605272 bytes read in 491 ms (5.1 MiB/s)
## Booting kernel from Legacy Image at 82000000 ...
   Image Name:   Linux-2.6.37
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2605208 Bytes = 2.5 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK
[/list]

Its a bummer that the u-boot system's autoboot is locked in. That would have been a fun toy to play with. But there is hope that the JTAG is still operational (according to the evm.h file) and the i2c bus configuration is known. Also, the fact that we can boot from a SD card (if we can figure out where to solder it in!) gives hope that we can root the Echo eventually with minimal hardware modifications.

If anyone has any insights or comments, I would love to hear them.  :)   

For those who are curious, this is the full output I received from the console during the Echo's boot process:

Quote

Texas Instruments X-Loader 1.51 (Mar  6 2015 - 04:24:27)
LAB126 Rev 0
Starting X-loader on mmc-0...failed!
Starting X-loader on mmc-0...failed!
Booting from eMMC . . .
Starting X-loader on mmc-1...Reading boot sector

155568 Bytes Read from MMC
Starting OS Bootloader from MMC...
Starting OS Bootloader...(time = 628 ms)


U-Boot 2010.06-00001-g65e5723 (Jun 22 2015 - 22:05:52)

OMAP34xx/35xx-GP ES2.1, CPU-OPP2 L3-165MHz
OMAP3 LAB126 board + LPDDR/NAND
I2C:   ready
DRAM:  256 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Using default environment

In:    serial
Out:   serial
Err:   serial
OMAP3 Lab126 Rev: 0x1a
Die ID #{removed by me}
76 bytes read in 6 ms (11.7 KiB/s)
463 bytes read in 5 ms (89.8 KiB/s)
824 bytes read in 7 ms (114.3 KiB/s)
Animation Version = 3
File System is consistent
file found deleting
update journal finished
File System is consistent
update journal finished
Card did not respond to voltage select!
Invalid uuid. Booting by block dev
booting ...main-A
*
Booting from mmc ...
2605272 bytes read in 491 ms (5.1 MiB/s)
## Booting kernel from Legacy Image at 82000000 ...
   Image Name:   Linux-2.6.37
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    2605208 Bytes = 2.5 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK
OK

Starting kernel ...

[    0.000000] Trying to install type control for IRQ385
[    0.000000] Trying to set irq flags for IRQ385
[    0.158660] mtdoops: mtd device (mtddev=name/number) must be supplied
[    0.168914] ks8851 spi1.0: failed to read device ID
[    0.205841] codec: aic32xx_i2c_probe : snd_soc_register_codec success
[    0.250244] Power Management for TI OMAP3.
[    0.260070] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
[    2.315979] DSPLINK Module (1.65.01.05_eng) created on Date: Jun 23 2015 Time: 05:09:20
Shared memory /QSpeakerIn.shm deletion failed.

Shared memory /QEarconIn.shm deletion failed.

Shared memory /AudiodCmd.shm deletion failed.

Shared memory /BMicsOut.shm deletion failed.

Shared memory /BPhoneMic.shm deletion failed.

Shared memory /BTraitReport.shm deletion failed.

Shared memory /BAsrMetadata.shm deletion failed.

Shared memory /BRemoteMic.shm deletion failed.

CGRE[824]: Started the CGroup Rules Engine Daemon.
shared memory /QSpeakerIn.shm created successfully. (byte_num=95232.)
shared memory /QEarconIn.shm created successfully. (byte_num=16000.)
shared memory /AudiodCmd.shm created successfully. (byte_num=3000.)
shared memory /BMicsOut.shm created successfully. (msg_size=2, msg_num=1048575.)
shared memory /BPhoneMic.shm created successfully. (msg_size=2, msg_num=16000.)
shared memory /BRemoteMic.shm created successfully. (msg_size=2, msg_num=16000.)
shared memory /BTraitReport.shm created successfully. (msg_size=24, msg_num=128.)
shared memory /BAsrMetadata.shm created successfully. (msg_size=1, msg_num=131072.)
CMEM Shared Sizes: Audio A2D 9612 82836 Aux A2D 240276 1600276

If you ground the reset pin on the testpads at the bottom of the Echo (see opiette's forum for the location of that pin), it will perform a factor reset which will provide additional console output.

Quote
[  240.001007] 20150804:203941 factory-reset: Perform factory reset now
AFE_MSG_SHUTDOWN status=0
To call Engine_close()
CERuntime_exit() Done
devcapd[933]: I devcap:StoppingDevCap::Stopping DevCap
[  242.909362] Restarting system.
« Last Edit: August 06, 2015, 10:06:49 am by gssincla »

Bcmg82

Re: Understanding Echo's U-Boot process
« Reply #1 on: August 06, 2015, 10:18:47 pm »
Amazing!  Thank you for taking the time to post that! Very cool.

dj_skully

Re: Understanding Echo's U-Boot process
« Reply #2 on: September 23, 2015, 08:19:14 pm »
First of all, thank you SO much for the writeup! My research partner and I are tackling analyzing security and privacy concerns of the device. Can you elaborate on how you connected to the pins? What equipment? Which pins? How/when did you get the console read-out? Sorry if these are simple questions, I am fairly new to hardware hacking!

Thanks again,

A fellow hacker