Commit d0d678fd authored by Ye Li's avatar Ye Li

MLK-12527-2 android: Add FSL android fastboot support

Integrate the FSL android fastboot features into community's fastboot.

1. Use USB gadget g_dnl driver
2. Integrate the FSL SD/SATA/NAND flash operations, since the GPT and
   EFI partitions are not support by i.MX.
3. Add FDT support to community's android image.
4. Add a new boot command "boota" for android image boot. The boota
   implements to load ramdisk and fdt to their loading addresses
   specified in boot.img header, while bootm won't do it for android image.
5. Support the authentication of boot.img at the "load_addr" for
   both SD and NAND.
6. We use new configuration CONFIG_FSL_FASTBOOT for Freescale's fastboot
   with relevant header file "fsl_fastboot.h". While disabling the
   configuration, the community fastboot is used.
7. Overwrite the cmdline in boot.img by using bootargs saved in local environment.
8. Add recovery and reboot-bootloader support.
Signed-off-by: 's avatarYe Li <ye.li@nxp.com>
(cherry picked from commit 23d63ff185929fff5e392efc853d69b606ba081a)
parent e84160ea
......@@ -22,6 +22,10 @@
#include <dm.h>
#include <imx_thermal.h>
#include <mmc.h>
#if defined(CONFIG_FSL_FASTBOOT) && defined(CONFIG_ANDROID_RECOVERY)
#include <recovery.h>
#endif
enum ldo_reg {
LDO_ARM,
......@@ -657,6 +661,19 @@ int board_postclk_init(void)
return 0;
}
#ifdef CONFIG_SERIAL_TAG
void get_board_serial(struct tag_serialnr *serialnr)
{
struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
struct fuse_bank *bank = &ocotp->bank[0];
struct fuse_bank0_regs *fuse =
(struct fuse_bank0_regs *)bank->fuse_regs;
serialnr->low = fuse->uid_low;
serialnr->high = fuse->uid_high;
}
#endif
#if defined(CONFIG_FEC_MXC)
void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
{
......@@ -713,6 +730,49 @@ const struct boot_mode soc_boot_modes[] = {
{NULL, 0},
};
enum boot_device get_boot_device(void)
{
enum boot_device boot_dev = UNKNOWN_BOOT;
uint soc_sbmr = readl(SRC_BASE_ADDR + 0x4);
uint bt_mem_ctl = (soc_sbmr & 0x000000FF) >> 4 ;
uint bt_mem_type = (soc_sbmr & 0x00000008) >> 3;
uint bt_dev_port = (soc_sbmr & 0x00001800) >> 11;
switch (bt_mem_ctl) {
case 0x0:
if (bt_mem_type)
boot_dev = ONE_NAND_BOOT;
else
boot_dev = WEIM_NOR_BOOT;
break;
case 0x2:
boot_dev = SATA_BOOT;
break;
case 0x3:
if (bt_mem_type)
boot_dev = I2C_BOOT;
else
boot_dev = SPI_NOR_BOOT;
break;
case 0x4:
case 0x5:
boot_dev = bt_dev_port + SD1_BOOT;
break;
case 0x6:
case 0x7:
boot_dev = bt_dev_port + MMC1_BOOT;
break;
case 0x8 ... 0xf:
boot_dev = NAND_BOOT;
break;
default:
boot_dev = UNKNOWN_BOOT;
break;
}
return boot_dev;
}
void set_wdog_reset(struct wdog_regs *wdog)
{
u32 reg = readw(&wdog->wcr);
......@@ -994,3 +1054,56 @@ void finish_anatop_bypass(void)
set_arm_freq_400M(false);
}
#endif
#ifdef CONFIG_FSL_FASTBOOT
#ifdef CONFIG_ANDROID_RECOVERY
#define ANDROID_RECOVERY_BOOT (1 << 7)
/* check if the recovery bit is set by kernel, it can be set by kernel
* issue a command '# reboot recovery' */
int recovery_check_and_clean_flag(void)
{
int flag_set = 0;
u32 reg;
reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR);
flag_set = !!(reg & ANDROID_RECOVERY_BOOT);
printf("check_and_clean: reg %x, flag_set %d\n", reg, flag_set);
/* clean it in case looping infinite here.... */
if (flag_set) {
reg &= ~ANDROID_RECOVERY_BOOT;
writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR);
}
return flag_set;
}
#endif /*CONFIG_ANDROID_RECOVERY*/
#define ANDROID_FASTBOOT_BOOT (1 << 8)
/* check if the recovery bit is set by kernel, it can be set by kernel
* issue a command '# reboot fastboot' */
int fastboot_check_and_clean_flag(void)
{
int flag_set = 0;
u32 reg;
reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR);
flag_set = !!(reg & ANDROID_FASTBOOT_BOOT);
/* clean it in case looping infinite here.... */
if (flag_set) {
reg &= ~ANDROID_FASTBOOT_BOOT;
writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR);
}
return flag_set;
}
void fastboot_enable_flag(void)
{
setbits_le32(SNVS_BASE_ADDR + SNVS_LPGPR,
ANDROID_FASTBOOT_BOOT);
}
#endif /*CONFIG_FSL_FASTBOOT*/
......@@ -19,6 +19,9 @@
#include <dm.h>
#include <imx_thermal.h>
#include <fsl_wdog.h>
#if defined(CONFIG_FSL_FASTBOOT) && defined(CONFIG_ANDROID_RECOVERY)
#include <recovery.h>
#endif
#if defined(CONFIG_IMX_THERMAL)
static const struct imx_thermal_plat imx7_thermal_plat = {
......@@ -510,3 +513,60 @@ void reset_cpu(ulong addr)
*/
}
}
#ifdef CONFIG_FSL_FASTBOOT
#ifdef CONFIG_ANDROID_RECOVERY
#define ANDROID_RECOVERY_BOOT (1 << 7)
/*
* check if the recovery bit is set by kernel, it can be set by kernel
* issue a command '# reboot recovery'
*/
int recovery_check_and_clean_flag(void)
{
int flag_set = 0;
u32 reg;
reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR);
flag_set = !!(reg & ANDROID_RECOVERY_BOOT);
printf("check_and_clean: reg %x, flag_set %d\n", reg, flag_set);
/* clean it in case looping infinite here.... */
if (flag_set) {
reg &= ~ANDROID_RECOVERY_BOOT;
writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR);
}
return flag_set;
}
#endif /*CONFIG_ANDROID_RECOVERY*/
#define ANDROID_FASTBOOT_BOOT (1 << 8)
/*
* check if the recovery bit is set by kernel, it can be set by kernel
* issue a command '# reboot fastboot'
*/
int fastboot_check_and_clean_flag(void)
{
int flag_set = 0;
u32 reg;
reg = readl(SNVS_BASE_ADDR + SNVS_LPGPR);
flag_set = !!(reg & ANDROID_FASTBOOT_BOOT);
/* clean it in case looping infinite here.... */
if (flag_set) {
reg &= ~ANDROID_FASTBOOT_BOOT;
writel(reg, SNVS_BASE_ADDR + SNVS_LPGPR);
}
return flag_set;
}
void fastboot_enable_flag(void)
{
setbits_le32(SNVS_BASE_ADDR + SNVS_LPGPR,
ANDROID_FASTBOOT_BOOT);
}
#endif /*CONFIG_FSL_FASTBOOT*/
......@@ -3,6 +3,8 @@
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
* Copyright 2017 NXP
*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
......
......@@ -65,6 +65,9 @@ obj-$(CONFIG_POWER_MC34VR500) += mc34vr500.o
obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze_dm.o
obj-$(CONFIG_MXC_EPDC) += epdc_setup.o
obj-y += mmc.o
ifdef CONFIG_FSL_FASTBOOT
obj-${CONFIG_ANDROID_RECOVERY} += recovery.o
endif
obj-$(CONFIG_LS102XA_STREAM_ID) += ls102xa_stream_id.o
......
/*
* Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <malloc.h>
#include <recovery.h>
#ifdef CONFIG_MXC_KPD
#include <mxc_keyb.h>
#endif
#include <asm/imx-common/boot_mode.h>
#ifdef CONFIG_MXC_KPD
#define PRESSED_VOL_DOWN 0x01
#define PRESSED_POWER 0x02
#define RECOVERY_KEY_MASK (PRESSED_VOL_DOWN | PRESSED_POWER)
inline int test_key(int value, struct kpp_key_info *ki)
{
return (ki->val == value) && (ki->evt == KDepress);
}
int check_key_pressing(void)
{
struct kpp_key_info *key_info = NULL;
int state = 0, keys, i;
int ret = 0;
mxc_kpp_init();
/* due to glitch suppression circuit,
wait sometime to let all keys scanned. */
udelay(1000);
keys = mxc_kpp_getc(&key_info);
printf("Detecting VOL_DOWN+POWER key for recovery(%d:%d) ...\n",
keys, keys ? key_info->val : 0);
if (keys > 1) {
for (i = 0; i < keys; i++) {
if (test_key(CONFIG_POWER_KEY, &key_info[i]))
state |= PRESSED_POWER;
else if (test_key(CONFIG_VOL_DOWN_KEY, &key_info[i]))
state |= PRESSED_VOL_DOWN;
}
}
if ((state & RECOVERY_KEY_MASK) == RECOVERY_KEY_MASK)
ret = 1;
if (key_info)
free(key_info);
return ret;
}
#else
/* If not using mxc keypad, currently we will detect power key on board */
int check_key_pressing(void)
{
return 0;
}
#endif
void setup_recovery_env(void)
{
board_recovery_setup();
}
/* export to lib_arm/board.c */
void check_recovery_mode(void)
{
if (check_key_pressing()) {
puts("Fastboot: Recovery key pressing got!\n");
setup_recovery_env();
} else if (check_recovery_cmd_file()) {
puts("Fastboot: Recovery command file found!\n");
setup_recovery_env();
} else {
puts("Fastboot: Normal\n");
}
}
......@@ -24,6 +24,44 @@ config ANDROID_BOOT_IMAGE
This enables support for booting images which use the Android
image format header.
config FSL_FASTBOOT
bool "Enable FSL fastboot support"
help
This enables FSL implementation for Android fastboot.
if FSL_FASTBOOT
config ANDROID_RECOVERY
bool "Enable the recovery boot function"
help
This enables the Android Recovery boot function.
config CMD_BOOTA
bool "Enable the boota command"
help
This enables the boota command for booting android images.
choice
prompt "Android Image Storage select"
default FASTBOOT_STORAGE_MMC
config FASTBOOT_STORAGE_MMC
bool "Using eMMC/SD for Android fastboot storage media"
config FASTBOOT_STORAGE_NAND
bool "Using NAND flash for Android fastboot storage media"
config FASTBOOT_STORAGE_SATA
bool "Using SATA disk for Android fastboot storage media"
endchoice
config FASTBOOT_SATA_NO
int "Sata device index"
depends on FASTBOOT_STORAGE_SATA
endif #FSL_FASTBOOT
if USB_FUNCTION_FASTBOOT
config FASTBOOT_BUF_ADDR
......
......@@ -7,6 +7,8 @@
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
......@@ -66,6 +68,9 @@
#include <asm/arch/mmu.h>
#endif
#include <efi_loader.h>
#ifdef CONFIG_FSL_FASTBOOT
#include <fsl_fastboot.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
......@@ -717,6 +722,20 @@ static int initr_kbd(void)
}
#endif
#ifdef CONFIG_FSL_FASTBOOT
static int initr_fastboot_setup(void)
{
fastboot_setup();
return 0;
}
static int initr_check_fastboot(void)
{
check_fastboot();
return 0;
}
#endif
static int run_main_loop(void)
{
#ifdef CONFIG_SANDBOX
......@@ -894,6 +913,9 @@ static init_fnc_t init_sequence_r[] = {
#ifdef CONFIG_BOARD_LATE_INIT
board_late_init,
#endif
#ifdef CONFIG_FSL_FASTBOOT
initr_fastboot_setup,
#endif
#if defined(CONFIG_CMD_AMBAPP)
ambapp_init_reloc,
#if defined(CONFIG_SYS_AMBAPP_PRINT_ON_STARTUP)
......@@ -941,6 +963,9 @@ static init_fnc_t init_sequence_r[] = {
#endif
#if defined(CONFIG_SPARC)
prom_init,
#endif
#ifdef CONFIG_FSL_FASTBOOT
initr_check_fastboot,
#endif
run_main_loop,
};
......
/*
* Copyright (c) 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
......@@ -9,6 +11,7 @@
#include <android_image.h>
#include <malloc.h>
#include <errno.h>
#include <asm/bootm.h>
#define ANDROID_IMAGE_DEFAULT_KERNEL_ADDR 0x10008000
......@@ -68,7 +71,6 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
int len = 0;
if (*hdr->cmdline) {
printf("Kernel command line: %s\n", hdr->cmdline);
len += strlen(hdr->cmdline);
}
......@@ -85,12 +87,25 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
if (bootargs) {
strcpy(newbootargs, bootargs);
strcat(newbootargs, " ");
}
if (*hdr->cmdline)
} else if (*hdr->cmdline) {
strcat(newbootargs, hdr->cmdline);
}
printf("Kernel command line: %s\n", newbootargs);
#ifdef CONFIG_SERIAL_TAG
struct tag_serialnr serialnr;
char commandline[ANDR_BOOT_ARGS_SIZE];
get_board_serial(&serialnr);
sprintf(commandline,
"%s androidboot.serialno=%08x%08x",
newbootargs,
serialnr.high,
serialnr.low);
setenv("bootargs", commandline);
#else
setenv("bootargs", newbootargs);
#endif
if (os_data) {
*os_data = (ulong)hdr;
......@@ -174,3 +189,21 @@ void android_print_contents(const struct andr_img_hdr *hdr)
printf("%scmdline: %s\n", p, hdr->cmdline);
}
#endif
int android_image_get_fdt(const struct andr_img_hdr *hdr,
ulong *fdt_data, ulong *fdt_len)
{
if (!hdr->second_size)
return -1;
printf("FDT load addr 0x%08x size %u KiB\n",
hdr->second_addr, DIV_ROUND_UP(hdr->second_size, 1024));
*fdt_data = (unsigned long)hdr;
*fdt_data += hdr->page_size;
*fdt_data += ALIGN(hdr->kernel_size, hdr->page_size);
*fdt_data += ALIGN(hdr->ramdisk_size, hdr->page_size);
*fdt_len = hdr->second_size;
return 0;
}
......@@ -6,6 +6,8 @@
* (C) Copyright 2000-2006
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
......@@ -417,7 +419,34 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch,
debug("## No Flattened Device Tree\n");
goto no_fdt;
}
} else {
}
#ifdef CONFIG_ANDROID_BOOT_IMAGE
else if (genimg_get_format((void *)images->os.start) ==
IMAGE_FORMAT_ANDROID) {
ulong fdt_data, fdt_len;
android_image_get_fdt((void *)images->os.start,
&fdt_data, &fdt_len);
if (fdt_len) {
fdt_blob = (char *)fdt_data;
printf(" Booting using the fdt at 0x%p\n", fdt_blob);
if (fdt_check_header(fdt_blob) != 0) {
fdt_error("image is not a fdt");
goto error;
}
if (fdt_totalsize(fdt_blob) != fdt_len) {
fdt_error("fdt size != image size");
goto error;
}
} else {
debug("## No Flattened Device Tree\n");
goto no_fdt;
}
}
#endif
else {
debug("## No Flattened Device Tree\n");
goto no_fdt;
}
......
This diff is collapsed.
/*
* Copyright (C) 2010-2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef FSL_FASTBOOT_H
#define FSL_FASTBOOT_H
#define FASTBOOT_PTENTRY_FLAGS_REPEAT(n) (n & 0x0f)
#define FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK 0x0000000F
/* Writes happen a block at a time.
If the write fails, go to next block
NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
#define FASTBOOT_PTENTRY_FLAGS_WRITE_NEXT_GOOD_BLOCK 0x00000010
/* Find a contiguous block big enough for a the whole file
NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
#define FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK 0x00000020
/* Write the file with write.i */
#define FASTBOOT_PTENTRY_FLAGS_WRITE_I 0x00000100
/* Write the file with write.trimffs */
#define FASTBOOT_PTENTRY_FLAGS_WRITE_TRIMFFS 0x00000200
/* Write the file as a series of variable/value pairs
using the setenv and saveenv commands */
#define FASTBOOT_PTENTRY_FLAGS_WRITE_ENV 0x00000400
#define FASTBOOT_MMC_BOOT_PARTITION_ID 1
#define FASTBOOT_MMC_USER_PARTITION_ID 0
#define FASTBOOT_MMC_NONE_PARTITION_ID -1
#define FASTBOOT_PARTITION_BOOT "boot"
#define FASTBOOT_PARTITION_RECOVERY "recovery"
#define FASTBOOT_PARTITION_SYSTEM "system"
#define FASTBOOT_PARTITION_BOOTLOADER "bootloader"
#define FASTBOOT_PARTITION_DATA "data"
enum {
DEV_SATA,
DEV_MMC,
DEV_NAND
};
struct cmd_fastboot_interface {
/* This function is called when a buffer has been
recieved from the client app.
The buffer is a supplied by the board layer and must be unmodified.
The buffer_size is how much data is passed in.
Returns 0 on success
Returns 1 on failure
Set by cmd_fastboot */
int (*rx_handler)(const unsigned char *buffer,
unsigned int buffer_size);
/* This function is called when an exception has
occurred in the device code and the state
off fastboot needs to be reset
Set by cmd_fastboot */
void (*reset_handler)(void);
/* A getvar string for the product name
It can have a maximum of 60 characters
Set by board */
char *product_name;
/* A getvar string for the serial number
It can have a maximum of 60 characters
Set by board */
char *serial_no;
/* Nand block size
Supports the write option WRITE_NEXT_GOOD_BLOCK
Set by board */
unsigned int nand_block_size;
/* Nand oob size
Set by board */
unsigned int nand_oob_size;
/* Transfer buffer, for handling flash updates
Should be multiple of the nand_block_size
Care should be take so it does not overrun bootloader memory
Controlled by the configure variable CFG_FASTBOOT_TRANSFER_BUFFER
Set by board */
unsigned char *transfer_buffer;
/* How big is the transfer buffer
Controlled by the configure variable
CFG_FASTBOOT_TRANSFER_BUFFER_SIZE
Set by board */
unsigned int transfer_buffer_size;
};
/* flash partitions are defined in terms of blocks
** (flash erase units)
*/
struct fastboot_ptentry {
/* The logical name for this partition, null terminated */
char name[16];
/* The start wrt the nand part, must be multiple of nand block size */
unsigned int start;
/* The length of the partition, must be multiple of nand block size */
unsigned int length;
/* Controls the details of how operations are done on the partition
See the FASTBOOT_PTENTRY_FLAGS_*'s defined below */
unsigned int flags;
/* partition id: 0 - normal partition; 1 - boot partition */
unsigned int partition_id;
/* partition number in block device */
unsigned int partition_index;
};
struct fastboot_device_info {
unsigned char type;
unsigned char dev_id;
};
extern struct fastboot_device_info fastboot_devinfo;
/* Prepare the fastboot environments,
* should be executed before "fastboot" cmd
*/
void fastboot_setup(void);
/* The Android-style flash handling */
/* tools to populate and query the partition table */
void fastboot_flash_add_ptn(struct fastboot_ptentry *ptn);
struct fastboot_ptentry *fastboot_flash_find_ptn(const char *name);
struct fastboot_ptentry *fastboot_flash_get_ptn(unsigned n);
unsigned int fastboot_flash_get_ptn_count(void);
void fastboot_flash_dump_ptn(void);
/* Check the board special boot mode reboot to fastboot mode. */
int fastboot_check_and_clean_flag(void);
/* Set the flag which reboot to fastboot mode*/
void fastboot_enable_flag(void);
/*check if fastboot mode is requested by user*/
void check_fastboot(void);
/*Setup board-relative fastboot environment */
void board_fastboot_setup(void);
#ifdef CONFIG_FASTBOOT_STORAGE_NAND
/*Save parameters for NAND storage partitions */
void save_parts_values(struct fastboot_ptentry *ptn,
unsigned int offset, unsigned int size);
/* Checks parameters for NAND storage partitions
* Return 1 if the parameter is not set
* Return 0 if the parameter has been set
*/
int check_parts_values(struct fastboot_ptentry *ptn);
#endif /*CONFIG_FASTBOOT_STORAGE_NAND*/
#endif /* FSL_FASTBOOT_H */
......@@ -4,6 +4,8 @@
* (C) Copyright 2000-2005
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
*
* SPDX-License-Identifier: GPL-2.0+
********************************************************************
* NOTE: This header file defines an interface to U-Boot. Including
......@@ -1238,6 +1240,8 @@ int android_image_get_kernel(const struct andr_img_hdr *hdr, int verify,
ulong *os_data, ulong *os_len);
int android_image_get_ramdisk(const struct andr_img_hdr *hdr,
ulong *rd_data, ulong *rd_len);
int android_image_get_fdt(const struct andr_img_hdr *hdr,
ulong *fdt_data, ulong *fdt_len);
ulong android_image_get_end(const struct andr_img_hdr *hdr);
ulong android_image_get_kload(const struct andr_img_hdr *hdr);
void android_print_contents(const struct andr_img_hdr *hdr);
......
/*
* Copyright (C) 2010-2016 Freescale Semiconductor, Inc. All Rights Reserved.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __RECOVERY_H_
#define __RECOVERY_H_
struct reco_envs {
char *cmd;
char *args;
};
void check_recovery_mode(void);
int recovery_check_and_clean_flag(void);
int check_recovery_cmd_file(void);
void board_recovery_setup(void);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment