summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/bootctrl.c339
-rw-r--r--drivers/usb/gadget/f_fastboot.c8
-rw-r--r--include/configs/mx6ul_14x14_evk_brillo.h8
-rw-r--r--include/fsl_fastboot.h2
4 files changed, 255 insertions, 102 deletions
diff --git a/drivers/usb/gadget/bootctrl.c b/drivers/usb/gadget/bootctrl.c
index 0f979f2..4d37e78 100644
--- a/drivers/usb/gadget/bootctrl.c
+++ b/drivers/usb/gadget/bootctrl.c
@@ -17,34 +17,54 @@
#include <common.h>
#include <g_dnl.h>
#include <fsl_fastboot.h>
-#include <ext_common.h>
#include "bootctrl.h"
+#include <linux/types.h>
+#include <linux/stat.h>
#define SLOT_NUM (unsigned int)2
-#define META_FILE "slotmeta.data"
-#define META_BAK_FILE ".slotmeta.data.bak"
-#define META_FILE_ABS_PATH "/slotmeta.data"
-#define META_BAK_FILE_ABS_PATH "/.slotmeta.data.bak"
+
+/* 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 {
- unsigned int priority;
- unsigned int tryremain;
- unsigned int bootsuc;
- unsigned int reserved[4];
+ u8 bootsuc:1;
+ u8 tryremain:3;
+ u8 priority:4;
};
struct boot_ctl {
- unsigned int crc;
- unsigned int recovery_tryremain;
+ char magic[4]; /* "\0FSL" */
+ u32 crc;
struct slot_meta a_slot_meta[SLOT_NUM];
- unsigned int reserved[4];
+ 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"};
+static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+
static int strcmp_l1(const char *s1, const char *s2)
{
if (!s1 || !s2)
@@ -65,11 +85,11 @@ static void dump_slotmeta(struct boot_ctl *ptbootctl)
return;
printf("RecoveryTryRemain %d, crc %u\n",
- ptbootctl->recovery_tryremain, ptbootctl->crc);
+ ptbootctl->recovery_tryremain, ptbootctl->crc);
for (i = 0; i < SLOT_NUM; i++) {
printf("slot %d: pri %d, try %d, suc %d\n", i,
- ptbootctl->a_slot_meta[i].priority,
+ ptbootctl->a_slot_meta[i].priority,
ptbootctl->a_slot_meta[i].tryremain,
ptbootctl->a_slot_meta[i].bootsuc);
}
@@ -88,11 +108,11 @@ static unsigned int slot_find(struct boot_ctl *ptbootctl)
unsigned int slot = -1;
int i;
- for (i = 0; i < SLOT_NUM; i++) {
+ for (i = 0; i < SLOT_NUM; i++) {
struct slot_meta *pslot_meta = &(ptbootctl->a_slot_meta[i]);
if ((pslot_meta->priority > max_pri) &&
- ((pslot_meta->bootsuc > 0) ||
- (pslot_meta->tryremain > 0))) {
+ ((pslot_meta->bootsuc > 0) ||
+ (pslot_meta->tryremain > 0))) {
max_pri = pslot_meta->priority;
slot = i;
printf("select_slot slot %d\n", slot);
@@ -101,112 +121,179 @@ static unsigned int slot_find(struct boot_ctl *ptbootctl)
return slot;
}
-static int read_bootctl(struct boot_ctl *ptbootctl)
+
+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 len_str[8];
+ char cnt_str[8];
char devpart_str[8];
- unsigned int crc;
- int load_count = 0;
- char *pmeta_file = META_FILE;
+ 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 (ptbootctl == NULL)
+ if (!bread && (pblock_write == NULL))
return -1;
- sprintf(len_str, "0x%x", sizeof(struct boot_ctl));
- sprintf(addr_str, "0x%x", (unsigned int)ptbootctl);
- sprintf(devpart_str, "%d:%d", g_mmc_id,
- CONFIG_ANDROID_SLOTMETA_PARTITION_MMC);
+ 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);
-load_meta:
- argv[0] = "ext4load";
+ 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] = pmeta_file;
- argv[5] = len_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_read(NULL, 0, 6, argv);
+ if (ret) {
+ free(p_block);
+ printf("do_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;
+}
- ret = do_ext4_load(NULL, 0, 5, argv);
+static int read_bootctl(struct boot_ctl *ptbootctl)
+{
+ int ret = 0;
+ unsigned int crc = 0;
+ char *p_block = NULL;
+ uint offset_in_block = 0;
+ uint blk_size = 0;
+ char *pmagic = NULL;
+
+ if (ptbootctl == NULL)
+ return -1;
+
+ ret = rw_block(true, &p_block, &blk_size, NULL);
if (ret) {
- printf("do_ext4_load %s failed, ret %d\n", pmeta_file, ret);
+ printf("read_bootctl, rw_block read failed\n");
return -1;
}
- /* check crc, if faled, load backup meta data */
- crc = crc32(0, (unsigned char *)ptbootctl + 4,
- sizeof(struct boot_ctl) - 4);
- if (crc != ptbootctl->crc) {
- printf("%s, crc check failed, caculated %d, read %d\n",
- pmeta_file, crc, ptbootctl->crc);
-
- if (load_count == 0) {
- load_count++;
- pmeta_file = META_BAK_FILE;
- printf("load backup meta %s\n", pmeta_file);
- goto load_meta;
- }
+ offset_in_block = BOOTCTRL_OFFSET%blk_size;
+ memcpy(ptbootctl, p_block + offset_in_block, sizeof(struct boot_ctl));
+
+ pmagic = ptbootctl->magic;
+ if (!((pmagic[0] == '\0') && (pmagic[1] == 'F') &&
+ (pmagic[2] == 'S') && (pmagic[3] == 'L'))) {
+ printf("magic error, %c %c %c %c\n",
+ pmagic[0], pmagic[1], pmagic[2], pmagic[3]);
+
+ free(p_block);
return -1;
}
- /* use backup meta to recover */
- if (load_count > 0) {
- printf("use backup meta to recover\n");
- argv[0] = "ext4write";
- argv[4] = META_FILE_ABS_PATH;
- do_ext4_write(NULL, 0, 6, argv);
+ /* check crc */
+ crc = crc32(0, (unsigned char *)ptbootctl + CRC_DATA_OFFSET,
+ sizeof(struct boot_ctl) - CRC_DATA_OFFSET);
+ if (crc != ptbootctl->crc) {
+ printf("crc check failed, caculated %d, read %d\n",
+ crc, ptbootctl->crc);
+
+ free(p_block);
+ return -1;
}
+ free(p_block);
return 0;
}
static int write_bootctl(struct boot_ctl *ptbootctl)
{
int ret = 0;
- char *argv[6];
- char addr_str[20];
- char len_str[8];
- char devpart_str[8];
+ char *p_block = NULL;
+ uint offset_in_block = 0;
+ uint blk_size = 0;
if (ptbootctl == NULL)
return -1;
- ptbootctl->crc = crc32(0, (unsigned char *)ptbootctl + 4,
- sizeof(struct boot_ctl) - 4);
-
- sprintf(len_str, "0x%x", sizeof(struct boot_ctl));
- sprintf(addr_str, "0x%x", (unsigned int)ptbootctl);
- sprintf(devpart_str, "%d:%d", g_mmc_id,
- CONFIG_ANDROID_SLOTMETA_PARTITION_MMC);
-
- argv[0] = "ext4write";
- argv[1] = "mmc";
- argv[2] = devpart_str;
- argv[3] = addr_str;
- argv[4] = META_FILE_ABS_PATH;
- argv[5] = len_str;
-
+ ptbootctl->crc = crc32(0, (unsigned char *)ptbootctl + CRC_DATA_OFFSET,
+ sizeof(struct boot_ctl) - CRC_DATA_OFFSET);
- /* write back t_bootctl */
- ret = do_ext4_write(NULL, 0, 6, argv);
+ ret = rw_block(true, &p_block, &blk_size, NULL);
if (ret) {
- printf("!!! do_ext4_write %s failed, ret %d\n", argv[4], ret);
- return ret;
+ printf("write_bootctl, rw_block read failed\n");
+ return -1;
}
- /* back up */
- argv[4] = META_BAK_FILE_ABS_PATH;
- ret = do_ext4_write(NULL, 0, 6, argv);
+ 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);
if (ret) {
- printf("!!! do_ext4_write %s failed, ret %d\n", argv[4], ret);
- return ret;
+ free(p_block);
+ printf("write_bootctl, rw_block write failed\n");
+ return -1;
}
- return ret;
+ free(p_block);
+ return 0;
}
-
char *select_slot(void)
{
int i = 0;
@@ -230,11 +317,11 @@ char *select_slot(void)
}
/* invalid slot, set priority to 0 */
- for (i = 0; i < SLOT_NUM; i++) {
+ for (i = 0; i < SLOT_NUM; i++) {
struct slot_meta *pslot_meta = &(t_bootctl.a_slot_meta[i]);
if ((pslot_meta->bootsuc == 0) &&
- (pslot_meta->tryremain == 0) &&
- (pslot_meta->priority > 0)) {
+ (pslot_meta->tryremain == 0) &&
+ (pslot_meta->priority > 0)) {
pslot_meta->priority = 0;
b_need_write = true;
}
@@ -246,7 +333,7 @@ char *select_slot(void)
}
if ((t_bootctl.a_slot_meta[slot].bootsuc == 0) &&
- (t_bootctl.a_slot_meta[slot].tryremain > 0)) {
+ (t_bootctl.a_slot_meta[slot].tryremain > 0)) {
b_need_write = true;
t_bootctl.a_slot_meta[slot].tryremain--;
}
@@ -280,11 +367,11 @@ static unsigned int slotidx_from_suffix(char *suffix)
bool is_sotvar(char *cmd)
{
if (!strcmp_l1("has-slot:", cmd) ||
- !strcmp_l1("slot-successful:", cmd) ||
- !strcmp_l1("slot-suffixes", cmd) ||
- !strcmp_l1("current-slot", cmd) ||
- !strcmp_l1("slot-unbootable:", cmd) ||
- !strcmp_l1("slot-retry-count:", cmd)) {
+ !strcmp_l1("slot-successful:", cmd) ||
+ !strcmp_l1("slot-suffixes", cmd) ||
+ !strcmp_l1("current-slot", cmd) ||
+ !strcmp_l1("slot-unbootable:", cmd) ||
+ !strcmp_l1("slot-retry-count:", cmd)) {
return true;
}
@@ -401,3 +488,71 @@ 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/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 400f941..3263ecc 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -169,7 +169,7 @@ enum {
#ifdef CONFIG_BRILLO_SUPPORT
PTN_KERNEL_B_INDEX,
PTN_SYSTEM_B_INDEX,
- PTN_SLOTMETA_INDEX,
+ PTN_MISC_INDEX,
#endif
PTN_NUM
};
@@ -1251,10 +1251,10 @@ static int _fastboot_parts_load_from_ptable(void)
FASTBOOT_PARTITION_SYSTEM_B,
dev_desc, ptable);
- _fastboot_parts_add_ptable_entry(PTN_SLOTMETA_INDEX,
- CONFIG_ANDROID_SLOTMETA_PARTITION_MMC,
+ _fastboot_parts_add_ptable_entry(PTN_MISC_INDEX,
+ CONFIG_ANDROID_MISC_PARTITION_MMC,
user_partition,
- FASTBOOT_PARTITION_SLOTMETA,
+ FASTBOOT_PARTITION_MISC,
dev_desc, ptable);
#else
_fastboot_parts_add_ptable_entry(PTN_KERNEL_INDEX,
diff --git a/include/configs/mx6ul_14x14_evk_brillo.h b/include/configs/mx6ul_14x14_evk_brillo.h
index 9b2f9e1..bb42c24 100644
--- a/include/configs/mx6ul_14x14_evk_brillo.h
+++ b/include/configs/mx6ul_14x14_evk_brillo.h
@@ -10,15 +10,13 @@
#define CONFIG_ANDROID_BOOT_B_PARTITION_MMC 7
#define CONFIG_ANDROID_SYSTEM_B_PARTITION_MMC 8
-#define CONFIG_ANDROID_SLOTMETA_PARTITION_MMC 9
+#define CONFIG_ANDROID_MISC_PARTITION_MMC 9
-
-#define CONFIG_CMD_EXT2
-#define CONFIG_CMD_EXT4
-#define CONFIG_CMD_EXT4_WRITE
#define CONFIG_CMD_FAT
#define CONFIG_DOS_PARTITION
#define CONFIG_SYS_BOOTM_LEN 0x1000000
+#define CONFIG_CMD_READ
+
#endif
diff --git a/include/fsl_fastboot.h b/include/fsl_fastboot.h
index 177c99a..e98913b 100644
--- a/include/fsl_fastboot.h
+++ b/include/fsl_fastboot.h
@@ -41,7 +41,7 @@
#define FASTBOOT_PARTITION_DATA "data"
#define FASTBOOT_PARTITION_BOOT_B "boot_b"
#define FASTBOOT_PARTITION_SYSTEM_B "system_b"
-#define FASTBOOT_PARTITION_SLOTMETA "slotmeta"
+#define FASTBOOT_PARTITION_MISC "misc"
#else
#define FASTBOOT_PARTITION_BOOT "boot"
#define FASTBOOT_PARTITION_RECOVERY "recovery"