mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 13:11:31 +00:00
Merge tag 'ti-v2020.04-rc2' of https://gitlab.denx.de/u-boot/custodians/u-boot-ti
- DFU boot support for J721e - I2C support for J721e - GPIO support for J721e - Android boot image updates on AM57XX - OMAP watchdog fixes
This commit is contained in:
commit
d861183dc5
39 changed files with 1658 additions and 393 deletions
|
@ -56,7 +56,7 @@ R: Sam Protsenko <joe.skb7@gmail.com>
|
|||
S: Maintained
|
||||
F: cmd/ab_select.c
|
||||
F: common/android_ab.c
|
||||
F: doc/android/ab.txt
|
||||
F: doc/android/ab.rst
|
||||
F: include/android_ab.h
|
||||
F: test/py/tests/test_android/test_ab.py
|
||||
|
||||
|
@ -65,7 +65,7 @@ M: Igor Opaniuk <igor.opaniuk@gmail.com>
|
|||
S: Maintained
|
||||
F: cmd/avb.c
|
||||
F: common/avb_verify.c
|
||||
F: doc/android/avb2.txt
|
||||
F: doc/android/avb2.rst
|
||||
F: include/avb_verify.h
|
||||
F: lib/libavb/
|
||||
F: test/py/tests/test_android/test_avb.py
|
||||
|
|
|
@ -337,3 +337,15 @@
|
|||
&wkup_i2c0 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&main_i2c0 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&main_i2c0_pins_default {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&exp2 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
|
|
@ -107,6 +107,13 @@
|
|||
J721E_IOPAD(0x214, PIN_OUTPUT, 4) /* (V4) MCAN1_TX.USB1_DRVVBUS */
|
||||
>;
|
||||
};
|
||||
|
||||
main_i2c0_pins_default: main-i2c0-pins-default {
|
||||
pinctrl-single,pins = <
|
||||
J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */
|
||||
J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&wkup_pmx0 {
|
||||
|
@ -145,3 +152,23 @@
|
|||
pinctrl-0 = <&wkup_i2c0_pins_default>;
|
||||
clock-frequency = <400000>;
|
||||
};
|
||||
|
||||
&main_i2c0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&main_i2c0_pins_default>;
|
||||
clock-frequency = <400000>;
|
||||
|
||||
exp1: gpio@20 {
|
||||
compatible = "ti,tca6416";
|
||||
reg = <0x20>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
exp2: gpio@22 {
|
||||
compatible = "ti,tca6424";
|
||||
reg = <0x22>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -200,6 +200,28 @@
|
|||
clock-names = "fclk";
|
||||
};
|
||||
|
||||
main_gpio0: gpio@600000 {
|
||||
compatible = "ti,j721e-gpio", "ti,keystone-gpio";
|
||||
reg = <0x0 0x00600000 0x0 0x100>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
interrupts = <105 0 IRQ_TYPE_EDGE_RISING>,
|
||||
<105 1 IRQ_TYPE_EDGE_RISING>,
|
||||
<105 2 IRQ_TYPE_EDGE_RISING>,
|
||||
<105 3 IRQ_TYPE_EDGE_RISING>,
|
||||
<105 4 IRQ_TYPE_EDGE_RISING>,
|
||||
<105 5 IRQ_TYPE_EDGE_RISING>,
|
||||
<105 6 IRQ_TYPE_EDGE_RISING>,
|
||||
<105 7 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-controller;
|
||||
#interrupt-cells = <2>;
|
||||
ti,ngpio = <128>;
|
||||
ti,davinci-gpio-unbanked = <0>;
|
||||
power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
|
||||
clocks = <&k3_clks 105 0>;
|
||||
clock-names = "gpio";
|
||||
};
|
||||
|
||||
main_sdhci0: sdhci@4f80000 {
|
||||
compatible = "ti,j721e-sdhci-8bit";
|
||||
reg = <0x0 0x4f80000 0x0 0x1000>, <0x0 0x4f88000 0x0 0x400>;
|
||||
|
@ -433,4 +455,81 @@
|
|||
dma-coherent;
|
||||
};
|
||||
};
|
||||
|
||||
main_i2c0: i2c@2000000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2000000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 187 0>;
|
||||
power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
|
||||
main_i2c1: i2c@2010000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2010000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 188 0>;
|
||||
power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
|
||||
main_i2c2: i2c@2020000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2020000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 189 0>;
|
||||
power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
|
||||
main_i2c3: i2c@2030000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2030000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 190 0>;
|
||||
power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
|
||||
main_i2c4: i2c@2040000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2040000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 191 0>;
|
||||
power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
|
||||
main_i2c5: i2c@2050000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2050000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 192 0>;
|
||||
power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
|
||||
main_i2c6: i2c@2060000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x2060000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 193 0>;
|
||||
power-domains = <&k3_pds 193 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -144,4 +144,26 @@
|
|||
assigned-clock-rates = <250000000>;
|
||||
};
|
||||
};
|
||||
|
||||
mcu_i2c0: i2c@40b00000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x40b00000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 852 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 194 0>;
|
||||
power-domains = <&k3_pds 194 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
|
||||
mcu_i2c1: i2c@40b10000 {
|
||||
compatible = "ti,j721e-i2c", "ti,omap4-i2c";
|
||||
reg = <0x0 0x40b10000 0x0 0x100>;
|
||||
interrupts = <GIC_SPI 853 IRQ_TYPE_LEVEL_HIGH>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
clock-names = "fck";
|
||||
clocks = <&k3_clks 195 0>;
|
||||
power-domains = <&k3_pds 195 TI_SCI_PD_EXCLUSIVE>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -40,6 +40,13 @@
|
|||
clock-frequency = <200000000>;
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
clk_19_2mhz: dummy_clock {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <19200000>;
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
};
|
||||
|
||||
&cbass_mcu_wakeup {
|
||||
|
@ -133,6 +140,13 @@
|
|||
J721E_IOPAD(0x25c, PIN_INPUT, 0) /* (R28) MMC1_SDWP */
|
||||
>;
|
||||
};
|
||||
|
||||
main_i2c0_pins_default: main-i2c0-pins-default {
|
||||
pinctrl-single,pins = <
|
||||
J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */
|
||||
J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&wkup_uart0 {
|
||||
|
@ -207,4 +221,35 @@
|
|||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&usbss0 {
|
||||
/delete-property/ power-domains;
|
||||
/delete-property/ assigned-clocks;
|
||||
/delete-property/ assigned-clock-parents;
|
||||
clocks = <&clk_19_2mhz>;
|
||||
clock-names = "usb2_refclk";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&main_usbss0_pins_default>;
|
||||
ti,vbus-divider;
|
||||
};
|
||||
|
||||
&main_i2c0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&main_i2c0_pins_default>;
|
||||
clock-frequency = <400000>;
|
||||
|
||||
exp1: gpio@20 {
|
||||
compatible = "ti,tca6416";
|
||||
reg = <0x20>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
exp2: gpio@22 {
|
||||
compatible = "ti,tca6424";
|
||||
reg = <0x22>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
||||
#include "k3-j721e-common-proc-board-u-boot.dtsi"
|
||||
|
|
|
@ -30,6 +30,16 @@
|
|||
serial9 = &main_uart7;
|
||||
serial10 = &main_uart8;
|
||||
serial11 = &main_uart9;
|
||||
i2c0 = &wkup_i2c0;
|
||||
i2c1 = &mcu_i2c0;
|
||||
i2c2 = &mcu_i2c1;
|
||||
i2c3 = &main_i2c0;
|
||||
i2c4 = &main_i2c1;
|
||||
i2c5 = &main_i2c2;
|
||||
i2c6 = &main_i2c3;
|
||||
i2c7 = &main_i2c4;
|
||||
i2c8 = &main_i2c5;
|
||||
i2c9 = &main_i2c6;
|
||||
};
|
||||
|
||||
chosen { };
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
/* With BootMode B = 1 */
|
||||
#define BOOT_DEVICE_MMC2 0x10
|
||||
#define BOOT_DEVICE_MMC1 0x11
|
||||
#define BOOT_DEVICE_USB 0x12
|
||||
#define BOOT_DEVICE_DFU 0x12
|
||||
#define BOOT_DEVICE_UFS 0x13
|
||||
#define BOOT_DEVIE_GPMC 0x14
|
||||
#define BOOT_DEVICE_PCIE 0x15
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
#include <malloc.h>
|
||||
#include <remoteproc.h>
|
||||
#include <linux/soc/ti/ti_sci_protocol.h>
|
||||
#include <g_dnl.h>
|
||||
#include <usb.h>
|
||||
#include <dfu.h>
|
||||
|
||||
#include <asm/arch/sys_proto.h>
|
||||
#include "common.h"
|
||||
|
||||
|
@ -172,6 +176,27 @@ static void k3_sysfw_configure_using_fit(void *fit,
|
|||
ret);
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(DFU)
|
||||
static int k3_sysfw_dfu_download(void *addr)
|
||||
{
|
||||
char dfu_str[50];
|
||||
int ret;
|
||||
|
||||
sprintf(dfu_str, "sysfw.itb ram 0x%p 0x%x", addr,
|
||||
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
|
||||
ret = dfu_config_entities(dfu_str, "ram", "0");
|
||||
if (ret) {
|
||||
dfu_free_entities();
|
||||
goto exit;
|
||||
}
|
||||
|
||||
run_usb_dnl_gadget(0, "usb_dnl_dfu");
|
||||
exit:
|
||||
dfu_free_entities();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void k3_sysfw_loader(void (*config_pm_done_callback)(void))
|
||||
{
|
||||
struct spl_image_info spl_image = { 0 };
|
||||
|
@ -235,6 +260,11 @@ void k3_sysfw_loader(void (*config_pm_done_callback)(void))
|
|||
#endif
|
||||
ret = spl_ymodem_load_image(&spl_image, &bootdev);
|
||||
break;
|
||||
#endif
|
||||
#if CONFIG_IS_ENABLED(DFU)
|
||||
case BOOT_DEVICE_DFU:
|
||||
ret = k3_sysfw_dfu_download(sysfw_load_address);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
panic("Loading SYSFW image from device %u not supported!\n",
|
||||
|
|
12
cmd/Kconfig
12
cmd/Kconfig
|
@ -386,6 +386,16 @@ config CMD_ADTIMG
|
|||
files should be merged in one dtb further, which needs to be passed to
|
||||
the kernel, as part of a boot process.
|
||||
|
||||
config CMD_ABOOTIMG
|
||||
bool "abootimg"
|
||||
depends on ANDROID_BOOT_IMAGE
|
||||
help
|
||||
Android Boot Image manipulation commands. Allows one to extract
|
||||
images contained in boot.img, like kernel, ramdisk, dtb, etc, and
|
||||
obtain corresponding meta-information from boot.img.
|
||||
|
||||
See doc/android/boot-image.rst for details.
|
||||
|
||||
config CMD_ELF
|
||||
bool "bootelf, bootvx"
|
||||
default y
|
||||
|
@ -870,7 +880,7 @@ config CMD_FASTBOOT
|
|||
Android devices. Fastboot requires either the network stack
|
||||
enabled or support for acting as a USB device.
|
||||
|
||||
See doc/android/fastboot.txt for more information.
|
||||
See doc/android/fastboot.rst for more information.
|
||||
|
||||
config CMD_FLASH
|
||||
bool "flinfo, erase, protect"
|
||||
|
|
|
@ -48,6 +48,7 @@ ifdef CONFIG_POST
|
|||
obj-$(CONFIG_CMD_DIAG) += diag.o
|
||||
endif
|
||||
obj-$(CONFIG_CMD_ADTIMG) += adtimg.o
|
||||
obj-$(CONFIG_CMD_ABOOTIMG) += abootimg.o
|
||||
obj-$(CONFIG_CMD_ECHO) += echo.o
|
||||
obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o
|
||||
obj-$(CONFIG_CMD_EEPROM) += eeprom.o
|
||||
|
|
258
cmd/abootimg.c
Normal file
258
cmd/abootimg.c
Normal file
|
@ -0,0 +1,258 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2020
|
||||
* Sam Protsenko <joe.skb7@gmail.com>
|
||||
*/
|
||||
|
||||
#include <android_image.h>
|
||||
#include <common.h>
|
||||
#include <mapmem.h>
|
||||
|
||||
#define abootimg_addr() \
|
||||
(_abootimg_addr == -1 ? image_load_addr : _abootimg_addr)
|
||||
|
||||
/* Please use abootimg_addr() macro to obtain the boot image address */
|
||||
static ulong _abootimg_addr = -1;
|
||||
|
||||
static int abootimg_get_ver(int argc, char * const argv[])
|
||||
{
|
||||
const struct andr_img_hdr *hdr;
|
||||
int res = CMD_RET_SUCCESS;
|
||||
|
||||
if (argc > 1)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
|
||||
if (android_image_check_header(hdr)) {
|
||||
printf("Error: Boot Image header is incorrect\n");
|
||||
res = CMD_RET_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (argc == 0)
|
||||
printf("%u\n", hdr->header_version);
|
||||
else
|
||||
env_set_ulong(argv[0], hdr->header_version);
|
||||
|
||||
exit:
|
||||
unmap_sysmem(hdr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int abootimg_get_recovery_dtbo(int argc, char * const argv[])
|
||||
{
|
||||
ulong addr;
|
||||
u32 size;
|
||||
|
||||
if (argc > 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if (!android_image_get_dtbo(abootimg_addr(), &addr, &size))
|
||||
return CMD_RET_FAILURE;
|
||||
|
||||
if (argc == 0) {
|
||||
printf("%lx\n", addr);
|
||||
} else {
|
||||
env_set_hex(argv[0], addr);
|
||||
if (argc == 2)
|
||||
env_set_hex(argv[1], size);
|
||||
}
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static int abootimg_get_dtb_load_addr(int argc, char * const argv[])
|
||||
{
|
||||
const struct andr_img_hdr *hdr;
|
||||
int res = CMD_RET_SUCCESS;
|
||||
|
||||
if (argc > 1)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
|
||||
if (android_image_check_header(hdr)) {
|
||||
printf("Error: Boot Image header is incorrect\n");
|
||||
res = CMD_RET_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hdr->header_version < 2) {
|
||||
printf("Error: header_version must be >= 2 for this\n");
|
||||
res = CMD_RET_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (argc == 0)
|
||||
printf("%lx\n", (ulong)hdr->dtb_addr);
|
||||
else
|
||||
env_set_hex(argv[0], (ulong)hdr->dtb_addr);
|
||||
|
||||
exit:
|
||||
unmap_sysmem(hdr);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int abootimg_get_dtb_by_index(int argc, char * const argv[])
|
||||
{
|
||||
const char *index_str;
|
||||
u32 num;
|
||||
char *endp;
|
||||
ulong addr;
|
||||
u32 size;
|
||||
|
||||
if (argc < 1 || argc > 3)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
index_str = argv[0] + strlen("--index=");
|
||||
if (index_str[0] == '\0') {
|
||||
printf("Error: Wrong index num\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
num = simple_strtoul(index_str, &endp, 0);
|
||||
if (*endp != '\0') {
|
||||
printf("Error: Wrong index num\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if (!android_image_get_dtb_by_index(abootimg_addr(), num,
|
||||
&addr, &size)) {
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
printf("%lx\n", addr);
|
||||
} else {
|
||||
if (env_set_hex(argv[1], addr)) {
|
||||
printf("Error: Can't set [addr_var]\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
if (argc == 3) {
|
||||
if (env_set_hex(argv[2], size)) {
|
||||
printf("Error: Can't set [size_var]\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static int abootimg_get_dtb(int argc, char * const argv[])
|
||||
{
|
||||
if (argc < 1)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if (strstr(argv[0], "--index="))
|
||||
return abootimg_get_dtb_by_index(argc, argv);
|
||||
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
static int do_abootimg_addr(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
char *endp;
|
||||
ulong img_addr;
|
||||
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
img_addr = simple_strtoul(argv[1], &endp, 16);
|
||||
if (*endp != '\0') {
|
||||
printf("Error: Wrong image address\n");
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
|
||||
_abootimg_addr = img_addr;
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static int do_abootimg_get(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
const char *param;
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
param = argv[1];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
if (!strcmp(param, "ver"))
|
||||
return abootimg_get_ver(argc, argv);
|
||||
else if (!strcmp(param, "recovery_dtbo"))
|
||||
return abootimg_get_recovery_dtbo(argc, argv);
|
||||
else if (!strcmp(param, "dtb_load_addr"))
|
||||
return abootimg_get_dtb_load_addr(argc, argv);
|
||||
else if (!strcmp(param, "dtb"))
|
||||
return abootimg_get_dtb(argc, argv);
|
||||
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
static int do_abootimg_dump(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
if (!strcmp(argv[1], "dtb")) {
|
||||
if (android_image_print_dtb_contents(abootimg_addr()))
|
||||
return CMD_RET_FAILURE;
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
static cmd_tbl_t cmd_abootimg_sub[] = {
|
||||
U_BOOT_CMD_MKENT(addr, 2, 1, do_abootimg_addr, "", ""),
|
||||
U_BOOT_CMD_MKENT(dump, 2, 1, do_abootimg_dump, "", ""),
|
||||
U_BOOT_CMD_MKENT(get, 5, 1, do_abootimg_get, "", ""),
|
||||
};
|
||||
|
||||
static int do_abootimg(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
cmd_tbl_t *cp;
|
||||
|
||||
cp = find_cmd_tbl(argv[1], cmd_abootimg_sub,
|
||||
ARRAY_SIZE(cmd_abootimg_sub));
|
||||
|
||||
/* Strip off leading 'abootimg' command argument */
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (!cp || argc > cp->maxargs)
|
||||
return CMD_RET_USAGE;
|
||||
if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
|
||||
return CMD_RET_SUCCESS;
|
||||
|
||||
return cp->cmd(cmdtp, flag, argc, argv);
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
abootimg, CONFIG_SYS_MAXARGS, 0, do_abootimg,
|
||||
"manipulate Android Boot Image",
|
||||
"addr <addr>\n"
|
||||
" - set the address in RAM where boot image is located\n"
|
||||
" ($loadaddr is used by default)\n"
|
||||
"abootimg dump dtb\n"
|
||||
" - print info for all DT blobs in DTB area\n"
|
||||
"abootimg get ver [varname]\n"
|
||||
" - get header version\n"
|
||||
"abootimg get recovery_dtbo [addr_var [size_var]]\n"
|
||||
" - get address and size (hex) of recovery DTBO area in the image\n"
|
||||
" [addr_var]: variable name to contain DTBO area address\n"
|
||||
" [size_var]: variable name to contain DTBO area size\n"
|
||||
"abootimg get dtb_load_addr [varname]\n"
|
||||
" - get load address (hex) of DTB, from image header\n"
|
||||
"abootimg get dtb --index=<num> [addr_var [size_var]]\n"
|
||||
" - get address and size (hex) of DT blob in the image by index\n"
|
||||
" <num>: index number of desired DT blob in DTB area\n"
|
||||
" [addr_var]: variable name to contain DT blob address\n"
|
||||
" [size_var]: variable name to contain DT blob size"
|
||||
);
|
|
@ -108,7 +108,7 @@ endif
|
|||
|
||||
obj-y += image.o
|
||||
obj-$(CONFIG_ANDROID_AB) += android_ab.o
|
||||
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
|
||||
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
|
||||
obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
|
||||
obj-$(CONFIG_$(SPL_)MULTI_DTB_FIT) += boot_fit.o common_fit.o
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
#include <common.h>
|
||||
#include <env.h>
|
||||
#include <image.h>
|
||||
#include <image-android-dt.h>
|
||||
#include <android_image.h>
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <mapmem.h>
|
||||
|
||||
#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000
|
||||
|
||||
|
@ -195,6 +197,182 @@ int android_image_get_second(const struct andr_img_hdr *hdr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* android_image_get_dtbo() - Get address and size of recovery DTBO image.
|
||||
* @hdr_addr: Boot image header address
|
||||
* @addr: If not NULL, will contain address of recovery DTBO image
|
||||
* @size: If not NULL, will contain size of recovery DTBO image
|
||||
*
|
||||
* Get the address and size of DTBO image in "Recovery DTBO" area of Android
|
||||
* Boot Image in RAM. The format of this image is Android DTBO (see
|
||||
* corresponding "DTB/DTBO Partitions" AOSP documentation for details). Once
|
||||
* the address is obtained from this function, one can use 'adtimg' U-Boot
|
||||
* command or android_dt_*() functions to extract desired DTBO blob.
|
||||
*
|
||||
* This DTBO (included in boot image) is only needed for non-A/B devices, and it
|
||||
* only can be found in recovery image. On A/B devices we can always rely on
|
||||
* "dtbo" partition. See "Including DTBO in Recovery for Non-A/B Devices" in
|
||||
* AOSP documentation for details.
|
||||
*
|
||||
* Return: true on success or false on error.
|
||||
*/
|
||||
bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size)
|
||||
{
|
||||
const struct andr_img_hdr *hdr;
|
||||
ulong dtbo_img_addr;
|
||||
bool ret = true;
|
||||
|
||||
hdr = map_sysmem(hdr_addr, sizeof(*hdr));
|
||||
if (android_image_check_header(hdr)) {
|
||||
printf("Error: Boot Image header is incorrect\n");
|
||||
ret = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hdr->header_version < 1) {
|
||||
printf("Error: header_version must be >= 1 to get dtbo\n");
|
||||
ret = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hdr->recovery_dtbo_size == 0) {
|
||||
printf("Error: recovery_dtbo_size is 0\n");
|
||||
ret = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Calculate the address of DTB area in boot image */
|
||||
dtbo_img_addr = hdr_addr;
|
||||
dtbo_img_addr += hdr->page_size;
|
||||
dtbo_img_addr += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
dtbo_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
dtbo_img_addr += ALIGN(hdr->second_size, hdr->page_size);
|
||||
|
||||
if (addr)
|
||||
*addr = dtbo_img_addr;
|
||||
if (size)
|
||||
*size = hdr->recovery_dtbo_size;
|
||||
|
||||
exit:
|
||||
unmap_sysmem(hdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* android_image_get_dtb_img_addr() - Get the address of DTB area in boot image.
|
||||
* @hdr_addr: Boot image header address
|
||||
* @addr: Will contain the address of DTB area in boot image
|
||||
*
|
||||
* Return: true on success or false on fail.
|
||||
*/
|
||||
static bool android_image_get_dtb_img_addr(ulong hdr_addr, ulong *addr)
|
||||
{
|
||||
const struct andr_img_hdr *hdr;
|
||||
ulong dtb_img_addr;
|
||||
bool ret = true;
|
||||
|
||||
hdr = map_sysmem(hdr_addr, sizeof(*hdr));
|
||||
if (android_image_check_header(hdr)) {
|
||||
printf("Error: Boot Image header is incorrect\n");
|
||||
ret = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hdr->header_version < 2) {
|
||||
printf("Error: header_version must be >= 2 to get dtb\n");
|
||||
ret = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (hdr->dtb_size == 0) {
|
||||
printf("Error: dtb_size is 0\n");
|
||||
ret = false;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Calculate the address of DTB area in boot image */
|
||||
dtb_img_addr = hdr_addr;
|
||||
dtb_img_addr += hdr->page_size;
|
||||
dtb_img_addr += ALIGN(hdr->kernel_size, hdr->page_size);
|
||||
dtb_img_addr += ALIGN(hdr->ramdisk_size, hdr->page_size);
|
||||
dtb_img_addr += ALIGN(hdr->second_size, hdr->page_size);
|
||||
dtb_img_addr += ALIGN(hdr->recovery_dtbo_size, hdr->page_size);
|
||||
|
||||
*addr = dtb_img_addr;
|
||||
|
||||
exit:
|
||||
unmap_sysmem(hdr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* android_image_get_dtb_by_index() - Get address and size of blob in DTB area.
|
||||
* @hdr_addr: Boot image header address
|
||||
* @index: Index of desired DTB in DTB area (starting from 0)
|
||||
* @addr: If not NULL, will contain address to specified DTB
|
||||
* @size: If not NULL, will contain size of specified DTB
|
||||
*
|
||||
* Get the address and size of DTB blob by its index in DTB area of Android
|
||||
* Boot Image in RAM.
|
||||
*
|
||||
* Return: true on success or false on error.
|
||||
*/
|
||||
bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr,
|
||||
u32 *size)
|
||||
{
|
||||
const struct andr_img_hdr *hdr;
|
||||
bool res;
|
||||
ulong dtb_img_addr; /* address of DTB part in boot image */
|
||||
u32 dtb_img_size; /* size of DTB payload in boot image */
|
||||
ulong dtb_addr; /* address of DTB blob with specified index */
|
||||
u32 i; /* index iterator */
|
||||
|
||||
res = android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
/* Check if DTB area of boot image is in DTBO format */
|
||||
if (android_dt_check_header(dtb_img_addr)) {
|
||||
return android_dt_get_fdt_by_index(dtb_img_addr, index, addr,
|
||||
size);
|
||||
}
|
||||
|
||||
/* Find out the address of DTB with specified index in concat blobs */
|
||||
hdr = map_sysmem(hdr_addr, sizeof(*hdr));
|
||||
dtb_img_size = hdr->dtb_size;
|
||||
unmap_sysmem(hdr);
|
||||
i = 0;
|
||||
dtb_addr = dtb_img_addr;
|
||||
while (dtb_addr < dtb_img_addr + dtb_img_size) {
|
||||
const struct fdt_header *fdt;
|
||||
u32 dtb_size;
|
||||
|
||||
fdt = map_sysmem(dtb_addr, sizeof(*fdt));
|
||||
if (fdt_check_header(fdt) != 0) {
|
||||
unmap_sysmem(fdt);
|
||||
printf("Error: Invalid FDT header for index %u\n", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
dtb_size = fdt_totalsize(fdt);
|
||||
unmap_sysmem(fdt);
|
||||
|
||||
if (i == index) {
|
||||
if (size)
|
||||
*size = dtb_size;
|
||||
if (addr)
|
||||
*addr = dtb_addr;
|
||||
return true;
|
||||
}
|
||||
|
||||
dtb_addr += dtb_size;
|
||||
++i;
|
||||
}
|
||||
|
||||
printf("Error: Index is out of bounds (%u/%u)\n", index, i);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
/**
|
||||
* android_print_contents - prints out the contents of the Android format image
|
||||
|
@ -246,4 +424,108 @@ void android_print_contents(const struct andr_img_hdr *hdr)
|
|||
printf("%sdtb addr: %llx\n", p, hdr->dtb_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* android_image_print_dtb_info - Print info for one DTB blob in DTB area.
|
||||
* @fdt: DTB header
|
||||
* @index: Number of DTB blob in DTB area.
|
||||
*
|
||||
* Return: true on success or false on error.
|
||||
*/
|
||||
static bool android_image_print_dtb_info(const struct fdt_header *fdt,
|
||||
u32 index)
|
||||
{
|
||||
int root_node_off;
|
||||
u32 fdt_size;
|
||||
const char *model;
|
||||
const char *compatible;
|
||||
|
||||
root_node_off = fdt_path_offset(fdt, "/");
|
||||
if (root_node_off < 0) {
|
||||
printf("Error: Root node not found\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
fdt_size = fdt_totalsize(fdt);
|
||||
compatible = fdt_getprop(fdt, root_node_off, "compatible",
|
||||
NULL);
|
||||
model = fdt_getprop(fdt, root_node_off, "model", NULL);
|
||||
|
||||
printf(" - DTB #%u:\n", index);
|
||||
printf(" (DTB)size = %d\n", fdt_size);
|
||||
printf(" (DTB)model = %s\n", model ? model : "(unknown)");
|
||||
printf(" (DTB)compatible = %s\n",
|
||||
compatible ? compatible : "(unknown)");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* android_image_print_dtb_contents() - Print info for DTB blobs in DTB area.
|
||||
* @hdr_addr: Boot image header address
|
||||
*
|
||||
* DTB payload in Android Boot Image v2+ can be in one of following formats:
|
||||
* 1. Concatenated DTB blobs
|
||||
* 2. Android DTBO format (see CONFIG_CMD_ADTIMG for details)
|
||||
*
|
||||
* This function does next:
|
||||
* 1. Prints out the format used in DTB area
|
||||
* 2. Iterates over all DTB blobs in DTB area and prints out the info for
|
||||
* each blob.
|
||||
*
|
||||
* Return: true on success or false on error.
|
||||
*/
|
||||
bool android_image_print_dtb_contents(ulong hdr_addr)
|
||||
{
|
||||
const struct andr_img_hdr *hdr;
|
||||
bool res;
|
||||
ulong dtb_img_addr; /* address of DTB part in boot image */
|
||||
u32 dtb_img_size; /* size of DTB payload in boot image */
|
||||
ulong dtb_addr; /* address of DTB blob with specified index */
|
||||
u32 i; /* index iterator */
|
||||
|
||||
res = android_image_get_dtb_img_addr(hdr_addr, &dtb_img_addr);
|
||||
if (!res)
|
||||
return false;
|
||||
|
||||
/* Check if DTB area of boot image is in DTBO format */
|
||||
if (android_dt_check_header(dtb_img_addr)) {
|
||||
printf("## DTB area contents (DTBO format):\n");
|
||||
android_dt_print_contents(dtb_img_addr);
|
||||
return true;
|
||||
}
|
||||
|
||||
printf("## DTB area contents (concat format):\n");
|
||||
|
||||
/* Iterate over concatenated DTB blobs */
|
||||
hdr = map_sysmem(hdr_addr, sizeof(*hdr));
|
||||
dtb_img_size = hdr->dtb_size;
|
||||
unmap_sysmem(hdr);
|
||||
i = 0;
|
||||
dtb_addr = dtb_img_addr;
|
||||
while (dtb_addr < dtb_img_addr + dtb_img_size) {
|
||||
const struct fdt_header *fdt;
|
||||
u32 dtb_size;
|
||||
|
||||
fdt = map_sysmem(dtb_addr, sizeof(*fdt));
|
||||
if (fdt_check_header(fdt) != 0) {
|
||||
unmap_sysmem(fdt);
|
||||
printf("Error: Invalid FDT header for index %u\n", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = android_image_print_dtb_info(fdt, i);
|
||||
if (!res) {
|
||||
unmap_sysmem(fdt);
|
||||
return false;
|
||||
}
|
||||
|
||||
dtb_size = fdt_totalsize(fdt);
|
||||
unmap_sysmem(fdt);
|
||||
dtb_addr += dtb_size;
|
||||
++i;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,8 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
|
|||
# CONFIG_MISC_INIT_R is not set
|
||||
CONFIG_VERSION_VARIABLE=y
|
||||
CONFIG_BOARD_EARLY_INIT_F=y
|
||||
CONFIG_AVB_VERIFY=y
|
||||
CONFIG_ANDROID_AB=y
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SPL_DMA=y
|
||||
|
@ -31,11 +33,14 @@ CONFIG_SPL_SPI_LOAD=y
|
|||
CONFIG_SYS_SPI_U_BOOT_OFFS=0x40000
|
||||
CONFIG_SPL_YMODEM_SUPPORT=y
|
||||
CONFIG_CMD_ADTIMG=y
|
||||
CONFIG_CMD_ABOOTIMG=y
|
||||
CONFIG_CMD_SPL=y
|
||||
CONFIG_CMD_BCB=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
CONFIG_CMD_AB_SELECT=y
|
||||
# CONFIG_CMD_PMIC is not set
|
||||
CONFIG_CMD_AVB=y
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="am572x-idk"
|
||||
|
@ -102,3 +107,4 @@ CONFIG_USB_GADGET=y
|
|||
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
|
||||
CONFIG_LIBAVB=y
|
||||
|
|
|
@ -27,6 +27,8 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
|
|||
# CONFIG_MISC_INIT_R is not set
|
||||
CONFIG_VERSION_VARIABLE=y
|
||||
CONFIG_BOARD_EARLY_INIT_F=y
|
||||
CONFIG_AVB_VERIFY=y
|
||||
CONFIG_ANDROID_AB=y
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SPL_DMA=y
|
||||
|
@ -34,10 +36,13 @@ CONFIG_SPL_DMA=y
|
|||
CONFIG_SPL_SPI_LOAD=y
|
||||
CONFIG_SYS_SPI_U_BOOT_OFFS=0x40000
|
||||
CONFIG_CMD_ADTIMG=y
|
||||
CONFIG_CMD_ABOOTIMG=y
|
||||
CONFIG_CMD_BCB=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
CONFIG_CMD_AB_SELECT=y
|
||||
# CONFIG_CMD_PMIC is not set
|
||||
CONFIG_CMD_AVB=y
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="am57xx-beagle-x15"
|
||||
|
@ -98,3 +103,4 @@ CONFIG_USB_GADGET=y
|
|||
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
|
||||
CONFIG_LIBAVB=y
|
||||
|
|
|
@ -28,6 +28,8 @@ CONFIG_SYS_CONSOLE_INFO_QUIET=y
|
|||
# CONFIG_MISC_INIT_R is not set
|
||||
CONFIG_VERSION_VARIABLE=y
|
||||
CONFIG_BOARD_EARLY_INIT_F=y
|
||||
CONFIG_AVB_VERIFY=y
|
||||
CONFIG_ANDROID_AB=y
|
||||
CONFIG_SPL_SYS_MALLOC_SIMPLE=y
|
||||
CONFIG_SPL_SEPARATE_BSS=y
|
||||
CONFIG_SPL_DMA=y
|
||||
|
@ -39,10 +41,13 @@ CONFIG_SPL_USB_GADGET=y
|
|||
CONFIG_SPL_DFU=y
|
||||
CONFIG_SPL_YMODEM_SUPPORT=y
|
||||
CONFIG_CMD_ADTIMG=y
|
||||
CONFIG_CMD_ABOOTIMG=y
|
||||
CONFIG_CMD_BCB=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
CONFIG_CMD_AB_SELECT=y
|
||||
# CONFIG_CMD_PMIC is not set
|
||||
CONFIG_CMD_AVB=y
|
||||
CONFIG_OF_CONTROL=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="am57xx-beagle-x15"
|
||||
|
@ -105,3 +110,4 @@ CONFIG_USB_GADGET=y
|
|||
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0xd022
|
||||
CONFIG_LIBAVB=y
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
CONFIG_ARM=y
|
||||
CONFIG_ARCH_K3=y
|
||||
CONFIG_SPL_GPIO_SUPPORT=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x8000
|
||||
|
@ -32,13 +33,18 @@ CONFIG_SPL_DM_MAILBOX=y
|
|||
CONFIG_SPL_DM_RESET=y
|
||||
CONFIG_SPL_POWER_SUPPORT=y
|
||||
CONFIG_SPL_POWER_DOMAIN=y
|
||||
CONFIG_SPL_RAM_SUPPORT=y
|
||||
CONFIG_SPL_RAM_DEVICE=y
|
||||
CONFIG_SPL_SPI_LOAD=y
|
||||
CONFIG_SYS_SPI_U_BOOT_OFFS=0x280000
|
||||
CONFIG_SPL_USB_GADGET=y
|
||||
CONFIG_SPL_DFU=y
|
||||
CONFIG_SPL_YMODEM_SUPPORT=y
|
||||
CONFIG_CMD_ASKENV=y
|
||||
CONFIG_CMD_DFU=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_GPIO=y
|
||||
CONFIG_CMD_I2C=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_MTD=y
|
||||
|
@ -60,7 +66,7 @@ CONFIG_SPL_MULTI_DTB_FIT=y
|
|||
CONFIG_SPL_MULTI_DTB_FIT_NO_COMPRESSION=y
|
||||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
|
||||
CONFIG_ENV_OFFSET_REDUND=0x700000
|
||||
CONFIG_ENV_OFFSET_REDUND=0x6A0000
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_DM=y
|
||||
|
@ -85,6 +91,9 @@ CONFIG_FASTBOOT_FLASH=y
|
|||
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
|
||||
CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
|
||||
CONFIG_TI_SCI_PROTOCOL=y
|
||||
CONFIG_DM_GPIO=y
|
||||
CONFIG_DA8XX_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_OMAP24XX=y
|
||||
CONFIG_DM_MAILBOX=y
|
||||
|
@ -117,6 +126,7 @@ CONFIG_PINCTRL_SINGLE=y
|
|||
CONFIG_POWER_DOMAIN=y
|
||||
CONFIG_TI_SCI_POWER_DOMAIN=y
|
||||
CONFIG_RAM=y
|
||||
CONFIG_SPL_RAM=y
|
||||
CONFIG_REMOTEPROC_TI_K3_DSP=y
|
||||
CONFIG_REMOTEPROC_TI_K3_R5F=y
|
||||
CONFIG_DM_RESET=y
|
||||
|
@ -139,6 +149,7 @@ CONFIG_USB_XHCI_HCD=y
|
|||
CONFIG_USB_CDNS3=y
|
||||
CONFIG_USB_CDNS3_GADGET=y
|
||||
CONFIG_USB_CDNS3_HOST=y
|
||||
CONFIG_SPL_USB_CDNS3_GADGET=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
|
||||
|
|
|
@ -3,7 +3,7 @@ CONFIG_ARCH_K3=y
|
|||
CONFIG_SPL_GPIO_SUPPORT=y
|
||||
CONFIG_SPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_SPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x55000
|
||||
CONFIG_SYS_MALLOC_F_LEN=0x70000
|
||||
CONFIG_SOC_K3_J721E=y
|
||||
CONFIG_TARGET_J721E_R5_EVM=y
|
||||
CONFIG_ENV_SIZE=0x20000
|
||||
|
@ -36,8 +36,11 @@ CONFIG_SPL_RAM_DEVICE=y
|
|||
CONFIG_SPL_REMOTEPROC=y
|
||||
CONFIG_SPL_SPI_LOAD=y
|
||||
CONFIG_SYS_SPI_U_BOOT_OFFS=0x80000
|
||||
CONFIG_SPL_USB_GADGET=y
|
||||
CONFIG_SPL_DFU=y
|
||||
CONFIG_SPL_YMODEM_SUPPORT=y
|
||||
CONFIG_HUSH_PARSER=y
|
||||
CONFIG_CMD_DFU=y
|
||||
# CONFIG_CMD_FLASH is not set
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_MMC=y
|
||||
|
@ -63,6 +66,7 @@ CONFIG_SPL_CLK=y
|
|||
CONFIG_CLK_TI_SCI=y
|
||||
CONFIG_TI_SCI_PROTOCOL=y
|
||||
CONFIG_DA8XX_GPIO=y
|
||||
CONFIG_DM_PCA953X=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_I2C_SET_DEFAULT_BUS_NUM=y
|
||||
CONFIG_SYS_I2C_OMAP24XX=y
|
||||
|
@ -104,5 +108,17 @@ CONFIG_SYSRESET_TI_SCI=y
|
|||
CONFIG_TIMER=y
|
||||
CONFIG_SPL_TIMER=y
|
||||
CONFIG_OMAP_TIMER=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_DM_USB=y
|
||||
CONFIG_DM_USB_GADGET=y
|
||||
CONFIG_SPL_DM_USB_GADGET=y
|
||||
CONFIG_USB_CDNS3=y
|
||||
CONFIG_USB_CDNS3_GADGET=y
|
||||
CONFIG_SPL_USB_CDNS3_GADGET=y
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
|
||||
CONFIG_USB_GADGET_VENDOR_NUM=0x0451
|
||||
CONFIG_USB_GADGET_PRODUCT_NUM=0x6163
|
||||
CONFIG_USB_GADGET_DOWNLOAD=y
|
||||
CONFIG_FS_EXT4=y
|
||||
CONFIG_FS_FAT_MAX_CLUSTSIZE=16384
|
||||
|
|
|
@ -25,6 +25,7 @@ CONFIG_ANDROID_AB=y
|
|||
CONFIG_CMD_CPU=y
|
||||
CONFIG_CMD_LICENSE=y
|
||||
CONFIG_CMD_BOOTZ=y
|
||||
CONFIG_CMD_ABOOTIMG=y
|
||||
# CONFIG_CMD_ELF is not set
|
||||
CONFIG_CMD_ASKENV=y
|
||||
CONFIG_CMD_GREPENV=y
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Android A/B updates
|
||||
===================
|
||||
|
||||
|
@ -7,41 +9,44 @@ Overview
|
|||
A/B system updates ensures modern approach for system update. This feature
|
||||
allows one to use two sets (or more) of partitions referred to as slots
|
||||
(normally slot A and slot B). The system runs from the current slot while the
|
||||
partitions in the unused slot can be updated [1].
|
||||
partitions in the unused slot can be updated [1]_.
|
||||
|
||||
A/B enablement
|
||||
--------------
|
||||
|
||||
The A/B updates support can be activated by specifying next options in
|
||||
your board configuration file:
|
||||
your board configuration file::
|
||||
|
||||
CONFIG_ANDROID_AB=y
|
||||
CONFIG_CMD_AB_SELECT=y
|
||||
|
||||
The disk space on target device must be partitioned in a way so that each
|
||||
partition which needs to be updated has two or more instances. The name of
|
||||
each instance must be formed by adding suffixes: _a, _b, _c, etc.
|
||||
For example: boot_a, boot_b, system_a, system_b, vendor_a, vendor_b.
|
||||
each instance must be formed by adding suffixes: ``_a``, ``_b``, ``_c``, etc.
|
||||
For example: ``boot_a``, ``boot_b``, ``system_a``, ``system_b``, ``vendor_a``,
|
||||
``vendor_b``.
|
||||
|
||||
As a result you can use 'ab_select' command to ensure A/B boot process in your
|
||||
As a result you can use ``ab_select`` command to ensure A/B boot process in your
|
||||
boot script. This command analyzes and processes A/B metadata stored on a
|
||||
special partition (e.g. "misc") and determines which slot should be used for
|
||||
special partition (e.g. ``misc``) and determines which slot should be used for
|
||||
booting up.
|
||||
|
||||
Command usage
|
||||
-------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
ab_select <slot_var_name> <interface> <dev[:part_number|#part_name]>
|
||||
|
||||
for example:
|
||||
for example::
|
||||
|
||||
=> ab_select slot_name mmc 1:4
|
||||
|
||||
or
|
||||
or::
|
||||
|
||||
=> ab_select slot_name mmc 1#misc
|
||||
|
||||
Result:
|
||||
Result::
|
||||
|
||||
=> printenv slot_name
|
||||
slot_name=a
|
||||
|
@ -49,19 +54,19 @@ Result:
|
|||
Based on this slot information, the current boot partition should be defined,
|
||||
and next kernel command line parameters should be generated:
|
||||
|
||||
- androidboot.slot_suffix=
|
||||
- root=
|
||||
* ``androidboot.slot_suffix=``
|
||||
* ``root=``
|
||||
|
||||
For example:
|
||||
For example::
|
||||
|
||||
androidboot.slot_suffix=_a root=/dev/mmcblk1p12
|
||||
|
||||
A/B metadata is organized according to AOSP reference [2]. On the first system
|
||||
start with A/B enabled, when 'misc' partition doesn't contain required data,
|
||||
the default A/B metadata will be created and written to 'misc' partition.
|
||||
A/B metadata is organized according to AOSP reference [2]_. On the first system
|
||||
start with A/B enabled, when ``misc`` partition doesn't contain required data,
|
||||
the default A/B metadata will be created and written to ``misc`` partition.
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
[1] https://source.android.com/devices/tech/ota/ab
|
||||
[2] bootable/recovery/bootloader_message/include/bootloader_message/bootloader_message.h
|
||||
.. [1] https://source.android.com/devices/tech/ota/ab
|
||||
.. [2] https://android.googlesource.com/platform/bootable/recovery/+/refs/tags/android-10.0.0_r25/bootloader_message/include/bootloader_message/bootloader_message.h
|
133
doc/android/avb2.rst
Normal file
133
doc/android/avb2.rst
Normal file
|
@ -0,0 +1,133 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Android Verified Boot 2.0
|
||||
=========================
|
||||
|
||||
This file contains information about the current support of Android Verified
|
||||
Boot 2.0 in U-Boot.
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Verified Boot establishes a chain of trust from the bootloader to system images:
|
||||
|
||||
* Provides integrity checking for:
|
||||
|
||||
* Android Boot image: Linux kernel + ramdisk. RAW hashing of the whole
|
||||
partition is done and the hash is compared with the one stored in
|
||||
the VBMeta image
|
||||
* ``system``/``vendor`` partitions: verifying root hash of dm-verity hashtrees
|
||||
|
||||
* Provides capabilities for rollback protection
|
||||
|
||||
Integrity of the bootloader (U-Boot BLOB and environment) is out of scope.
|
||||
|
||||
For additional details check [1]_.
|
||||
|
||||
AVB using OP-TEE (optional)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If AVB is configured to use OP-TEE (see `Enable on your board`_) rollback
|
||||
indexes and device lock state are stored in RPMB. The RPMB partition is managed
|
||||
by OP-TEE (see [2]_ for details) which is a secure OS leveraging ARM
|
||||
TrustZone.
|
||||
|
||||
AVB 2.0 U-Boot shell commands
|
||||
-----------------------------
|
||||
|
||||
Provides CLI interface to invoke AVB 2.0 verification + misc. commands for
|
||||
different testing purposes::
|
||||
|
||||
avb init <dev> - initialize avb 2.0 for <dev>
|
||||
avb verify - run verification process using hash data from vbmeta structure
|
||||
avb read_rb <num> - read rollback index at location <num>
|
||||
avb write_rb <num> <rb> - write rollback index <rb> to <num>
|
||||
avb is_unlocked - returns unlock status of the device
|
||||
avb get_uuid <partname> - read and print uuid of partition <partname>
|
||||
avb read_part <partname> <offset> <num> <addr> - read <num> bytes from
|
||||
partition <partname> to buffer <addr>
|
||||
avb write_part <partname> <offset> <num> <addr> - write <num> bytes to
|
||||
<partname> by <offset> using data from <addr>
|
||||
|
||||
Partitions tampering (example)
|
||||
------------------------------
|
||||
|
||||
Boot or system/vendor (dm-verity metadata section) is tampered::
|
||||
|
||||
=> avb init 1
|
||||
=> avb verify
|
||||
avb_slot_verify.c:175: ERROR: boot: Hash of data does not match digest in
|
||||
descriptor.
|
||||
Slot verification result: ERROR_IO
|
||||
|
||||
Vbmeta partition is tampered::
|
||||
|
||||
=> avb init 1
|
||||
=> avb verify
|
||||
avb_vbmeta_image.c:206: ERROR: Hash does not match!
|
||||
avb_slot_verify.c:388: ERROR: vbmeta: Error verifying vbmeta image:
|
||||
HASH_MISMATCH
|
||||
Slot verification result: ERROR_IO
|
||||
|
||||
Enable on your board
|
||||
--------------------
|
||||
|
||||
The following options must be enabled::
|
||||
|
||||
CONFIG_LIBAVB=y
|
||||
CONFIG_AVB_VERIFY=y
|
||||
CONFIG_CMD_AVB=y
|
||||
|
||||
In addtion optionally if storing rollback indexes in RPMB with help of
|
||||
OP-TEE::
|
||||
|
||||
CONFIG_TEE=y
|
||||
CONFIG_OPTEE=y
|
||||
CONFIG_OPTEE_TA_AVB=y
|
||||
CONFIG_SUPPORT_EMMC_RPMB=y
|
||||
|
||||
Then add ``avb verify`` invocation to your android boot sequence of commands,
|
||||
e.g.::
|
||||
|
||||
=> avb_verify=avb init $mmcdev; avb verify;
|
||||
=> if run avb_verify; then \
|
||||
echo AVB verification OK. Continue boot; \
|
||||
set bootargs $bootargs $avb_bootargs; \
|
||||
else \
|
||||
echo AVB verification failed; \
|
||||
exit; \
|
||||
fi; \
|
||||
|
||||
=> emmc_android_boot= \
|
||||
echo Trying to boot Android from eMMC ...; \
|
||||
... \
|
||||
run avb_verify; \
|
||||
mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; \
|
||||
mmc read ${loadaddr} ${boot_start} ${boot_size}; \
|
||||
bootm $loadaddr $loadaddr $fdtaddr; \
|
||||
|
||||
If partitions you want to verify are slotted (have A/B suffixes), then current
|
||||
slot suffix should be passed to ``avb verify`` sub-command, e.g.::
|
||||
|
||||
=> avb verify _a
|
||||
|
||||
To switch on automatic generation of vbmeta partition in AOSP build, add these
|
||||
lines to device configuration mk file::
|
||||
|
||||
BOARD_AVB_ENABLE := true
|
||||
BOARD_AVB_ALGORITHM := SHA512_RSA4096
|
||||
BOARD_BOOTIMAGE_PARTITION_SIZE := <boot partition size>
|
||||
|
||||
After flashing U-Boot don't forget to update environment and write new
|
||||
partition table::
|
||||
|
||||
=> env default -f -a
|
||||
=> setenv partitions $partitions_android
|
||||
=> env save
|
||||
=> gpt write mmc 1 $partitions_android
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [1] https://android.googlesource.com/platform/external/avb/+/master/README.md
|
||||
.. [2] https://www.op-tee.org/
|
|
@ -1,115 +0,0 @@
|
|||
Android Verified Boot 2.0
|
||||
|
||||
This file contains information about the current support of Android Verified
|
||||
Boot 2.0 in U-boot
|
||||
|
||||
1. OVERVIEW
|
||||
---------------------------------
|
||||
Verified Boot establishes a chain of trust from the bootloader to system images
|
||||
* Provides integrity checking for:
|
||||
- Android Boot image: Linux kernel + ramdisk. RAW hashing of the whole
|
||||
partition is done and the hash is compared with the one stored in
|
||||
the VBMeta image
|
||||
- system/vendor partitions: verifying root hash of dm-verity hashtrees.
|
||||
* Provides capabilities for rollback protection.
|
||||
|
||||
Integrity of the bootloader (U-boot BLOB and environment) is out of scope.
|
||||
|
||||
For additional details check:
|
||||
https://android.googlesource.com/platform/external/avb/+/master/README.md
|
||||
|
||||
1.1. AVB using OP-TEE (optional)
|
||||
---------------------------------
|
||||
If AVB is configured to use OP-TEE (see 4. below) rollback indexes and
|
||||
device lock state are stored in RPMB. The RPMB partition is managed by
|
||||
OP-TEE (https://www.op-tee.org/) which is a secure OS leveraging ARM
|
||||
TrustZone.
|
||||
|
||||
|
||||
2. AVB 2.0 U-BOOT SHELL COMMANDS
|
||||
-----------------------------------
|
||||
Provides CLI interface to invoke AVB 2.0 verification + misc. commands for
|
||||
different testing purposes:
|
||||
|
||||
avb init <dev> - initialize avb 2.0 for <dev>
|
||||
avb verify - run verification process using hash data from vbmeta structure
|
||||
avb read_rb <num> - read rollback index at location <num>
|
||||
avb write_rb <num> <rb> - write rollback index <rb> to <num>
|
||||
avb is_unlocked - returns unlock status of the device
|
||||
avb get_uuid <partname> - read and print uuid of partition <partname>
|
||||
avb read_part <partname> <offset> <num> <addr> - read <num> bytes from
|
||||
partition <partname> to buffer <addr>
|
||||
avb write_part <partname> <offset> <num> <addr> - write <num> bytes to
|
||||
<partname> by <offset> using data from <addr>
|
||||
|
||||
|
||||
3. PARTITIONS TAMPERING (EXAMPLE)
|
||||
-----------------------------------
|
||||
Boot or system/vendor (dm-verity metadata section) is tampered:
|
||||
=> avb init 1
|
||||
=> avb verify
|
||||
avb_slot_verify.c:175: ERROR: boot: Hash of data does not match digest in
|
||||
descriptor.
|
||||
Slot verification result: ERROR_IO
|
||||
|
||||
Vbmeta partition is tampered:
|
||||
=> avb init 1
|
||||
=> avb verify
|
||||
avb_vbmeta_image.c:206: ERROR: Hash does not match!
|
||||
avb_slot_verify.c:388: ERROR: vbmeta: Error verifying vbmeta image:
|
||||
HASH_MISMATCH
|
||||
Slot verification result: ERROR_IO
|
||||
|
||||
|
||||
4. ENABLE ON YOUR BOARD
|
||||
-----------------------------------
|
||||
The following options must be enabled:
|
||||
CONFIG_LIBAVB=y
|
||||
CONFIG_AVB_VERIFY=y
|
||||
CONFIG_CMD_AVB=y
|
||||
|
||||
In addtion optionally if storing rollback indexes in RPMB with help of
|
||||
OP-TEE:
|
||||
CONFIG_TEE=y
|
||||
CONFIG_OPTEE=y
|
||||
CONFIG_OPTEE_TA_AVB=y
|
||||
CONFIG_SUPPORT_EMMC_RPMB=y
|
||||
|
||||
Then add `avb verify` invocation to your android boot sequence of commands,
|
||||
e.g.:
|
||||
|
||||
=> avb_verify=avb init $mmcdev; avb verify;
|
||||
=> if run avb_verify; then \
|
||||
echo AVB verification OK. Continue boot; \
|
||||
set bootargs $bootargs $avb_bootargs; \
|
||||
else \
|
||||
echo AVB verification failed; \
|
||||
exit; \
|
||||
fi; \
|
||||
|
||||
=> emmc_android_boot= \
|
||||
echo Trying to boot Android from eMMC ...; \
|
||||
... \
|
||||
run avb_verify; \
|
||||
mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; \
|
||||
mmc read ${loadaddr} ${boot_start} ${boot_size}; \
|
||||
bootm $loadaddr $loadaddr $fdtaddr; \
|
||||
|
||||
If partitions you want to verify are slotted (have A/B suffixes), then current
|
||||
slot suffix should be passed to 'avb verify' sub-command, e.g.:
|
||||
|
||||
=> avb verify _a
|
||||
|
||||
To switch on automatic generation of vbmeta partition in AOSP build, add these
|
||||
lines to device configuration mk file:
|
||||
|
||||
BOARD_AVB_ENABLE := true
|
||||
BOARD_AVB_ALGORITHM := SHA512_RSA4096
|
||||
BOARD_BOOTIMAGE_PARTITION_SIZE := <boot partition size>
|
||||
|
||||
After flashing U-boot don't forget to update environment and write new
|
||||
partition table:
|
||||
=> env default -f -a
|
||||
=> setenv partitions $partitions_android
|
||||
=> env save
|
||||
=> gpt write mmc 1 $partitions_android
|
100
doc/android/bcb.rst
Normal file
100
doc/android/bcb.rst
Normal file
|
@ -0,0 +1,100 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Android Bootloader Control Block (BCB)
|
||||
======================================
|
||||
|
||||
The purpose behind this file is to:
|
||||
|
||||
* give an overview of BCB w/o duplicating public documentation
|
||||
* describe the main BCB use-cases which concern U-Boot
|
||||
* reflect current support status in U-Boot
|
||||
* mention any relevant U-Boot build-time tunables
|
||||
* precisely exemplify one or more use-cases
|
||||
|
||||
Additions and fixes are welcome!
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Bootloader Control Block (BCB) is a well established term/acronym in
|
||||
the Android namespace which refers to a location in a dedicated raw
|
||||
(i.e. FS-unaware) flash (e.g. eMMC) partition, usually called ``misc``,
|
||||
which is used as media for exchanging messages between Android userspace
|
||||
(particularly recovery [1]_) and an Android-capable bootloader.
|
||||
|
||||
On higher level, BCB provides a way to implement a subset of Android
|
||||
Bootloader Requirements [2]_, amongst which are:
|
||||
|
||||
* Android-specific bootloader flow [3]_
|
||||
* Get the "reboot reason" (and act accordingly) [4]_
|
||||
* Get/pass a list of commands from/to recovery [1]_
|
||||
* TODO
|
||||
|
||||
|
||||
'bcb'. Shell command overview
|
||||
-----------------------------
|
||||
|
||||
The ``bcb`` command provides a CLI to facilitate the development of the
|
||||
requirements enumerated above. Below is the command's help message::
|
||||
|
||||
=> bcb
|
||||
bcb - Load/set/clear/test/dump/store Android BCB fields
|
||||
|
||||
Usage:
|
||||
bcb load <dev> <part> - load BCB from mmc <dev>:<part>
|
||||
bcb set <field> <val> - set BCB <field> to <val>
|
||||
bcb clear [<field>] - clear BCB <field> or all fields
|
||||
bcb test <field> <op> <val> - test BCB <field> against <val>
|
||||
bcb dump <field> - dump BCB <field>
|
||||
bcb store - store BCB back to mmc
|
||||
|
||||
Legend:
|
||||
<dev> - MMC device index containing the BCB partition
|
||||
<part> - MMC partition index or name containing the BCB
|
||||
<field> - one of {command,status,recovery,stage,reserved}
|
||||
<op> - the binary operator used in 'bcb test':
|
||||
'=' returns true if <val> matches the string stored in <field>
|
||||
'~' returns true if <val> matches a subset of <field>'s string
|
||||
<val> - string/text provided as input to bcb {set,test}
|
||||
NOTE: any ':' character in <val> will be replaced by line feed
|
||||
during 'bcb set' and used as separator by upper layers
|
||||
|
||||
|
||||
'bcb'. Example of getting reboot reason
|
||||
---------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
if bcb load 1 misc; then
|
||||
# valid BCB found
|
||||
if bcb test command = bootonce-bootloader; then
|
||||
bcb clear command; bcb store;
|
||||
# do the equivalent of AOSP ${fastbootcmd}
|
||||
# i.e. call fastboot
|
||||
else if bcb test command = boot-recovery; then
|
||||
bcb clear command; bcb store;
|
||||
# do the equivalent of AOSP ${recoverycmd}
|
||||
# i.e. do anything required for booting into recovery
|
||||
else
|
||||
# boot Android OS normally
|
||||
fi
|
||||
else
|
||||
# corrupted/non-existent BCB
|
||||
# report error or boot non-Android OS (platform-specific)
|
||||
fi
|
||||
|
||||
|
||||
Enable on your board
|
||||
--------------------
|
||||
|
||||
The following Kconfig options must be enabled::
|
||||
|
||||
CONFIG_PARTITIONS=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_BCB=y
|
||||
|
||||
.. [1] https://android.googlesource.com/platform/bootable/recovery
|
||||
.. [2] https://source.android.com/devices/bootloader
|
||||
.. [3] https://patchwork.ozlabs.org/patch/746835/
|
||||
("[U-Boot,5/6] Initial support for the Android Bootloader flow")
|
||||
.. [4] https://source.android.com/devices/bootloader/boot-reason
|
|
@ -1,89 +0,0 @@
|
|||
Android Bootloader Control Block (BCB)
|
||||
|
||||
The purpose behind this file is to:
|
||||
- give an overview of BCB w/o duplicating public documentation
|
||||
- describe the main BCB use-cases which concern U-Boot
|
||||
- reflect current support status in U-Boot
|
||||
- mention any relevant U-Boot build-time tunables
|
||||
- precisely exemplify one or more use-cases
|
||||
|
||||
Additions and fixes are welcome!
|
||||
|
||||
|
||||
1. OVERVIEW
|
||||
---------------------------------
|
||||
Bootloader Control Block (BCB) is a well established term/acronym in
|
||||
the Android namespace which refers to a location in a dedicated raw
|
||||
(i.e. FS-unaware) flash (e.g. eMMC) partition, usually called "misc",
|
||||
which is used as media for exchanging messages between Android userspace
|
||||
(particularly recovery [1]) and an Android-capable bootloader.
|
||||
|
||||
On higher level, BCB provides a way to implement a subset of Android
|
||||
Bootloader Requirements [2], amongst which are:
|
||||
- Android-specific bootloader flow [3]
|
||||
- Get the "reboot reason" (and act accordingly) [4]
|
||||
- Get/pass a list of commands from/to recovery [1]
|
||||
- TODO
|
||||
|
||||
|
||||
2. 'BCB'. SHELL COMMAND OVERVIEW
|
||||
-----------------------------------
|
||||
The 'bcb' command provides a CLI to facilitate the development of the
|
||||
requirements enumerated above. Below is the command's help message:
|
||||
|
||||
=> bcb
|
||||
bcb - Load/set/clear/test/dump/store Android BCB fields
|
||||
|
||||
Usage:
|
||||
bcb load <dev> <part> - load BCB from mmc <dev>:<part>
|
||||
bcb set <field> <val> - set BCB <field> to <val>
|
||||
bcb clear [<field>] - clear BCB <field> or all fields
|
||||
bcb test <field> <op> <val> - test BCB <field> against <val>
|
||||
bcb dump <field> - dump BCB <field>
|
||||
bcb store - store BCB back to mmc
|
||||
|
||||
Legend:
|
||||
<dev> - MMC device index containing the BCB partition
|
||||
<part> - MMC partition index or name containing the BCB
|
||||
<field> - one of {command,status,recovery,stage,reserved}
|
||||
<op> - the binary operator used in 'bcb test':
|
||||
'=' returns true if <val> matches the string stored in <field>
|
||||
'~' returns true if <val> matches a subset of <field>'s string
|
||||
<val> - string/text provided as input to bcb {set,test}
|
||||
NOTE: any ':' character in <val> will be replaced by line feed
|
||||
during 'bcb set' and used as separator by upper layers
|
||||
|
||||
|
||||
3. 'BCB'. EXAMPLE OF GETTING REBOOT REASON
|
||||
-----------------------------------
|
||||
if bcb load 1 misc; then
|
||||
# valid BCB found
|
||||
if bcb test command = bootonce-bootloader; then
|
||||
bcb clear command; bcb store;
|
||||
# do the equivalent of AOSP ${fastbootcmd}
|
||||
# i.e. call fastboot
|
||||
else if bcb test command = boot-recovery; then
|
||||
bcb clear command; bcb store;
|
||||
# do the equivalent of AOSP ${recoverycmd}
|
||||
# i.e. do anything required for booting into recovery
|
||||
else
|
||||
# boot Android OS normally
|
||||
fi
|
||||
else
|
||||
# corrupted/non-existent BCB
|
||||
# report error or boot non-Android OS (platform-specific)
|
||||
fi
|
||||
|
||||
|
||||
4. ENABLE ON YOUR BOARD
|
||||
-----------------------------------
|
||||
The following Kconfig options must be enabled:
|
||||
CONFIG_PARTITIONS=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_BCB=y
|
||||
|
||||
[1] https://android.googlesource.com/platform/bootable/recovery
|
||||
[2] https://source.android.com/devices/bootloader
|
||||
[3] https://patchwork.ozlabs.org/patch/746835/
|
||||
("[U-Boot,5/6] Initial support for the Android Bootloader flow")
|
||||
[4] https://source.android.com/devices/bootloader/boot-reason
|
154
doc/android/boot-image.rst
Normal file
154
doc/android/boot-image.rst
Normal file
|
@ -0,0 +1,154 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
.. sectionauthor:: Sam Protsenko <joe.skb7@gmail.com>
|
||||
|
||||
Android Boot Image
|
||||
==================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
Android Boot Image is used to boot Android OS. It usually contains kernel image
|
||||
(like ``zImage`` file) and ramdisk. Sometimes it can contain additional
|
||||
binaries. This image is built as a part of AOSP (called ``boot.img``), and being
|
||||
flashed into ``boot`` partition on eMMC. Bootloader then reads that image from
|
||||
``boot`` partition to RAM and boots the kernel from it. Kernel than starts
|
||||
``init`` process from the ramdisk. It should be mentioned that recovery image
|
||||
(``recovery.img``) also has Android Boot Image format.
|
||||
|
||||
Android Boot Image format is described at [1]_. At the moment it can have one of
|
||||
next image headers:
|
||||
|
||||
* v0: it's called *legacy* boot image header; used in devices launched before
|
||||
Android 9; contains kernel image, ramdisk and second stage bootloader
|
||||
(usually unused)
|
||||
* v1: used in devices launched with Android 9; adds ``recovery_dtbo`` field,
|
||||
which should be used for non-A/B devices in ``recovery.img`` (see [2]_ for
|
||||
details)
|
||||
* v2: used in devices launched with Android 10; adds ``dtb`` field, which
|
||||
references payload containing DTB blobs (either concatenated one after the
|
||||
other, or in Android DTBO image format)
|
||||
|
||||
v2, v1 and v0 formats are backward compatible.
|
||||
|
||||
Android Boot Image format is represented by :c:type:`struct andr_img_hdr` in
|
||||
U-Boot, and can be seen in ``include/android_image.h``. U-Boot supports booting
|
||||
Android Boot Image and also has associated command
|
||||
|
||||
Booting
|
||||
-------
|
||||
|
||||
U-Boot is able to boot the Android OS from Android Boot Image using ``bootm``
|
||||
command. In order to use Android Boot Image format support, next option should
|
||||
be enabled::
|
||||
|
||||
CONFIG_ANDROID_BOOT_IMAGE=y
|
||||
|
||||
Then one can use next ``bootm`` command call to run Android:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
=> bootm $loadaddr $loadaddr $fdtaddr
|
||||
|
||||
where ``$loadaddr`` - address in RAM where boot image was loaded; ``$fdtaddr`` -
|
||||
address in RAM where DTB blob was loaded.
|
||||
|
||||
And parameters are, correspondingly:
|
||||
|
||||
1. Where kernel image is located in RAM
|
||||
2. Where ramdisk is located in RAM (can be ``"-"`` if not applicable)
|
||||
3. Where DTB blob is located in RAM
|
||||
|
||||
``bootm`` command will figure out that image located in ``$loadaddr`` has
|
||||
Android Boot Image format, will parse that and boot the kernel from it,
|
||||
providing DTB blob to kernel (from 3rd parameter), passing info about ramdisk to
|
||||
kernel via DTB.
|
||||
|
||||
DTB and DTBO blobs
|
||||
------------------
|
||||
|
||||
``bootm`` command can't just use DTB blob from Android Boot Image (``dtb``
|
||||
field), because:
|
||||
|
||||
* there is no DTB area in Android Boot Image before v2
|
||||
* there may be several DTB blobs in DTB area (e.g. for different SoCs)
|
||||
* some DTBO blobs may have to be merged in DTB blobs before booting
|
||||
(e.g. for different boards)
|
||||
|
||||
So user has to prepare DTB blob manually and provide it in a 3rd parameter
|
||||
of ``bootm`` command. Next commands can be used to do so:
|
||||
|
||||
1. ``abootimg``: manipulates Anroid Boot Image, allows one to extract
|
||||
meta-information and payloads from it
|
||||
2. ``adtimg``: manipulates Android DTB/DTBO image [3]_, allows one to extract
|
||||
DTB/DTBO blobs from it
|
||||
|
||||
In order to use those, please enable next config options::
|
||||
|
||||
CONFIG_CMD_ABOOTIMG=y
|
||||
CONFIG_CMD_ADTIMG=y
|
||||
|
||||
For example, let's assume we have next Android partitions on eMMC:
|
||||
|
||||
* ``boot``: contains Android Boot Image v2 (including DTB blobs)
|
||||
* ``dtbo``: contains DTBO blobs
|
||||
|
||||
Then next command sequence can be used to boot Android:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
=> mmc dev 1
|
||||
|
||||
# Read boot image to RAM (into $loadaddr)
|
||||
=> part start mmc 1 boot boot_start
|
||||
=> part size mmc 1 boot boot_size
|
||||
=> mmc read $loadaddr $boot_start $boot_size
|
||||
|
||||
# Read DTBO image to RAM (into $dtboaddr)
|
||||
=> part start mmc 1 dtbo dtbo_start
|
||||
=> part size mmc 1 dtbo dtbo_size
|
||||
=> mmc read $dtboaddr $dtbo_start $dtbo_size
|
||||
|
||||
# Copy required DTB blob (into $fdtaddr)
|
||||
=> abootimg get dtb --index=0 dtb0_start dtb0_size
|
||||
=> cp.b $dtb0_start $fdtaddr $dtb0_size
|
||||
|
||||
# Merge required DTBO blobs into DTB blob
|
||||
=> fdt addr $fdtaddr 0x100000
|
||||
=> adtimg addr $dtboaddr
|
||||
=> adtimg get dt --index=0 $dtbo0_addr
|
||||
=> fdt apply $dtbo0_addr
|
||||
|
||||
# Boot Android
|
||||
=> bootm $loadaddr $loadaddr $fdtaddr
|
||||
|
||||
This sequence should be used for Android 10 boot. Of course, the whole Android
|
||||
boot procedure includes much more actions, like:
|
||||
|
||||
* obtaining reboot reason from BCB (see [4]_)
|
||||
* implementing recovery boot
|
||||
* implementing fastboot boot
|
||||
* implementing A/B slotting (see [5]_)
|
||||
* implementing AVB2.0 (see [6]_)
|
||||
|
||||
But Android Boot Image booting is the most crucial part in Android boot scheme.
|
||||
|
||||
All Android bootloader requirements documentation is available at [7]_. Some
|
||||
overview on the whole Android 10 boot process can be found at [8]_.
|
||||
|
||||
C API for working with Android Boot Image format
|
||||
------------------------------------------------
|
||||
|
||||
.. kernel-doc:: common/image-android.c
|
||||
:internal:
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [1] https://source.android.com/devices/bootloader/boot-image-header
|
||||
.. [2] https://source.android.com/devices/bootloader/recovery-image
|
||||
.. [3] https://source.android.com/devices/architecture/dto/partitions
|
||||
.. [4] :doc:`bcb`
|
||||
.. [5] :doc:`ab`
|
||||
.. [6] :doc:`avb2`
|
||||
.. [7] https://source.android.com/devices/bootloader
|
||||
.. [8] https://connect.linaro.org/resources/san19/san19-217/
|
|
@ -1,12 +1,13 @@
|
|||
FastBoot Version 0.4
|
||||
----------------------
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
FastBoot Version 0.4
|
||||
====================
|
||||
|
||||
The fastboot protocol is a mechanism for communicating with bootloaders
|
||||
over USB. It is designed to be very straightforward to implement, to
|
||||
allow it to be used across a wide range of devices and from hosts running
|
||||
Linux, Windows, or OSX.
|
||||
|
||||
|
||||
Basic Requirements
|
||||
------------------
|
||||
|
||||
|
@ -66,31 +67,33 @@ Transport and Framing
|
|||
Example Session
|
||||
---------------
|
||||
|
||||
Host: "getvar:version" request version variable
|
||||
.. code-block:: none
|
||||
|
||||
Client: "OKAY0.4" return version "0.4"
|
||||
Host: "getvar:version" request version variable
|
||||
|
||||
Host: "getvar:nonexistant" request some undefined variable
|
||||
Client: "OKAY0.4" return version "0.4"
|
||||
|
||||
Client: "OKAY" return value ""
|
||||
Host: "getvar:nonexistant" request some undefined variable
|
||||
|
||||
Host: "download:00001234" request to send 0x1234 bytes of data
|
||||
Client: "OKAY" return value ""
|
||||
|
||||
Client: "DATA00001234" ready to accept data
|
||||
Host: "download:00001234" request to send 0x1234 bytes of data
|
||||
|
||||
Host: < 0x1234 bytes > send data
|
||||
Client: "DATA00001234" ready to accept data
|
||||
|
||||
Client: "OKAY" success
|
||||
Host: < 0x1234 bytes > send data
|
||||
|
||||
Host: "flash:bootloader" request to flash the data to the bootloader
|
||||
Client: "OKAY" success
|
||||
|
||||
Client: "INFOerasing flash" indicate status / progress
|
||||
"INFOwriting flash"
|
||||
"OKAY" indicate success
|
||||
Host: "flash:bootloader" request to flash the data to the bootloader
|
||||
|
||||
Host: "powerdown" send a command
|
||||
Client: "INFOerasing flash" indicate status / progress
|
||||
"INFOwriting flash"
|
||||
"OKAY" indicate success
|
||||
|
||||
Client: "FAILunknown command" indicate failure
|
||||
Host: "powerdown" send a command
|
||||
|
||||
Client: "FAILunknown command" indicate failure
|
||||
|
||||
|
||||
Command Reference
|
||||
|
@ -105,6 +108,8 @@ Command Reference
|
|||
specification. OEM-specific commands should not begin with a
|
||||
lowercase letter, to prevent incompatibilities with future specs.
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
"getvar:%s" Read a config/version variable from the bootloader.
|
||||
The variable contents will be returned after the
|
||||
OKAY response.
|
||||
|
@ -139,16 +144,14 @@ Command Reference
|
|||
|
||||
"powerdown" Power off the device.
|
||||
|
||||
|
||||
|
||||
Client Variables
|
||||
----------------
|
||||
|
||||
The "getvar:%s" command is used to read client variables which
|
||||
The ``getvar:%s`` command is used to read client variables which
|
||||
represent various information about the device and the software
|
||||
on it.
|
||||
|
||||
The various currently defined names are:
|
||||
The various currently defined names are::
|
||||
|
||||
version Version of FastBoot protocol supported.
|
||||
It should be "0.3" for this document.
|
|
@ -1,12 +1,12 @@
|
|||
================
|
||||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Android Fastboot
|
||||
================
|
||||
|
||||
Overview
|
||||
========
|
||||
--------
|
||||
|
||||
The protocol that is used over USB and UDP is described in
|
||||
``doc/android/fastboot-protocol.txt``.
|
||||
The protocol that is used over USB and UDP is described in [1]_.
|
||||
|
||||
The current implementation supports the following standard commands:
|
||||
|
||||
|
@ -22,25 +22,23 @@ The current implementation supports the following standard commands:
|
|||
|
||||
The following OEM commands are supported (if enabled):
|
||||
|
||||
- oem format - this executes ``gpt write mmc %x $partitions``
|
||||
- ``oem format`` - this executes ``gpt write mmc %x $partitions``
|
||||
|
||||
Support for both eMMC and NAND devices is included.
|
||||
|
||||
Client installation
|
||||
===================
|
||||
-------------------
|
||||
|
||||
The counterpart to this is the fastboot client which can be found in
|
||||
Android's ``platform/system/core`` repository in the fastboot
|
||||
folder. It runs on Windows, Linux and OSX. The fastboot client is
|
||||
part of the Android SDK Platform-Tools and can be downloaded from:
|
||||
|
||||
https://developer.android.com/studio/releases/platform-tools
|
||||
part of the Android SDK Platform-Tools and can be downloaded from [2]_.
|
||||
|
||||
Board specific
|
||||
==============
|
||||
--------------
|
||||
|
||||
USB configuration
|
||||
-----------------
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The fastboot gadget relies on the USB download gadget, so the following
|
||||
options must be configured:
|
||||
|
@ -57,7 +55,7 @@ supported by the fastboot client. The list of vendor IDs supported can
|
|||
be found in the fastboot client source code.
|
||||
|
||||
General configuration
|
||||
---------------------
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The fastboot protocol requires a large memory buffer for
|
||||
downloads. This buffer should be as large as possible for a
|
||||
|
@ -67,46 +65,46 @@ may be overridden on the fastboot command line using ``-l`` and
|
|||
``-s``.
|
||||
|
||||
Fastboot environment variables
|
||||
==============================
|
||||
------------------------------
|
||||
|
||||
Partition aliases
|
||||
-----------------
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Fastboot partition aliases can also be defined for devices where GPT
|
||||
limitations prevent user-friendly partition names such as "boot", "system"
|
||||
and "cache". Or, where the actual partition name doesn't match a standard
|
||||
limitations prevent user-friendly partition names such as ``boot``, ``system``
|
||||
and ``cache``. Or, where the actual partition name doesn't match a standard
|
||||
partition name used commonly with fastboot.
|
||||
|
||||
The current implementation checks aliases when accessing partitions by
|
||||
name (flash_write and erase functions). To define a partition alias
|
||||
add an environment variable similar to:
|
||||
add an environment variable similar to::
|
||||
|
||||
``fastboot_partition_alias_<alias partition name>=<actual partition name>``
|
||||
fastboot_partition_alias_<alias partition name>=<actual partition name>
|
||||
|
||||
for example:
|
||||
for example::
|
||||
|
||||
``fastboot_partition_alias_boot=LNX``
|
||||
fastboot_partition_alias_boot=LNX
|
||||
|
||||
Variable overrides
|
||||
------------------
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Variables retrived through ``getvar`` can be overridden by defining
|
||||
environment variables of the form ``fastboot.<variable>``. These are
|
||||
looked up first so can be used to override values which would
|
||||
otherwise be returned. Using this mechanism you can also return types
|
||||
for NAND filesystems, as the fully parameterised variable is looked
|
||||
up, e.g.
|
||||
up, e.g.::
|
||||
|
||||
``fastboot.partition-type:boot=jffs2``
|
||||
fastboot.partition-type:boot=jffs2
|
||||
|
||||
Boot command
|
||||
------------
|
||||
^^^^^^^^^^^^
|
||||
|
||||
When executing the fastboot ``boot`` command, if ``fastboot_bootcmd`` is set then
|
||||
that will be executed in place of ``bootm <CONFIG_FASTBOOT_BUF_ADDR>``.
|
||||
When executing the fastboot ``boot`` command, if ``fastboot_bootcmd`` is set
|
||||
then that will be executed in place of ``bootm <CONFIG_FASTBOOT_BUF_ADDR>``.
|
||||
|
||||
Partition Names
|
||||
===============
|
||||
---------------
|
||||
|
||||
The Fastboot implementation in U-Boot allows to write images into disk
|
||||
partitions. Target partitions are referred on the host computer by
|
||||
|
@ -115,11 +113,11 @@ their names.
|
|||
For GPT/EFI the respective partition name is used.
|
||||
|
||||
For MBR the partitions are referred by generic names according to the
|
||||
following schema:
|
||||
following schema::
|
||||
|
||||
<device type><device index letter><partition index>
|
||||
<device type><device index letter><partition index>
|
||||
|
||||
Example: ``hda3``, ``sdb1``, ``usbda1``
|
||||
Example: ``hda3``, ``sdb1``, ``usbda1``.
|
||||
|
||||
The device type is as follows:
|
||||
|
||||
|
@ -135,7 +133,7 @@ controller, SD/MMC controller) or disk index. The partition index starts
|
|||
from ``1`` and describes the partition number on the particular device.
|
||||
|
||||
Writing Partition Table
|
||||
=======================
|
||||
-----------------------
|
||||
|
||||
Fastboot also allows to write the partition table to the media. This can be
|
||||
done by writing the respective partition table image to a special target
|
||||
|
@ -148,34 +146,26 @@ configuration options:
|
|||
CONFIG_FASTBOOT_MBR_NAME
|
||||
|
||||
In Action
|
||||
=========
|
||||
---------
|
||||
|
||||
Enter into fastboot by executing the fastboot command in U-Boot for either USB:
|
||||
|
||||
::
|
||||
Enter into fastboot by executing the fastboot command in U-Boot for either USB::
|
||||
|
||||
=> fastboot usb 0
|
||||
|
||||
or UDP:
|
||||
|
||||
::
|
||||
or UDP::
|
||||
|
||||
=> fastboot udp
|
||||
link up on port 0, speed 100, full duplex
|
||||
Using ethernet@4a100000 device
|
||||
Listening for fastboot command on 192.168.0.102
|
||||
|
||||
On the client side you can fetch the bootloader version for instance:
|
||||
|
||||
::
|
||||
On the client side you can fetch the bootloader version for instance::
|
||||
|
||||
$ fastboot getvar version-bootloader
|
||||
version-bootloader: U-Boot 2019.07-rc4-00240-g00c9f2a2ec
|
||||
Finished. Total time: 0.005s
|
||||
|
||||
or initiate a reboot:
|
||||
|
||||
::
|
||||
or initiate a reboot::
|
||||
|
||||
$ fastboot reboot
|
||||
|
||||
|
@ -184,9 +174,7 @@ and once the client comes back, the board should reset.
|
|||
You can also specify a kernel image to boot. You have to either specify
|
||||
the an image in Android format *or* pass a binary kernel and let the
|
||||
fastboot client wrap the Android suite around it. On OMAP for instance you
|
||||
take zImage kernel and pass it to the fastboot client:
|
||||
|
||||
::
|
||||
take zImage kernel and pass it to the fastboot client::
|
||||
|
||||
$ fastboot -b 0x80000000 -c "console=ttyO2 earlyprintk root=/dev/ram0 mem=128M" boot zImage
|
||||
creating boot image...
|
||||
|
@ -197,9 +185,7 @@ take zImage kernel and pass it to the fastboot client:
|
|||
OKAY [ -0.000s]
|
||||
finished. total time: 2.766s
|
||||
|
||||
and on the U-Boot side you should see:
|
||||
|
||||
::
|
||||
and on the U-Boot side you should see::
|
||||
|
||||
Starting download of 1847296 bytes
|
||||
........................................................
|
||||
|
@ -212,3 +198,9 @@ and on the U-Boot side you should see:
|
|||
OK
|
||||
|
||||
Starting kernel ...
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
.. [1] :doc:`fastboot-protocol`
|
||||
.. [2] https://developer.android.com/studio/releases/platform-tools
|
14
doc/android/index.rst
Normal file
14
doc/android/index.rst
Normal file
|
@ -0,0 +1,14 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
Android-specific doc
|
||||
====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
ab
|
||||
avb2
|
||||
bcb
|
||||
boot-image
|
||||
fastboot-protocol
|
||||
fastboot
|
|
@ -86,6 +86,18 @@ organized in a vendor subdirectory.
|
|||
|
||||
board/index
|
||||
|
||||
Android-specific doc
|
||||
--------------------
|
||||
|
||||
These books provide information about booting the Android OS from U-Boot,
|
||||
manipulating Android images from U-Boot shell and discusses other
|
||||
Android-specific features available in U-Boot.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
android/index
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
|
|
|
@ -434,7 +434,7 @@ int gpio_set_value(unsigned int gpio, int value)
|
|||
static struct davinci_gpio *davinci_get_gpio_bank(struct udevice *dev, unsigned int offset)
|
||||
{
|
||||
struct davinci_gpio_bank *bank = dev_get_priv(dev);
|
||||
unsigned int addr;
|
||||
unsigned long addr;
|
||||
|
||||
/*
|
||||
* The device tree is not broken into banks but the infrastructure is
|
||||
|
@ -535,6 +535,7 @@ static int davinci_gpio_probe(struct udevice *dev)
|
|||
static const struct udevice_id davinci_gpio_ids[] = {
|
||||
{ .compatible = "ti,dm6441-gpio" },
|
||||
{ .compatible = "ti,k2g-gpio" },
|
||||
{ .compatible = "ti,keystone-gpio" },
|
||||
{ }
|
||||
};
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
*
|
||||
* TODO:
|
||||
* 1. Support PCA957X_TYPE
|
||||
* 2. Support 24 gpio pins
|
||||
* 3. Support Polarity Inversion
|
||||
* 2. Support Polarity Inversion
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
@ -118,6 +117,10 @@ static int pca953x_read_regs(struct udevice *dev, int reg, u8 *val)
|
|||
ret = dm_i2c_read(dev, reg, val, 1);
|
||||
} else if (info->gpio_count <= 16) {
|
||||
ret = dm_i2c_read(dev, reg << 1, val, info->bank_count);
|
||||
} else if (info->gpio_count <= 24) {
|
||||
/* Auto increment */
|
||||
ret = dm_i2c_read(dev, (reg << 2) | 0x80, val,
|
||||
info->bank_count);
|
||||
} else if (info->gpio_count == 40) {
|
||||
/* Auto increment */
|
||||
ret = dm_i2c_read(dev, (reg << 3) | 0x80, val,
|
||||
|
@ -139,6 +142,10 @@ static int pca953x_write_regs(struct udevice *dev, int reg, u8 *val)
|
|||
ret = dm_i2c_write(dev, reg, val, 1);
|
||||
} else if (info->gpio_count <= 16) {
|
||||
ret = dm_i2c_write(dev, reg << 1, val, info->bank_count);
|
||||
} else if (info->gpio_count <= 24) {
|
||||
/* Auto increment */
|
||||
ret = dm_i2c_write(dev, (reg << 2) | 0x80, val,
|
||||
info->bank_count);
|
||||
} else if (info->gpio_count == 40) {
|
||||
/* Auto increment */
|
||||
ret = dm_i2c_write(dev, (reg << 3) | 0x80, val, info->bank_count);
|
||||
|
|
|
@ -150,24 +150,24 @@ static int omap3_wdt_reset(struct udevice *dev)
|
|||
{
|
||||
struct omap3_wdt_priv *priv = dev_get_priv(dev);
|
||||
|
||||
/*
|
||||
* Somebody just triggered watchdog reset and write to WTGR register
|
||||
* is in progress. It is resetting right now, no need to trigger it
|
||||
* again
|
||||
*/
|
||||
/*
|
||||
* Somebody just triggered watchdog reset and write to WTGR register
|
||||
* is in progress. It is resetting right now, no need to trigger it
|
||||
* again
|
||||
*/
|
||||
if ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR)
|
||||
return 0;
|
||||
|
||||
priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern);
|
||||
writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr);
|
||||
/*
|
||||
* Don't wait for posted write to complete, i.e. don't check
|
||||
* WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to
|
||||
* WTGR register outside of this func, and if entering it
|
||||
* we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset
|
||||
* was just triggered. This prevents us from wasting time in busy
|
||||
* polling of WDT_WWPS_PEND_WTGR bit.
|
||||
*/
|
||||
/*
|
||||
* Don't wait for posted write to complete, i.e. don't check
|
||||
* WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to
|
||||
* WTGR register outside of this func, and if entering it
|
||||
* we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset
|
||||
* was just triggered. This prevents us from wasting time in busy
|
||||
* polling of WDT_WWPS_PEND_WTGR bit.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -175,7 +175,7 @@ static int omap3_wdt_stop(struct udevice *dev)
|
|||
{
|
||||
struct omap3_wdt_priv *priv = dev_get_priv(dev);
|
||||
|
||||
/* disable watchdog */
|
||||
/* disable watchdog */
|
||||
writel(0xAAAA, &priv->regs->wdtwspr);
|
||||
while (readl(&priv->regs->wdtwwps) != 0x0)
|
||||
;
|
||||
|
@ -188,29 +188,29 @@ static int omap3_wdt_stop(struct udevice *dev)
|
|||
static int omap3_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
||||
{
|
||||
struct omap3_wdt_priv *priv = dev_get_priv(dev);
|
||||
u32 pre_margin = GET_WLDR_VAL(timeout_ms);
|
||||
/*
|
||||
* Make sure the watchdog is disabled. This is unfortunately required
|
||||
* because writing to various registers with the watchdog running has no
|
||||
* effect.
|
||||
*/
|
||||
u32 pre_margin = GET_WLDR_VAL(timeout_ms / 1000);
|
||||
/*
|
||||
* Make sure the watchdog is disabled. This is unfortunately required
|
||||
* because writing to various registers with the watchdog running has
|
||||
* no effect.
|
||||
*/
|
||||
omap3_wdt_stop(dev);
|
||||
|
||||
/* initialize prescaler */
|
||||
/* initialize prescaler */
|
||||
while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR)
|
||||
;
|
||||
|
||||
writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &priv->regs->wdtwclr);
|
||||
while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR)
|
||||
;
|
||||
/* just count up at 32 KHz */
|
||||
/* just count up at 32 KHz */
|
||||
while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR)
|
||||
;
|
||||
|
||||
writel(pre_margin, &priv->regs->wdtwldr);
|
||||
while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR)
|
||||
;
|
||||
/* Sequence to enable the watchdog */
|
||||
/* Sequence to enable the watchdog */
|
||||
writel(0xBBBB, &priv->regs->wdtwspr);
|
||||
while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR)
|
||||
;
|
||||
|
@ -219,6 +219,16 @@ static int omap3_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
|
|||
while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR)
|
||||
;
|
||||
|
||||
/* Trigger the watchdog to actually reload the counter. */
|
||||
while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR)
|
||||
;
|
||||
|
||||
priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern);
|
||||
writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr);
|
||||
|
||||
while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR)
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#ifdef CONFIG_TARGET_J721E_A72_EVM
|
||||
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SPL_TEXT_BASE + \
|
||||
CONFIG_SYS_K3_NON_SECURE_MSRAM_SIZE)
|
||||
/* Image load address in RAM for DFU boot*/
|
||||
#define CONFIG_SPL_LOAD_FIT_ADDRESS 0x81000000
|
||||
#else
|
||||
/*
|
||||
* Maximum size in memory allocated to the SPL BSS. Keep it as tight as
|
||||
|
@ -45,6 +47,8 @@
|
|||
/* Configure R5 SPL post-relocation malloc pool in DDR */
|
||||
#define CONFIG_SYS_SPL_MALLOC_START 0x84000000
|
||||
#define CONFIG_SYS_SPL_MALLOC_SIZE SZ_16M
|
||||
/* Image load address in RAM for DFU boot*/
|
||||
#define CONFIG_SPL_LOAD_FIT_ADDRESS 0x80080000
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_K3_SPL_ATF
|
||||
|
|
|
@ -37,11 +37,18 @@
|
|||
* seen large trees). We say all of this must be within the first 256MB
|
||||
* as that will normally be within the kernel lowmem and thus visible via
|
||||
* bootm_size and we only run on platforms with 256MB or more of memory.
|
||||
*
|
||||
* As a temporary storage for DTBO blobs (which should be applied into DTB
|
||||
* blob), we use the location 15.5 MB above the ramdisk. If someone wants to
|
||||
* use ramdisk bigger than 15.5 MB, then DTBO can be loaded and applied to DTB
|
||||
* blob before loading the ramdisk, as DTBO location is only used as a temporary
|
||||
* storage, and can be re-used after 'fdt apply' command is done.
|
||||
*/
|
||||
#define DEFAULT_LINUX_BOOT_ENV \
|
||||
"loadaddr=0x82000000\0" \
|
||||
"kernel_addr_r=0x82000000\0" \
|
||||
"fdtaddr=0x88000000\0" \
|
||||
"dtboaddr=0x89000000\0" \
|
||||
"fdt_addr_r=0x88000000\0" \
|
||||
"rdaddr=0x88080000\0" \
|
||||
"ramdisk_addr_r=0x88080000\0" \
|
||||
|
|
|
@ -13,30 +13,14 @@
|
|||
#define CONSOLEDEV "ttyS2"
|
||||
#endif
|
||||
|
||||
#define VBMETA_PART_SIZE (64 * 1024)
|
||||
|
||||
#if defined(CONFIG_LIBAVB)
|
||||
#define VBMETA_PART \
|
||||
"name=vbmeta,size=" __stringify(VBMETA_PART_SIZE) \
|
||||
",uuid=${uuid_gpt_vbmeta};"
|
||||
#else
|
||||
#define VBMETA_PART ""
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_AB_SELECT)
|
||||
#define COMMON_PARTS \
|
||||
"name=boot_a,size=20M,uuid=${uuid_gpt_boot_a};" \
|
||||
"name=boot_b,size=20M,uuid=${uuid_gpt_boot_b};" \
|
||||
"name=system_a,size=1024M,uuid=${uuid_gpt_system_a};" \
|
||||
"name=system_b,size=1024M,uuid=${uuid_gpt_system_b};"
|
||||
#else
|
||||
#define COMMON_PARTS \
|
||||
"name=boot,size=20M,uuid=${uuid_gpt_boot};" \
|
||||
"name=system,size=1024M,uuid=${uuid_gpt_system};"
|
||||
#endif
|
||||
|
||||
#ifndef PARTS_DEFAULT
|
||||
/* Define the default GPT table for eMMC */
|
||||
/*
|
||||
* Default GPT tables for eMMC (Linux and Android). Notes:
|
||||
* 1. Keep partitions aligned to erase group size (512 KiB) when possible
|
||||
* 2. Keep partitions in sync with DFU_ALT_INFO_EMMC (see dfu.h)
|
||||
* 3. Keep 'bootloader' partition (U-Boot proper) start address in sync with
|
||||
* CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR (see common/spl/Kconfig)
|
||||
*/
|
||||
#define PARTS_DEFAULT \
|
||||
/* Linux partitions */ \
|
||||
"uuid_disk=${uuid_gpt_disk};" \
|
||||
|
@ -49,10 +33,15 @@
|
|||
"name=bootloader,size=2048K,uuid=${uuid_gpt_bootloader};" \
|
||||
"name=uboot-env,start=2432K,size=256K,uuid=${uuid_gpt_reserved};" \
|
||||
"name=misc,size=128K,uuid=${uuid_gpt_misc};" \
|
||||
"name=recovery,size=40M,uuid=${uuid_gpt_recovery};" \
|
||||
COMMON_PARTS \
|
||||
"name=vendor,size=256M,uuid=${uuid_gpt_vendor};" \
|
||||
VBMETA_PART \
|
||||
"name=boot_a,size=20M,uuid=${uuid_gpt_boot_a};" \
|
||||
"name=boot_b,size=20M,uuid=${uuid_gpt_boot_b};" \
|
||||
"name=dtbo_a,size=8M,uuid=${uuid_gpt_dtbo_a};" \
|
||||
"name=dtbo_b,size=8M,uuid=${uuid_gpt_dtbo_b};" \
|
||||
"name=vbmeta_a,size=64K,uuid=${uuid_gpt_vbmeta_a};" \
|
||||
"name=vbmeta_b,size=64K,uuid=${uuid_gpt_vbmeta_b};" \
|
||||
"name=recovery,size=64M,uuid=${uuid_gpt_recovery};" \
|
||||
"name=super,size=2560M,uuid=${uuid_gpt_super};" \
|
||||
"name=metadata,size=16M,uuid=${uuid_gpt_metadata};" \
|
||||
"name=userdata,size=-,uuid=${uuid_gpt_userdata}"
|
||||
#endif /* PARTS_DEFAULT */
|
||||
|
||||
|
@ -63,7 +52,7 @@
|
|||
"else " \
|
||||
"echo AVB verification failed.;" \
|
||||
"exit; fi;"
|
||||
#define AVB_VERIFY_CMD "avb_verify=avb init 1; avb verify;\0"
|
||||
#define AVB_VERIFY_CMD "avb_verify=avb init 1; avb verify $slot_suffix;\0"
|
||||
#else
|
||||
#define AVB_VERIFY_CHECK ""
|
||||
#define AVB_VERIFY_CMD ""
|
||||
|
@ -72,7 +61,7 @@
|
|||
#define CONTROL_PARTITION "misc"
|
||||
|
||||
#if defined(CONFIG_CMD_AB_SELECT)
|
||||
#define AB_SELECT \
|
||||
#define AB_SELECT_SLOT \
|
||||
"if part number mmc 1 " CONTROL_PARTITION " control_part_number; " \
|
||||
"then " \
|
||||
"echo " CONTROL_PARTITION \
|
||||
|
@ -82,22 +71,55 @@
|
|||
"echo " CONTROL_PARTITION " partition not found;" \
|
||||
"exit;" \
|
||||
"fi;" \
|
||||
"setenv slot_suffix _${slot_name};" \
|
||||
"if part number mmc ${mmcdev} system${slot_suffix} " \
|
||||
"system_part_number; then " \
|
||||
"setenv bootargs_ab " \
|
||||
"ro root=/dev/mmcblk${mmcdev}p${system_part_number} " \
|
||||
"rootwait init=/init skip_initramfs " \
|
||||
"androidboot.slot_suffix=${slot_suffix};" \
|
||||
"echo A/B cmdline addition: ${bootargs_ab};" \
|
||||
"setenv bootargs ${bootargs} ${bootargs_ab};" \
|
||||
"else " \
|
||||
"echo system${slot_suffix} partition not found;" \
|
||||
"fi;"
|
||||
"setenv slot_suffix _${slot_name};"
|
||||
#define AB_SELECT_ARGS \
|
||||
"setenv bootargs_ab androidboot.slot_suffix=${slot_suffix}; " \
|
||||
"echo A/B cmdline addition: ${bootargs_ab};" \
|
||||
"setenv bootargs ${bootargs} ${bootargs_ab};"
|
||||
#else
|
||||
#define AB_SELECT ""
|
||||
#define AB_SELECT_SLOT ""
|
||||
#define AB_SELECT_ARGS ""
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Prepares complete device tree blob for current board (for Android boot).
|
||||
*
|
||||
* Boot image or recovery image should be loaded into $loadaddr prior to running
|
||||
* these commands. The logic of these commnads is next:
|
||||
*
|
||||
* 1. Read correct DTB for current SoC/board from boot image in $loadaddr
|
||||
* to $fdtaddr
|
||||
* 2. Merge all needed DTBO for current board from 'dtbo' partition into read
|
||||
* DTB
|
||||
* 3. User should provide $fdtaddr as 3rd argument to 'bootm'
|
||||
*/
|
||||
#define PREPARE_FDT \
|
||||
"echo Preparing FDT...; " \
|
||||
"if test $board_name = am57xx_evm_reva3; then " \
|
||||
"echo \" Reading DTBO partition...\"; " \
|
||||
"part start mmc ${mmcdev} dtbo${slot_suffix} p_dtbo_start; " \
|
||||
"part size mmc ${mmcdev} dtbo${slot_suffix} p_dtbo_size; " \
|
||||
"mmc read ${dtboaddr} ${p_dtbo_start} ${p_dtbo_size}; " \
|
||||
"echo \" Reading DTB for AM57x EVM RevA3...\"; " \
|
||||
"abootimg get dtb --index=0 dtb_start dtb_size; " \
|
||||
"cp.b $dtb_start $fdtaddr $dtb_size; " \
|
||||
"fdt addr $fdtaddr; " \
|
||||
"echo \" Applying DTBOs for AM57x EVM RevA3...\"; " \
|
||||
"adtimg addr $dtboaddr; " \
|
||||
"adtimg get dt --index=0 dtbo0_addr; " \
|
||||
"fdt apply $dtbo0_addr; " \
|
||||
"adtimg get dt --index=1 dtbo1_addr; " \
|
||||
"fdt apply $dtbo1_addr; " \
|
||||
"elif test $board_name = beagle_x15_revc; then " \
|
||||
"echo \" Reading DTB for Beagle X15 RevC...\"; " \
|
||||
"abootimg get dtb --index=0 dtb_start dtb_size; " \
|
||||
"cp.b $dtb_start $fdtaddr $dtb_size; " \
|
||||
"fdt addr $fdtaddr; " \
|
||||
"else " \
|
||||
"echo Error: Android boot is not supported for $board_name; " \
|
||||
"exit; " \
|
||||
"fi; " \
|
||||
|
||||
#define FASTBOOT_CMD \
|
||||
"echo Booting into fastboot ...; " \
|
||||
"fastboot " __stringify(CONFIG_FASTBOOT_USB_DEV) "; "
|
||||
|
@ -121,46 +143,44 @@
|
|||
"setenv mmcroot /dev/mmcblk0p2 rw; " \
|
||||
"run mmcboot;\0" \
|
||||
"emmc_android_boot=" \
|
||||
"setenv mmcdev 1; " \
|
||||
"mmc dev $mmcdev; " \
|
||||
"mmc rescan; " \
|
||||
AB_SELECT_SLOT \
|
||||
"if bcb load " __stringify(CONFIG_FASTBOOT_FLASH_MMC_DEV) " " \
|
||||
CONTROL_PARTITION "; then " \
|
||||
"setenv ardaddr -; " \
|
||||
"if bcb test command = bootonce-bootloader; then " \
|
||||
"echo BCB: Bootloader boot...; " \
|
||||
"echo Android: Bootloader boot...; " \
|
||||
"bcb clear command; bcb store; " \
|
||||
FASTBOOT_CMD \
|
||||
"exit; " \
|
||||
"elif bcb test command = boot-recovery; then " \
|
||||
"echo BCB: Recovery boot...; " \
|
||||
"echo Warning: recovery is not implemented; " \
|
||||
"echo Performing normal boot for now...; " \
|
||||
"bcb clear command; bcb store; " \
|
||||
"run emmc_android_normal_boot; " \
|
||||
"echo Android: Recovery boot...; " \
|
||||
"setenv ardaddr $loadaddr;" \
|
||||
"setenv apart recovery; " \
|
||||
"else " \
|
||||
"echo BCB: Normal boot requested...; " \
|
||||
"run emmc_android_normal_boot; " \
|
||||
"echo Android: Normal boot...; " \
|
||||
"setenv ardaddr $loadaddr; " \
|
||||
"setenv apart boot${slot_suffix}; " \
|
||||
"fi; " \
|
||||
"else " \
|
||||
"echo Warning: BCB is corrupted or does not exist; " \
|
||||
"echo Performing normal boot...; " \
|
||||
"run emmc_android_normal_boot; " \
|
||||
"fi;\0" \
|
||||
"emmc_android_normal_boot=" \
|
||||
"echo Trying to boot Android from eMMC ...; " \
|
||||
"run update_to_fit; " \
|
||||
"echo Android: Normal boot...; " \
|
||||
"fi; " \
|
||||
"setenv eval_bootargs setenv bootargs $bootargs; " \
|
||||
"run eval_bootargs; " \
|
||||
"setenv mmcdev 1; " \
|
||||
"setenv machid fe6; " \
|
||||
"mmc dev $mmcdev; " \
|
||||
"mmc rescan; " \
|
||||
AVB_VERIFY_CHECK \
|
||||
AB_SELECT \
|
||||
"if part start mmc ${mmcdev} boot${slot_suffix} boot_start; " \
|
||||
"then " \
|
||||
"part size mmc ${mmcdev} boot${slot_suffix} " \
|
||||
"boot_size; " \
|
||||
"mmc read ${loadaddr} ${boot_start} ${boot_size}; " \
|
||||
"bootm ${loadaddr}#${fdtfile}; " \
|
||||
AB_SELECT_ARGS \
|
||||
"if part start mmc $mmcdev $apart boot_start; then " \
|
||||
"part size mmc $mmcdev $apart boot_size; " \
|
||||
"mmc read $loadaddr $boot_start $boot_size; " \
|
||||
PREPARE_FDT \
|
||||
"bootm $loadaddr $ardaddr $fdtaddr; " \
|
||||
"else " \
|
||||
"echo boot${slot_suffix} partition not found; " \
|
||||
"echo $apart partition not found; " \
|
||||
"exit; " \
|
||||
"fi;\0"
|
||||
|
||||
#ifdef CONFIG_OMAP54XX
|
||||
|
|
|
@ -1425,10 +1425,16 @@ int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
|
|||
ulong *rd_data, ulong *rd_len);
|
||||
int android_image_get_second(const struct andr_img_hdr *hdr,
|
||||
ulong *second_data, ulong *second_len);
|
||||
bool android_image_get_dtbo(ulong hdr_addr, ulong *addr, u32 *size);
|
||||
bool android_image_get_dtb_by_index(ulong hdr_addr, u32 index, ulong *addr,
|
||||
u32 *size);
|
||||
ulong android_image_get_end(const struct andr_img_hdr *hdr);
|
||||
ulong android_image_get_kload(const struct andr_img_hdr *hdr);
|
||||
ulong android_image_get_kcomp(const struct andr_img_hdr *hdr);
|
||||
void android_print_contents(const struct andr_img_hdr *hdr);
|
||||
#if !defined(CONFIG_SPL_BUILD)
|
||||
bool android_image_print_dtb_contents(ulong hdr_addr);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_ANDROID_BOOT_IMAGE */
|
||||
|
||||
|
|
159
test/py/tests/test_android/test_abootimg.py
Normal file
159
test/py/tests/test_android/test_abootimg.py
Normal file
|
@ -0,0 +1,159 @@
|
|||
# SPDX-License-Identifier: GPL-2.0+
|
||||
# Copyright (c) 2020
|
||||
# Author: Sam Protsenko <joe.skb7@gmail.com>
|
||||
|
||||
# Test U-Boot's "abootimg" commands.
|
||||
|
||||
import os
|
||||
import pytest
|
||||
import u_boot_utils
|
||||
|
||||
"""
|
||||
These tests rely on disk image (boot.img), which is automatically created by
|
||||
the test from the stored hex dump. This is done to avoid the dependency on the
|
||||
most recent mkbootimg tool from AOSP/master. Here is the list of commands which
|
||||
was used to generate the boot.img and obtain compressed hex dump from it:
|
||||
|
||||
$ echo '/dts-v1/; / { model = "x1"; compatible = "y1,z1"; };' > test1.dts
|
||||
$ echo '/dts-v1/; / { model = "x2"; compatible = "y2,z2"; };' > test2.dts
|
||||
$ dtc test1.dts > dt1.dtb
|
||||
$ dtc test2.dts > dt2.dtb
|
||||
$ cat dt1.dtb dt2.dtb > dtb.img
|
||||
$ echo 'kernel payload' > kernel
|
||||
$ echo 'ramdisk payload' > ramdisk.img
|
||||
$ mkbootimg --kernel ./kernel --ramdisk ./ramdisk.img \
|
||||
--cmdline "cmdline test" --dtb ./dtb.img \
|
||||
--os_version R --os_patch_level 2019-06-05 \
|
||||
--header_version 2 --output boot.img
|
||||
$ gzip -9 boot.img
|
||||
$ xxd -p boot.img.gz > boot.img.gz.hex
|
||||
|
||||
Now one can obtain original boot.img from this hex dump like this:
|
||||
|
||||
$ xxd -r -p boot.img.gz.hex boot.img.gz
|
||||
$ gunzip -9 boot.img.gz
|
||||
"""
|
||||
|
||||
# boot.img.gz hex dump
|
||||
img_hex = """1f8b08084844af5d0203626f6f742e696d670073f47309f2f77451e46700
|
||||
820606010106301084501f04181819041838181898803c3346060c909c9b
|
||||
92939997aa50925a5cc2300a461c3078b2e1793c4b876fd92db97939fb6c
|
||||
b7762ffff07d345446c1281805e8a0868d81e117a45e111c0d8dc101b253
|
||||
8bf25273140a122b73f21353b8460364148c8251300a46c1281801a02831
|
||||
3725b3387bb401300a46c1281805a360148c207081f7df5b20550bc41640
|
||||
9c03c41a0c90f17fe85400986d82452b6c3680198a192a0ce17c3610ae34
|
||||
d4a9820881a70f3873f35352731892f3730b124b32937252a96bb9119ae5
|
||||
463a5546f82c1f05a360148c8251300a462e000085bf67f200200000"""
|
||||
# Expected response for "abootimg dtb_dump" command
|
||||
dtb_dump_resp="""## DTB area contents (concat format):
|
||||
- DTB #0:
|
||||
(DTB)size = 125
|
||||
(DTB)model = x1
|
||||
(DTB)compatible = y1,z1
|
||||
- DTB #1:
|
||||
(DTB)size = 125
|
||||
(DTB)model = x2
|
||||
(DTB)compatible = y2,z2"""
|
||||
# Address in RAM where to load the boot image ('abootimg' looks in $loadaddr)
|
||||
loadaddr = 0x1000
|
||||
# Expected DTB #1 offset from the boot image start address
|
||||
dtb1_offset = 0x187d
|
||||
# DTB #1 start address in RAM
|
||||
dtb1_addr = loadaddr + dtb1_offset
|
||||
|
||||
class AbootimgTestDiskImage(object):
|
||||
"""Disk image used by abootimg tests."""
|
||||
|
||||
def __init__(self, u_boot_console):
|
||||
"""Initialize a new AbootimgDiskImage object.
|
||||
|
||||
Args:
|
||||
u_boot_console: A U-Boot console.
|
||||
|
||||
Returns:
|
||||
Nothing.
|
||||
"""
|
||||
|
||||
gz_hex = u_boot_console.config.persistent_data_dir + '/boot.img.gz.hex'
|
||||
gz = u_boot_console.config.persistent_data_dir + '/boot.img.gz'
|
||||
|
||||
filename = 'boot.img'
|
||||
persistent = u_boot_console.config.persistent_data_dir + '/' + filename
|
||||
self.path = u_boot_console.config.result_dir + '/' + filename
|
||||
|
||||
with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent):
|
||||
if os.path.exists(persistent):
|
||||
u_boot_console.log.action('Disk image file ' + persistent +
|
||||
' already exists')
|
||||
else:
|
||||
u_boot_console.log.action('Generating ' + persistent)
|
||||
|
||||
f = open(gz_hex, "w")
|
||||
f.write(img_hex)
|
||||
f.close()
|
||||
|
||||
cmd = ('xxd', '-r', '-p', gz_hex, gz)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
cmd = ('gunzip', '-9', gz)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
cmd = ('cp', persistent, self.path)
|
||||
u_boot_utils.run_and_log(u_boot_console, cmd)
|
||||
|
||||
gtdi = None
|
||||
@pytest.fixture(scope='function')
|
||||
def abootimg_disk_image(u_boot_console):
|
||||
"""pytest fixture to provide a AbootimgTestDiskImage object to tests.
|
||||
This is function-scoped because it uses u_boot_console, which is also
|
||||
function-scoped. However, we don't need to actually do any function-scope
|
||||
work, so this simply returns the same object over and over each time."""
|
||||
|
||||
global gtdi
|
||||
if not gtdi:
|
||||
gtdi = AbootimgTestDiskImage(u_boot_console)
|
||||
return gtdi
|
||||
|
||||
@pytest.mark.boardspec('sandbox')
|
||||
@pytest.mark.buildconfigspec('android_boot_image')
|
||||
@pytest.mark.buildconfigspec('cmd_abootimg')
|
||||
@pytest.mark.buildconfigspec('cmd_fdt')
|
||||
@pytest.mark.requiredtool('xxd')
|
||||
@pytest.mark.requiredtool('gunzip')
|
||||
def test_abootimg(abootimg_disk_image, u_boot_console):
|
||||
"""Test the 'abootimg' command."""
|
||||
|
||||
u_boot_console.log.action('Loading disk image to RAM...')
|
||||
u_boot_console.run_command('setenv loadaddr 0x%x' % (loadaddr))
|
||||
u_boot_console.run_command('host load hostfs - 0x%x %s' % (loadaddr,
|
||||
abootimg_disk_image.path))
|
||||
|
||||
u_boot_console.log.action('Testing \'abootimg get ver\'...')
|
||||
response = u_boot_console.run_command('abootimg get ver')
|
||||
assert response == "2"
|
||||
u_boot_console.run_command('abootimg get ver v')
|
||||
response = u_boot_console.run_command('env print v')
|
||||
assert response == 'v=2'
|
||||
|
||||
u_boot_console.log.action('Testing \'abootimg get recovery_dtbo\'...')
|
||||
response = u_boot_console.run_command('abootimg get recovery_dtbo a')
|
||||
assert response == 'Error: recovery_dtbo_size is 0'
|
||||
|
||||
u_boot_console.log.action('Testing \'abootimg dump dtb\'...')
|
||||
response = u_boot_console.run_command('abootimg dump dtb').replace('\r', '')
|
||||
assert response == dtb_dump_resp
|
||||
|
||||
u_boot_console.log.action('Testing \'abootimg get dtb_load_addr\'...')
|
||||
u_boot_console.run_command('abootimg get dtb_load_addr a')
|
||||
response = u_boot_console.run_command('env print a')
|
||||
assert response == 'a=11f00000'
|
||||
|
||||
u_boot_console.log.action('Testing \'abootimg get dtb --index\'...')
|
||||
u_boot_console.run_command('abootimg get dtb --index=1 dtb1_start')
|
||||
response = u_boot_console.run_command('env print dtb1_start')
|
||||
correct_str = "dtb1_start=%x" % (dtb1_addr)
|
||||
assert response == correct_str
|
||||
u_boot_console.run_command('fdt addr $dtb1_start')
|
||||
u_boot_console.run_command('fdt get value v / model')
|
||||
response = u_boot_console.run_command('env print v')
|
||||
assert response == 'v=x2'
|
|
@ -8,7 +8,7 @@
|
|||
This tests Android Verified Boot 2.0 support in U-boot:
|
||||
|
||||
For additional details about how to build proper vbmeta partition
|
||||
check doc/android/avb2.txt
|
||||
check doc/android/avb2.rst
|
||||
|
||||
For configuration verification:
|
||||
- Corrupt boot partition and check for failure
|
||||
|
|
Loading…
Add table
Reference in a new issue