diff options
author | zhang sanshan <b51434@freescale.com> | 2016-04-14 12:06:34 +0800 |
---|---|---|
committer | zhang sanshan <b51434@freescale.com> | 2016-04-14 15:24:14 +0800 |
commit | a9289e4c1bfa8af172a77f24410fa0fc4276cf61 (patch) | |
tree | 56276041230e17970a85502798048dbf12190a13 /drivers | |
parent | 79d4702dd9366e478611a199ea9b7f2c2fb2bf45 (diff) | |
download | u-boot-imx-a9289e4c1bfa8af172a77f24410fa0fc4276cf61.zip u-boot-imx-a9289e4c1bfa8af172a77f24410fa0fc4276cf61.tar.gz u-boot-imx-a9289e4c1bfa8af172a77f24410fa0fc4276cf61.tar.bz2 |
MA-7633-1 [Android-SD-EMMC] enable BCB partition in android
1 Add some APIs to operate BCB/command.
2 Add action to check the command of BCB.
It can cover the case that power down when do factory-reset\ota in recovery mode.
Signed-off-by: zhang sanshan <b51434@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/bcb.c | 177 | ||||
-rw-r--r-- | drivers/usb/gadget/bcb.h | 38 | ||||
-rw-r--r-- | drivers/usb/gadget/bootctrl.c | 214 | ||||
-rw-r--r-- | drivers/usb/gadget/bootctrl.h | 24 | ||||
-rw-r--r-- | drivers/usb/gadget/command.c | 105 | ||||
-rw-r--r-- | drivers/usb/gadget/f_fastboot.c | 6 |
7 files changed, 353 insertions, 212 deletions
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 8e9732a..ad9804a 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_DFU_FUNCTION) += f_dfu.o obj-$(CONFIG_USB_GADGET_MASS_STORAGE) += f_mass_storage.o obj-$(CONFIG_CMD_FASTBOOT) += f_fastboot.o obj-$(CONFIG_BRILLO_SUPPORT) += bootctrl.o +obj-$(CONFIG_BCB_SUPPORT) += command.o bcb.o endif ifdef CONFIG_USB_ETHER obj-y += ether.o diff --git a/drivers/usb/gadget/bcb.c b/drivers/usb/gadget/bcb.c new file mode 100644 index 0000000..f6ccf91 --- /dev/null +++ b/drivers/usb/gadget/bcb.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "bcb.h" +#include "bootctrl.h" +#include <linux/stat.h> +#include <linux/types.h> +#include <common.h> +#include <g_dnl.h> +static unsigned int g_mmc_id; +void set_mmc_id(unsigned int id) +{ + g_mmc_id = id; +} +#define ALIGN_BYTES 64 /*armv7 cache line need 64 bytes aligned */ +static ulong get_block_size(char *ifname, int dev, int part) +{ + block_dev_desc_t *dev_desc = NULL; + disk_partition_t part_info; + + dev_desc = get_dev(ifname, dev); + if (dev_desc == NULL) { + printf("Block device %s %d not supported\n", ifname, dev); + return 0; + } + + if (get_partition_info(dev_desc, part, &part_info)) { + printf("Cannot find partition %d\n", part); + return 0; + } + + return part_info.blksz; +} + +static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *ep; + block_dev_desc_t *dev_desc = NULL; + int dev; + int part = 0; + disk_partition_t part_info; + ulong offset = 0u; + ulong limit = 0u; + void *addr; + uint blk; + uint cnt; + + if (argc != 6) { + cmd_usage(cmdtp); + return 1; + } + + dev = (int)simple_strtoul(argv[2], &ep, 16); + if (*ep) { + if (*ep != ':') { + printf("Invalid block device %s\n", argv[2]); + return 1; + } + part = (int)simple_strtoul(++ep, NULL, 16); + } + + dev_desc = get_dev(argv[1], dev); + if (dev_desc == NULL) { + printf("Block device %s %d not supported\n", argv[1], dev); + return 1; + } + + addr = (void *)simple_strtoul(argv[3], NULL, 16); + blk = simple_strtoul(argv[4], NULL, 16); + cnt = simple_strtoul(argv[5], NULL, 16); + + if (part != 0) { + if (get_partition_info(dev_desc, part, &part_info)) { + printf("Cannot find partition %d\n", part); + return 1; + } + offset = part_info.start; + limit = part_info.size; + } else { + /* Largest address not available in block_dev_desc_t. */ + limit = ~0; + } + + if (cnt + blk > limit) { + printf("Write out of range\n"); + return 1; + } + + if (dev_desc->block_write(dev, offset + blk, cnt, addr) < 0) { + printf("Error writing blocks\n"); + return 1; + } + + return 0; +} + +U_BOOT_CMD( + write, 6, 0, do_write, + "write binary data to a partition", + "<interface> <dev[:part]> addr blk# cnt" +); + +int rw_block(bool bread, char **ppblock, + uint *pblksize, char *pblock_write, uint offset, uint size) +{ + int ret; + char *argv[6]; + char addr_str[20]; + char cnt_str[8]; + char devpart_str[8]; + char block_begin_str[8]; + ulong blk_size = 0; + uint blk_begin = 0; + uint blk_end = 0; + uint block_cnt = 0; + char *p_block = NULL; + + if (bread && ((ppblock == NULL) || (pblksize == NULL))) + return -1; + + if (!bread && (pblock_write == NULL)) + return -1; + + blk_size = get_block_size("mmc", g_mmc_id, + CONFIG_ANDROID_MISC_PARTITION_MMC); + if (blk_size == 0) { + printf("rw_block, get_block_size return 0\n"); + return -1; + } + + blk_begin = offset/blk_size; + blk_end = (offset + size)/blk_size; + block_cnt = 1 + (blk_end - blk_begin); + + + sprintf(devpart_str, "0x%x:0x%x", g_mmc_id, + CONFIG_ANDROID_MISC_PARTITION_MMC); + sprintf(block_begin_str, "0x%x", blk_begin); + sprintf(cnt_str, "0x%x", block_cnt); + + argv[0] = "rw"; /* not care */ + argv[1] = "mmc"; + argv[2] = devpart_str; + argv[3] = addr_str; + argv[4] = block_begin_str; + argv[5] = cnt_str; + + if (bread) { + p_block = (char *)memalign(ALIGN_BYTES, blk_size * block_cnt); + if (NULL == p_block) { + printf("rw_block, memalign %d bytes failed\n", + (int)(blk_size * block_cnt)); + return -1; + } + sprintf(addr_str, "0x%x", (unsigned int)p_block); + ret = do_raw_read(NULL, 0, 6, argv); + if (ret) { + free(p_block); + printf("do_raw_read failed, ret %d\n", ret); + return -1; + } + + *ppblock = p_block; + *pblksize = (uint)blk_size; + } else { + sprintf(addr_str, "0x%x", (unsigned int)pblock_write); + ret = do_write(NULL, 0, 6, argv); + if (ret) { + printf("do_write failed, ret %d\n", ret); + return -1; + } + } + return 0; +} diff --git a/drivers/usb/gadget/bcb.h b/drivers/usb/gadget/bcb.h new file mode 100644 index 0000000..2512a7f --- /dev/null +++ b/drivers/usb/gadget/bcb.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef BCB_H +#define BCB_H +#include <linux/types.h> +#include <linux/stat.h> +/* keep same as bootable/recovery/bootloader.h */ +struct bootloader_message { + char command[32]; + char status[32]; + char recovery[768]; + + /* The 'recovery' field used to be 1024 bytes. It has only ever + been used to store the recovery command line, so 768 bytes + should be plenty. We carve off the last 256 bytes to store the + stage string (for multistage packages) and possible future + expansion. */ + char stage[32]; + char slot_suffix[32]; + char reserved[192]; +}; + +/* start from bootloader_message.slot_suffix[BOOTCTRL_IDX] */ +#define BOOTCTRL_IDX 0 +#define MISC_COMMAND_IDX 0 +#define BOOTCTRL_OFFSET \ + (u32)(&(((struct bootloader_message *)0)->slot_suffix[BOOTCTRL_IDX])) +#define MISC_COMMAND \ + (u32)(&(((struct bootloader_message *)0)->command[MISC_COMMAND_IDX])) +int rw_block(bool bread, char **ppblock, + uint *pblksize, char *pblock_write, uint offset, uint size); + +void set_mmc_id(unsigned int id); +#endif diff --git a/drivers/usb/gadget/bootctrl.c b/drivers/usb/gadget/bootctrl.c index 653c00c..21a7aee 100644 --- a/drivers/usb/gadget/bootctrl.c +++ b/drivers/usb/gadget/bootctrl.c @@ -10,46 +10,6 @@ #include "bootctrl.h" #include <linux/types.h> #include <linux/stat.h> - -#define SLOT_NUM (unsigned int)2 - -/* keep same as bootable/recovery/bootloader.h */ -struct bootloader_message { - char command[32]; - char status[32]; - char recovery[768]; - - /* The 'recovery' field used to be 1024 bytes. It has only ever - been used to store the recovery command line, so 768 bytes - should be plenty. We carve off the last 256 bytes to store the - stage string (for multistage packages) and possible future - expansion. */ - char stage[32]; - char slot_suffix[32]; - char reserved[192]; -}; - -/* start from bootloader_message.slot_suffix[BOOTCTRL_IDX] */ -#define BOOTCTRL_IDX 0 -#define BOOTCTRL_OFFSET \ - (u32)(&(((struct bootloader_message *)0)->slot_suffix[BOOTCTRL_IDX])) -#define CRC_DATA_OFFSET \ - (uint32_t)(&(((struct boot_ctl *)0)->a_slot_meta[0])) - -struct slot_meta { - u8 bootsuc:1; - u8 tryremain:3; - u8 priority:4; -}; - -struct boot_ctl { - char magic[4]; /* "\0FSL" */ - u32 crc; - struct slot_meta a_slot_meta[SLOT_NUM]; - u8 recovery_tryremain; -}; - -static unsigned int g_mmc_id; static unsigned int g_slot_selected; static const char *g_slot_suffix[SLOT_NUM] = {"_a", "_b"}; @@ -62,10 +22,6 @@ static int strcmp_l1(const char *s1, const char *s2) return strncmp(s1, s2, strlen(s1)); } -void set_mmc_id(unsigned int id) -{ - g_mmc_id = id; -} static void dump_slotmeta(struct boot_ctl *ptbootctl) { @@ -112,98 +68,7 @@ static unsigned int slot_find(struct boot_ctl *ptbootctl) return slot; } -static ulong get_block_size(char *ifname, int dev, int part) -{ - block_dev_desc_t *dev_desc = NULL; - disk_partition_t part_info; - - dev_desc = get_dev(ifname, dev); - if (dev_desc == NULL) { - printf("Block device %s %d not supported\n", ifname, dev); - return 0; - } - - if (get_partition_info(dev_desc, part, &part_info)) { - printf("Cannot find partition %d\n", part); - return 0; - } - - return part_info.blksz; -} - -#define ALIGN_BYTES 64 /*armv7 cache line need 64 bytes aligned */ -static int rw_block(bool bread, char **ppblock, - uint *pblksize, char *pblock_write) -{ - int ret; - char *argv[6]; - char addr_str[20]; - char cnt_str[8]; - char devpart_str[8]; - char block_begin_str[8]; - ulong blk_size = 0; - uint blk_begin = 0; - uint blk_end = 0; - uint block_cnt = 0; - char *p_block = NULL; - if (bread && ((ppblock == NULL) || (pblksize == NULL))) - return -1; - - if (!bread && (pblock_write == NULL)) - return -1; - - blk_size = get_block_size("mmc", g_mmc_id, - CONFIG_ANDROID_MISC_PARTITION_MMC); - if (blk_size == 0) { - printf("rw_block, get_block_size return 0\n"); - return -1; - } - - blk_begin = BOOTCTRL_OFFSET/blk_size; - blk_end = (BOOTCTRL_OFFSET + sizeof(struct boot_ctl) - 1)/blk_size; - block_cnt = 1 + (blk_end - blk_begin); - - sprintf(devpart_str, "0x%x:0x%x", g_mmc_id, - CONFIG_ANDROID_MISC_PARTITION_MMC); - sprintf(block_begin_str, "0x%x", blk_begin); - sprintf(cnt_str, "0x%x", block_cnt); - - argv[0] = "rw"; /* not care */ - argv[1] = "mmc"; - argv[2] = devpart_str; - argv[3] = addr_str; - argv[4] = block_begin_str; - argv[5] = cnt_str; - - if (bread) { - p_block = (char *)memalign(ALIGN_BYTES, blk_size * block_cnt); - if (NULL == p_block) { - printf("rw_block, memalign %d bytes failed\n", - (int)(blk_size * block_cnt)); - return -1; - } - sprintf(addr_str, "0x%x", (unsigned int)p_block); - ret = do_raw_read(NULL, 0, 6, argv); - if (ret) { - free(p_block); - printf("do_raw_read failed, ret %d\n", ret); - return -1; - } - - *ppblock = p_block; - *pblksize = (uint)blk_size; - } else { - sprintf(addr_str, "0x%x", (unsigned int)pblock_write); - ret = do_write(NULL, 0, 6, argv); - if (ret) { - printf("do_write failed, ret %d\n", ret); - return -1; - } - } - - return 0; -} static int read_bootctl(struct boot_ctl *ptbootctl) { @@ -216,8 +81,8 @@ static int read_bootctl(struct boot_ctl *ptbootctl) if (ptbootctl == NULL) return -1; - - ret = rw_block(true, &p_block, &blk_size, NULL); + ret = rw_block(true, &p_block, &blk_size, NULL, + BOOTCTRL_OFFSET, sizeof(struct boot_ctl)); if (ret) { printf("read_bootctl, rw_block read failed\n"); return -1; @@ -264,22 +129,22 @@ static int write_bootctl(struct boot_ctl *ptbootctl) ptbootctl->crc = crc32(0, (unsigned char *)ptbootctl + CRC_DATA_OFFSET, sizeof(struct boot_ctl) - CRC_DATA_OFFSET); - ret = rw_block(true, &p_block, &blk_size, NULL); + ret = rw_block(true, &p_block, &blk_size, NULL, + BOOTCTRL_OFFSET, sizeof(struct boot_ctl)); if (ret) { printf("write_bootctl, rw_block read failed\n"); return -1; } - offset_in_block = BOOTCTRL_OFFSET%blk_size; memcpy(p_block + offset_in_block, ptbootctl, sizeof(struct boot_ctl)); - ret = rw_block(false, NULL, NULL, p_block); + ret = rw_block(false, NULL, NULL, p_block, + BOOTCTRL_OFFSET, sizeof(struct boot_ctl)); if (ret) { free(p_block); printf("write_bootctl, rw_block write failed\n"); return -1; } - free(p_block); return 0; } @@ -479,70 +344,3 @@ void cb_set_active(struct usb_ep *ep, struct usb_request *req) return; } -static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *ep; - block_dev_desc_t *dev_desc = NULL; - int dev; - int part = 0; - disk_partition_t part_info; - ulong offset = 0u; - ulong limit = 0u; - void *addr; - uint blk; - uint cnt; - - if (argc != 6) { - cmd_usage(cmdtp); - return 1; - } - - dev = (int)simple_strtoul(argv[2], &ep, 16); - if (*ep) { - if (*ep != ':') { - printf("Invalid block device %s\n", argv[2]); - return 1; - } - part = (int)simple_strtoul(++ep, NULL, 16); - } - - dev_desc = get_dev(argv[1], dev); - if (dev_desc == NULL) { - printf("Block device %s %d not supported\n", argv[1], dev); - return 1; - } - - addr = (void *)simple_strtoul(argv[3], NULL, 16); - blk = simple_strtoul(argv[4], NULL, 16); - cnt = simple_strtoul(argv[5], NULL, 16); - - if (part != 0) { - if (get_partition_info(dev_desc, part, &part_info)) { - printf("Cannot find partition %d\n", part); - return 1; - } - offset = part_info.start; - limit = part_info.size; - } else { - /* Largest address not available in block_dev_desc_t. */ - limit = ~0; - } - - if (cnt + blk > limit) { - printf("Write out of range\n"); - return 1; - } - - if (dev_desc->block_write(dev, offset + blk, cnt, addr) < 0) { - printf("Error writing blocks\n"); - return 1; - } - - return 0; -} - -U_BOOT_CMD( - write, 6, 0, do_write, - "write binary data to a partition", - "<interface> <dev[:part]> addr blk# cnt" -); diff --git a/drivers/usb/gadget/bootctrl.h b/drivers/usb/gadget/bootctrl.h index 2153103..7712f75 100644 --- a/drivers/usb/gadget/bootctrl.h +++ b/drivers/usb/gadget/bootctrl.h @@ -7,11 +7,31 @@ #ifndef BOOTCTRL_H #define BOOTCTRL_H -void set_mmc_id(unsigned int id); +#include <common.h> +#include <g_dnl.h> +#include <linux/types.h> +#include <linux/stat.h> +#include "bcb.h" + +#define SLOT_NUM (unsigned int)2 +#define CRC_DATA_OFFSET \ + (uint32_t)(&(((struct boot_ctl *)0)->a_slot_meta[0])) + +struct slot_meta { + u8 bootsuc:1; + u8 tryremain:3; + u8 priority:4; +}; + +struct boot_ctl { + char magic[4]; /* "\0FSL" */ + u32 crc; + struct slot_meta a_slot_meta[SLOT_NUM]; + u8 recovery_tryremain; +}; char *select_slot(void); bool is_sotvar(char *cmd); void get_slotvar(char *cmd, char *response, size_t chars_left); void cb_set_active(struct usb_ep *ep, struct usb_request *req); const char *get_slot_suffix(void); - #endif diff --git a/drivers/usb/gadget/command.c b/drivers/usb/gadget/command.c new file mode 100644 index 0000000..3af3fcf --- /dev/null +++ b/drivers/usb/gadget/command.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <g_dnl.h> +#include "bcb.h" + +#ifndef CONFIG_FASTBOOT_STORAGE_NAND +static char command[32]; +static int read_command(char *command) +{ + int ret = 0; + char *p_block = NULL; + uint offset_in_block = 0; + uint blk_size = 0; + + if (command == NULL) + return -1; + + ret = rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); + if (ret) { + printf("read_bootctl, rw_block read failed\n"); + return -1; + } + + offset_in_block = MISC_COMMAND%blk_size; + memcpy(command, p_block + offset_in_block, 32); + + return 0; +} +static int write_command(char *bcb_command) +{ + int ret = 0; + char *p_block = NULL; + uint offset_in_block = 0; + uint blk_size = 0; + + if (bcb_command == NULL) + return -1; + + + ret = rw_block(true, &p_block, &blk_size, NULL, MISC_COMMAND, 32); + if (ret) { + printf("write_bootctl, rw_block read failed\n"); + return -1; + } + + offset_in_block = MISC_COMMAND%blk_size; + memcpy(p_block + offset_in_block, bcb_command, 32); + + ret = rw_block(false, NULL, NULL, p_block, MISC_COMMAND, 32); + if (ret) { + free(p_block); + printf("write_bootctl, rw_block write failed\n"); + return -1; + } + + free(p_block); + return 0; +} + +int recovery_check_and_clean_command(void) +{ + int ret; + ret = read_command(command); + if (ret < 0) { + printf("read command failed\n"); + return 0; + } + if (!strcmp(command, "boot-recovery")) { + memset(command, 0, 32); + write_command(command); + return 1; + } + return 0; +} +int fastboot_check_and_clean_command(void) +{ + int ret; + ret = read_command(command); + if (ret < 0) { + printf("read command failed\n"); + return 0; + } + if (!strcmp(command, "boot-bootloader")) { + memset(command, 0, 32); + write_command(command); + return 1; + } + + return 0; +} +#else +int recovery_check_and_clean_command(void) +{ + return 0; +} +int fastboot_check_and_clean_command(void) +{ + return 0; +} +#endif diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index fb2d11c..d641ebd 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -41,7 +41,9 @@ #ifdef CONFIG_BRILLO_SUPPORT #include "bootctrl.h" #endif - +#ifdef CONFIG_BCB_SUPPORT +#include "bcb.h" +#endif #define FASTBOOT_VERSION "0.4" #define FASTBOOT_INTERFACE_CLASS 0xff @@ -1099,7 +1101,7 @@ static int _fastboot_setup_dev(void) } else if (!strncmp(fastboot_env, "mmc", 3)) { fastboot_devinfo.type = DEV_MMC; fastboot_devinfo.dev_id = _fastboot_get_mmc_no(fastboot_env); -#ifdef CONFIG_BRILLO_SUPPORT +#ifdef CONFIG_BCB_SUPPORT set_mmc_id(fastboot_devinfo.dev_id); #endif } |