mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-19 05:31:32 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-usb
This commit is contained in:
commit
7a7ffedabd
15 changed files with 317 additions and 105 deletions
9
README
9
README
|
@ -1773,6 +1773,15 @@ The following options need to be configured:
|
||||||
regarding the non-volatile storage device. Define this to
|
regarding the non-volatile storage device. Define this to
|
||||||
the eMMC device that fastboot should use to store the image.
|
the eMMC device that fastboot should use to store the image.
|
||||||
|
|
||||||
|
CONFIG_FASTBOOT_GPT_NAME
|
||||||
|
The fastboot "flash" command supports writing the downloaded
|
||||||
|
image to the Protective MBR and the Primary GUID Partition
|
||||||
|
Table. (Additionally, this downloaded image is post-processed
|
||||||
|
to generate and write the Backup GUID Partition Table.)
|
||||||
|
This occurs when the specified "partition name" on the
|
||||||
|
"fastboot flash" command line matches this value.
|
||||||
|
Default is GPT_ENTRY_NAME (currently "gpt") if undefined.
|
||||||
|
|
||||||
- Journaling Flash filesystem support:
|
- Journaling Flash filesystem support:
|
||||||
CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
|
CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
|
||||||
CONFIG_JFFS2_NAND_DEV
|
CONFIG_JFFS2_NAND_DEV
|
||||||
|
|
|
@ -38,10 +38,10 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||||
|
|
||||||
int controller_index = simple_strtoul(usb_controller, NULL, 0);
|
int controller_index = simple_strtoul(usb_controller, NULL, 0);
|
||||||
board_usb_init(controller_index, USB_INIT_DEVICE);
|
board_usb_init(controller_index, USB_INIT_DEVICE);
|
||||||
dfu_clear_detach();
|
g_dnl_clear_detach();
|
||||||
g_dnl_register("usb_dnl_dfu");
|
g_dnl_register("usb_dnl_dfu");
|
||||||
while (1) {
|
while (1) {
|
||||||
if (dfu_detach()) {
|
if (g_dnl_detach()) {
|
||||||
/*
|
/*
|
||||||
* Check if USB bus reset is performed after detach,
|
* Check if USB bus reset is performed after detach,
|
||||||
* which indicates that -R switch has been passed to
|
* which indicates that -R switch has been passed to
|
||||||
|
@ -74,7 +74,7 @@ done:
|
||||||
if (dfu_reset)
|
if (dfu_reset)
|
||||||
run_command("reset", 0);
|
run_command("reset", 0);
|
||||||
|
|
||||||
dfu_clear_detach();
|
g_dnl_clear_detach();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,21 @@ static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
g_dnl_clear_detach();
|
||||||
ret = g_dnl_register("usb_dnl_fastboot");
|
ret = g_dnl_register("usb_dnl_fastboot");
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (g_dnl_detach())
|
||||||
|
break;
|
||||||
if (ctrlc())
|
if (ctrlc())
|
||||||
break;
|
break;
|
||||||
usb_gadget_handle_interrupts();
|
usb_gadget_handle_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
g_dnl_unregister();
|
g_dnl_unregister();
|
||||||
|
g_dnl_clear_detach();
|
||||||
return CMD_RET_SUCCESS;
|
return CMD_RET_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,17 @@
|
||||||
* SPDX-License-Identifier: GPL-2.0+
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <fb_mmc.h>
|
#include <fb_mmc.h>
|
||||||
#include <part.h>
|
#include <part.h>
|
||||||
#include <aboot.h>
|
#include <aboot.h>
|
||||||
#include <sparse_format.h>
|
#include <sparse_format.h>
|
||||||
|
|
||||||
|
#ifndef CONFIG_FASTBOOT_GPT_NAME
|
||||||
|
#define CONFIG_FASTBOOT_GPT_NAME GPT_ENTRY_NAME
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The 64 defined bytes plus the '\0' */
|
/* The 64 defined bytes plus the '\0' */
|
||||||
#define RESPONSE_LEN (64 + 1)
|
#define RESPONSE_LEN (64 + 1)
|
||||||
|
|
||||||
|
@ -62,7 +67,6 @@ static void write_raw_image(block_dev_desc_t *dev_desc, disk_partition_t *info,
|
||||||
void fb_mmc_flash_write(const char *cmd, void *download_buffer,
|
void fb_mmc_flash_write(const char *cmd, void *download_buffer,
|
||||||
unsigned int download_bytes, char *response)
|
unsigned int download_bytes, char *response)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
block_dev_desc_t *dev_desc;
|
block_dev_desc_t *dev_desc;
|
||||||
disk_partition_t info;
|
disk_partition_t info;
|
||||||
|
|
||||||
|
@ -76,8 +80,24 @@ void fb_mmc_flash_write(const char *cmd, void *download_buffer,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = get_partition_info_efi_by_name(dev_desc, cmd, &info);
|
if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
|
||||||
if (ret) {
|
printf("%s: updating MBR, Primary and Backup GPT(s)\n",
|
||||||
|
__func__);
|
||||||
|
if (is_valid_gpt_buf(dev_desc, download_buffer)) {
|
||||||
|
printf("%s: invalid GPT - refusing to write to flash\n",
|
||||||
|
__func__);
|
||||||
|
fastboot_fail("invalid GPT partition");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
|
||||||
|
printf("%s: writing GPT partitions failed\n", __func__);
|
||||||
|
fastboot_fail("writing GPT partitions failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("........ success\n");
|
||||||
|
fastboot_okay("");
|
||||||
|
return;
|
||||||
|
} else if (get_partition_info_efi_by_name(dev_desc, cmd, &info)) {
|
||||||
error("cannot find partition: '%s'\n", cmd);
|
error("cannot find partition: '%s'\n", cmd);
|
||||||
fastboot_fail("cannot find partition");
|
fastboot_fail("cannot find partition");
|
||||||
return;
|
return;
|
||||||
|
|
268
disk/part_efi.c
268
disk/part_efi.c
|
@ -69,6 +69,107 @@ static inline int is_bootable(gpt_entry *p)
|
||||||
sizeof(efi_guid_t));
|
sizeof(efi_guid_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int validate_gpt_header(gpt_header *gpt_h, lbaint_t lba,
|
||||||
|
lbaint_t lastlba)
|
||||||
|
{
|
||||||
|
uint32_t crc32_backup = 0;
|
||||||
|
uint32_t calc_crc32;
|
||||||
|
|
||||||
|
/* Check the GPT header signature */
|
||||||
|
if (le64_to_cpu(gpt_h->signature) != GPT_HEADER_SIGNATURE) {
|
||||||
|
printf("%s signature is wrong: 0x%llX != 0x%llX\n",
|
||||||
|
"GUID Partition Table Header",
|
||||||
|
le64_to_cpu(gpt_h->signature),
|
||||||
|
GPT_HEADER_SIGNATURE);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the GUID Partition Table CRC */
|
||||||
|
memcpy(&crc32_backup, &gpt_h->header_crc32, sizeof(crc32_backup));
|
||||||
|
memset(&gpt_h->header_crc32, 0, sizeof(gpt_h->header_crc32));
|
||||||
|
|
||||||
|
calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
|
||||||
|
le32_to_cpu(gpt_h->header_size));
|
||||||
|
|
||||||
|
memcpy(&gpt_h->header_crc32, &crc32_backup, sizeof(crc32_backup));
|
||||||
|
|
||||||
|
if (calc_crc32 != le32_to_cpu(crc32_backup)) {
|
||||||
|
printf("%s CRC is wrong: 0x%x != 0x%x\n",
|
||||||
|
"GUID Partition Table Header",
|
||||||
|
le32_to_cpu(crc32_backup), calc_crc32);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the my_lba entry points to the LBA that contains the GPT
|
||||||
|
*/
|
||||||
|
if (le64_to_cpu(gpt_h->my_lba) != lba) {
|
||||||
|
printf("GPT: my_lba incorrect: %llX != " LBAF "\n",
|
||||||
|
le64_to_cpu(gpt_h->my_lba),
|
||||||
|
lba);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the first_usable_lba and that the last_usable_lba are
|
||||||
|
* within the disk.
|
||||||
|
*/
|
||||||
|
if (le64_to_cpu(gpt_h->first_usable_lba) > lastlba) {
|
||||||
|
printf("GPT: first_usable_lba incorrect: %llX > " LBAF "\n",
|
||||||
|
le64_to_cpu(gpt_h->first_usable_lba), lastlba);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (le64_to_cpu(gpt_h->last_usable_lba) > lastlba) {
|
||||||
|
printf("GPT: last_usable_lba incorrect: %llX > " LBAF "\n",
|
||||||
|
le64_to_cpu(gpt_h->last_usable_lba), lastlba);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("GPT: first_usable_lba: %llX last_usable_lba: %llX last lba: "
|
||||||
|
LBAF "\n", le64_to_cpu(gpt_h->first_usable_lba),
|
||||||
|
le64_to_cpu(gpt_h->last_usable_lba), lastlba);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int validate_gpt_entries(gpt_header *gpt_h, gpt_entry *gpt_e)
|
||||||
|
{
|
||||||
|
uint32_t calc_crc32;
|
||||||
|
|
||||||
|
/* Check the GUID Partition Table Entry Array CRC */
|
||||||
|
calc_crc32 = efi_crc32((const unsigned char *)gpt_e,
|
||||||
|
le32_to_cpu(gpt_h->num_partition_entries) *
|
||||||
|
le32_to_cpu(gpt_h->sizeof_partition_entry));
|
||||||
|
|
||||||
|
if (calc_crc32 != le32_to_cpu(gpt_h->partition_entry_array_crc32)) {
|
||||||
|
printf("%s: 0x%x != 0x%x\n",
|
||||||
|
"GUID Partition Table Entry Array CRC is wrong",
|
||||||
|
le32_to_cpu(gpt_h->partition_entry_array_crc32),
|
||||||
|
calc_crc32);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prepare_backup_gpt_header(gpt_header *gpt_h)
|
||||||
|
{
|
||||||
|
uint32_t calc_crc32;
|
||||||
|
uint64_t val;
|
||||||
|
|
||||||
|
/* recalculate the values for the Backup GPT Header */
|
||||||
|
val = le64_to_cpu(gpt_h->my_lba);
|
||||||
|
gpt_h->my_lba = gpt_h->alternate_lba;
|
||||||
|
gpt_h->alternate_lba = cpu_to_le64(val);
|
||||||
|
gpt_h->partition_entry_lba =
|
||||||
|
cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
|
||||||
|
gpt_h->header_crc32 = 0;
|
||||||
|
|
||||||
|
calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
|
||||||
|
le32_to_cpu(gpt_h->header_size));
|
||||||
|
gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EFI_PARTITION
|
#ifdef CONFIG_EFI_PARTITION
|
||||||
/*
|
/*
|
||||||
* Public Functions (include/part.h)
|
* Public Functions (include/part.h)
|
||||||
|
@ -259,7 +360,6 @@ int write_gpt_table(block_dev_desc_t *dev_desc,
|
||||||
const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
|
const int pte_blk_cnt = BLOCK_CNT((gpt_h->num_partition_entries
|
||||||
* sizeof(gpt_entry)), dev_desc);
|
* sizeof(gpt_entry)), dev_desc);
|
||||||
u32 calc_crc32;
|
u32 calc_crc32;
|
||||||
u64 val;
|
|
||||||
|
|
||||||
debug("max lba: %x\n", (u32) dev_desc->lba);
|
debug("max lba: %x\n", (u32) dev_desc->lba);
|
||||||
/* Setup the Protective MBR */
|
/* Setup the Protective MBR */
|
||||||
|
@ -284,15 +384,7 @@ int write_gpt_table(block_dev_desc_t *dev_desc,
|
||||||
!= pte_blk_cnt)
|
!= pte_blk_cnt)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
/* recalculate the values for the Backup GPT Header */
|
prepare_backup_gpt_header(gpt_h);
|
||||||
val = le64_to_cpu(gpt_h->my_lba);
|
|
||||||
gpt_h->my_lba = gpt_h->alternate_lba;
|
|
||||||
gpt_h->alternate_lba = cpu_to_le64(val);
|
|
||||||
gpt_h->header_crc32 = 0;
|
|
||||||
|
|
||||||
calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
|
|
||||||
le32_to_cpu(gpt_h->header_size));
|
|
||||||
gpt_h->header_crc32 = cpu_to_le32(calc_crc32);
|
|
||||||
|
|
||||||
if (dev_desc->block_write(dev_desc->dev,
|
if (dev_desc->block_write(dev_desc->dev,
|
||||||
(lbaint_t)le64_to_cpu(gpt_h->last_usable_lba)
|
(lbaint_t)le64_to_cpu(gpt_h->last_usable_lba)
|
||||||
|
@ -455,6 +547,97 @@ err:
|
||||||
free(gpt_h);
|
free(gpt_h);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf)
|
||||||
|
{
|
||||||
|
gpt_header *gpt_h;
|
||||||
|
gpt_entry *gpt_e;
|
||||||
|
|
||||||
|
/* determine start of GPT Header in the buffer */
|
||||||
|
gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
|
||||||
|
dev_desc->blksz);
|
||||||
|
if (validate_gpt_header(gpt_h, GPT_PRIMARY_PARTITION_TABLE_LBA,
|
||||||
|
dev_desc->lba))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* determine start of GPT Entries in the buffer */
|
||||||
|
gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
|
||||||
|
dev_desc->blksz);
|
||||||
|
if (validate_gpt_entries(gpt_h, gpt_e))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf)
|
||||||
|
{
|
||||||
|
gpt_header *gpt_h;
|
||||||
|
gpt_entry *gpt_e;
|
||||||
|
int gpt_e_blk_cnt;
|
||||||
|
lbaint_t lba;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
if (is_valid_gpt_buf(dev_desc, buf))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* determine start of GPT Header in the buffer */
|
||||||
|
gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
|
||||||
|
dev_desc->blksz);
|
||||||
|
|
||||||
|
/* determine start of GPT Entries in the buffer */
|
||||||
|
gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
|
||||||
|
dev_desc->blksz);
|
||||||
|
gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) *
|
||||||
|
le32_to_cpu(gpt_h->sizeof_partition_entry)),
|
||||||
|
dev_desc);
|
||||||
|
|
||||||
|
/* write MBR */
|
||||||
|
lba = 0; /* MBR is always at 0 */
|
||||||
|
cnt = 1; /* MBR (1 block) */
|
||||||
|
if (dev_desc->block_write(dev_desc->dev, lba, cnt, buf) != cnt) {
|
||||||
|
printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
|
||||||
|
__func__, "MBR", cnt, lba);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write Primary GPT */
|
||||||
|
lba = GPT_PRIMARY_PARTITION_TABLE_LBA;
|
||||||
|
cnt = 1; /* GPT Header (1 block) */
|
||||||
|
if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
|
||||||
|
printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
|
||||||
|
__func__, "Primary GPT Header", cnt, lba);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lba = le64_to_cpu(gpt_h->partition_entry_lba);
|
||||||
|
cnt = gpt_e_blk_cnt;
|
||||||
|
if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
|
||||||
|
printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
|
||||||
|
__func__, "Primary GPT Entries", cnt, lba);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare_backup_gpt_header(gpt_h);
|
||||||
|
|
||||||
|
/* write Backup GPT */
|
||||||
|
lba = le64_to_cpu(gpt_h->partition_entry_lba);
|
||||||
|
cnt = gpt_e_blk_cnt;
|
||||||
|
if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
|
||||||
|
printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
|
||||||
|
__func__, "Backup GPT Entries", cnt, lba);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lba = le64_to_cpu(gpt_h->my_lba);
|
||||||
|
cnt = 1; /* GPT Header (1 block) */
|
||||||
|
if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
|
||||||
|
printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
|
||||||
|
__func__, "Backup GPT Header", cnt, lba);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -511,10 +694,6 @@ static int is_pmbr_valid(legacy_mbr * mbr)
|
||||||
static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba,
|
static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba,
|
||||||
gpt_header *pgpt_head, gpt_entry **pgpt_pte)
|
gpt_header *pgpt_head, gpt_entry **pgpt_pte)
|
||||||
{
|
{
|
||||||
u32 crc32_backup = 0;
|
|
||||||
u32 calc_crc32;
|
|
||||||
u64 lastlba;
|
|
||||||
|
|
||||||
if (!dev_desc || !pgpt_head) {
|
if (!dev_desc || !pgpt_head) {
|
||||||
printf("%s: Invalid Argument(s)\n", __func__);
|
printf("%s: Invalid Argument(s)\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -527,55 +706,8 @@ static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the GPT header signature */
|
if (validate_gpt_header(pgpt_head, (lbaint_t)lba, dev_desc->lba))
|
||||||
if (le64_to_cpu(pgpt_head->signature) != GPT_HEADER_SIGNATURE) {
|
|
||||||
printf("GUID Partition Table Header signature is wrong:"
|
|
||||||
"0x%llX != 0x%llX\n",
|
|
||||||
le64_to_cpu(pgpt_head->signature),
|
|
||||||
GPT_HEADER_SIGNATURE);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the GUID Partition Table CRC */
|
|
||||||
memcpy(&crc32_backup, &pgpt_head->header_crc32, sizeof(crc32_backup));
|
|
||||||
memset(&pgpt_head->header_crc32, 0, sizeof(pgpt_head->header_crc32));
|
|
||||||
|
|
||||||
calc_crc32 = efi_crc32((const unsigned char *)pgpt_head,
|
|
||||||
le32_to_cpu(pgpt_head->header_size));
|
|
||||||
|
|
||||||
memcpy(&pgpt_head->header_crc32, &crc32_backup, sizeof(crc32_backup));
|
|
||||||
|
|
||||||
if (calc_crc32 != le32_to_cpu(crc32_backup)) {
|
|
||||||
printf("GUID Partition Table Header CRC is wrong:"
|
|
||||||
"0x%x != 0x%x\n",
|
|
||||||
le32_to_cpu(crc32_backup), calc_crc32);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that the my_lba entry points to the LBA that contains the GPT */
|
|
||||||
if (le64_to_cpu(pgpt_head->my_lba) != lba) {
|
|
||||||
printf("GPT: my_lba incorrect: %llX != %" PRIX64 "\n",
|
|
||||||
le64_to_cpu(pgpt_head->my_lba),
|
|
||||||
lba);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the first_usable_lba and last_usable_lba are within the disk. */
|
|
||||||
lastlba = (u64)dev_desc->lba;
|
|
||||||
if (le64_to_cpu(pgpt_head->first_usable_lba) > lastlba) {
|
|
||||||
printf("GPT: first_usable_lba incorrect: %llX > %" PRIX64 "\n",
|
|
||||||
le64_to_cpu(pgpt_head->first_usable_lba), lastlba);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (le64_to_cpu(pgpt_head->last_usable_lba) > lastlba) {
|
|
||||||
printf("GPT: last_usable_lba incorrect: %llX > %" PRIX64 "\n",
|
|
||||||
le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
debug("GPT: first_usable_lba: %llX last_usable_lba %llX last lba %"
|
|
||||||
PRIX64 "\n", le64_to_cpu(pgpt_head->first_usable_lba),
|
|
||||||
le64_to_cpu(pgpt_head->last_usable_lba), lastlba);
|
|
||||||
|
|
||||||
/* Read and allocate Partition Table Entries */
|
/* Read and allocate Partition Table Entries */
|
||||||
*pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
|
*pgpt_pte = alloc_read_gpt_entries(dev_desc, pgpt_head);
|
||||||
|
@ -584,17 +716,7 @@ static int is_gpt_valid(block_dev_desc_t *dev_desc, u64 lba,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check the GUID Partition Table Entry Array CRC */
|
if (validate_gpt_entries(pgpt_head, *pgpt_pte)) {
|
||||||
calc_crc32 = efi_crc32((const unsigned char *)*pgpt_pte,
|
|
||||||
le32_to_cpu(pgpt_head->num_partition_entries) *
|
|
||||||
le32_to_cpu(pgpt_head->sizeof_partition_entry));
|
|
||||||
|
|
||||||
if (calc_crc32 != le32_to_cpu(pgpt_head->partition_entry_array_crc32)) {
|
|
||||||
printf("GUID Partition Table Entry Array CRC is wrong:"
|
|
||||||
"0x%x != 0x%x\n",
|
|
||||||
le32_to_cpu(pgpt_head->partition_entry_array_crc32),
|
|
||||||
calc_crc32);
|
|
||||||
|
|
||||||
free(*pgpt_pte);
|
free(*pgpt_pte);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
static bool dfu_detach_request;
|
|
||||||
static LIST_HEAD(dfu_list);
|
static LIST_HEAD(dfu_list);
|
||||||
static int dfu_alt_num;
|
static int dfu_alt_num;
|
||||||
static int alt_num_cnt;
|
static int alt_num_cnt;
|
||||||
|
@ -39,21 +38,6 @@ __weak bool dfu_usb_get_reset(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dfu_detach(void)
|
|
||||||
{
|
|
||||||
return dfu_detach_request;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dfu_trigger_detach(void)
|
|
||||||
{
|
|
||||||
dfu_detach_request = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dfu_clear_detach(void)
|
|
||||||
{
|
|
||||||
dfu_detach_request = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dfu_find_alt_num(const char *s)
|
static int dfu_find_alt_num(const char *s)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -111,8 +95,12 @@ unsigned char *dfu_get_buf(struct dfu_entity *dfu)
|
||||||
return dfu_buf;
|
return dfu_buf;
|
||||||
|
|
||||||
s = getenv("dfu_bufsiz");
|
s = getenv("dfu_bufsiz");
|
||||||
dfu_buf_size = s ? (unsigned long)simple_strtol(s, NULL, 16) :
|
if (s)
|
||||||
CONFIG_SYS_DFU_DATA_BUF_SIZE;
|
dfu_buf_size = (unsigned long)simple_strtol(s, NULL, 0);
|
||||||
|
|
||||||
|
if (!s || !dfu_buf_size)
|
||||||
|
dfu_buf_size = CONFIG_SYS_DFU_DATA_BUF_SIZE;
|
||||||
|
|
||||||
if (dfu->max_buf_size && dfu_buf_size > dfu->max_buf_size)
|
if (dfu->max_buf_size && dfu_buf_size > dfu->max_buf_size)
|
||||||
dfu_buf_size = dfu->max_buf_size;
|
dfu_buf_size = dfu->max_buf_size;
|
||||||
|
|
||||||
|
|
|
@ -40,10 +40,16 @@ static int mmc_access_part(struct dfu_entity *dfu, struct mmc *mmc, int part)
|
||||||
static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
|
static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
|
||||||
u64 offset, void *buf, long *len)
|
u64 offset, void *buf, long *len)
|
||||||
{
|
{
|
||||||
struct mmc *mmc = find_mmc_device(dfu->data.mmc.dev_num);
|
struct mmc *mmc;
|
||||||
u32 blk_start, blk_count, n = 0;
|
u32 blk_start, blk_count, n = 0;
|
||||||
int ret, part_num_bkp = 0;
|
int ret, part_num_bkp = 0;
|
||||||
|
|
||||||
|
mmc = find_mmc_device(dfu->data.mmc.dev_num);
|
||||||
|
if (!mmc) {
|
||||||
|
error("Device MMC %d - not found!", dfu->data.mmc.dev_num);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We must ensure that we work in lba_blk_size chunks, so ALIGN
|
* We must ensure that we work in lba_blk_size chunks, so ALIGN
|
||||||
* this value.
|
* this value.
|
||||||
|
|
|
@ -1062,7 +1062,6 @@ static void usba_ep_irq(struct usba_udc *udc, struct usba_ep *ep)
|
||||||
if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
|
if ((epstatus & epctrl) & USBA_RX_BK_RDY) {
|
||||||
DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
|
DBG(DBG_BUS, "%s: RX data ready\n", ep->ep.name);
|
||||||
receive_data(ep);
|
receive_data(ep);
|
||||||
usba_ep_writel(ep, CLR_STA, USBA_RX_BK_RDY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -366,7 +366,7 @@ static int state_dfu_idle(struct f_dfu *f_dfu,
|
||||||
to_runtime_mode(f_dfu);
|
to_runtime_mode(f_dfu);
|
||||||
f_dfu->dfu_state = DFU_STATE_appIDLE;
|
f_dfu->dfu_state = DFU_STATE_appIDLE;
|
||||||
|
|
||||||
dfu_trigger_detach();
|
g_dnl_trigger_detach();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
f_dfu->dfu_state = DFU_STATE_dfuERROR;
|
f_dfu->dfu_state = DFU_STATE_dfuERROR;
|
||||||
|
|
|
@ -480,6 +480,17 @@ static void cb_boot(struct usb_ep *ep, struct usb_request *req)
|
||||||
fastboot_tx_write_str("OKAY");
|
fastboot_tx_write_str("OKAY");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req)
|
||||||
|
{
|
||||||
|
g_dnl_trigger_detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_continue(struct usb_ep *ep, struct usb_request *req)
|
||||||
|
{
|
||||||
|
fastboot_func->in_req->complete = do_exit_on_complete;
|
||||||
|
fastboot_tx_write_str("OKAY");
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_FASTBOOT_FLASH
|
#ifdef CONFIG_FASTBOOT_FLASH
|
||||||
static void cb_flash(struct usb_ep *ep, struct usb_request *req)
|
static void cb_flash(struct usb_ep *ep, struct usb_request *req)
|
||||||
{
|
{
|
||||||
|
@ -520,6 +531,9 @@ static const struct cmd_dispatch_info cmd_dispatch_info[] = {
|
||||||
}, {
|
}, {
|
||||||
.cmd = "boot",
|
.cmd = "boot",
|
||||||
.cb = cb_boot,
|
.cb = cb_boot,
|
||||||
|
}, {
|
||||||
|
.cmd = "continue",
|
||||||
|
.cb = cb_continue,
|
||||||
},
|
},
|
||||||
#ifdef CONFIG_FASTBOOT_FLASH
|
#ifdef CONFIG_FASTBOOT_FLASH
|
||||||
{
|
{
|
||||||
|
|
|
@ -205,12 +205,24 @@ static long long int download_head(unsigned long long total,
|
||||||
|
|
||||||
static int download_tail(long long int left, int cnt)
|
static int download_tail(long long int left, int cnt)
|
||||||
{
|
{
|
||||||
struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num);
|
struct dfu_entity *dfu_entity;
|
||||||
void *transfer_buffer = dfu_get_buf(dfu_entity);
|
void *transfer_buffer;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
|
debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
|
||||||
|
|
||||||
|
dfu_entity = dfu_get_entity(alt_setting_num);
|
||||||
|
if (!dfu_entity) {
|
||||||
|
error("Alt setting: %d entity not found!\n", alt_setting_num);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
transfer_buffer = dfu_get_buf(dfu_entity);
|
||||||
|
if (!transfer_buffer) {
|
||||||
|
error("Transfer buffer not allocated!");
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (left) {
|
if (left) {
|
||||||
ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++);
|
ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -163,6 +163,23 @@ __weak int g_dnl_board_usb_cable_connected(void)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool g_dnl_detach_request;
|
||||||
|
|
||||||
|
bool g_dnl_detach(void)
|
||||||
|
{
|
||||||
|
return g_dnl_detach_request;
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_dnl_trigger_detach(void)
|
||||||
|
{
|
||||||
|
g_dnl_detach_request = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void g_dnl_clear_detach(void)
|
||||||
|
{
|
||||||
|
g_dnl_detach_request = false;
|
||||||
|
}
|
||||||
|
|
||||||
static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev)
|
static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev)
|
||||||
{
|
{
|
||||||
struct usb_gadget *gadget = cdev->gadget;
|
struct usb_gadget *gadget = cdev->gadget;
|
||||||
|
|
|
@ -150,9 +150,6 @@ struct dfu_entity *dfu_get_entity(int alt);
|
||||||
char *dfu_extract_token(char** e, int *n);
|
char *dfu_extract_token(char** e, int *n);
|
||||||
void dfu_trigger_reset(void);
|
void dfu_trigger_reset(void);
|
||||||
int dfu_get_alt(char *name);
|
int dfu_get_alt(char *name);
|
||||||
bool dfu_detach(void);
|
|
||||||
void dfu_trigger_detach(void);
|
|
||||||
void dfu_clear_detach(void);
|
|
||||||
int dfu_init_env_entities(char *interface, char *devstr);
|
int dfu_init_env_entities(char *interface, char *devstr);
|
||||||
unsigned char *dfu_get_buf(struct dfu_entity *dfu);
|
unsigned char *dfu_get_buf(struct dfu_entity *dfu);
|
||||||
unsigned char *dfu_free_buf(void);
|
unsigned char *dfu_free_buf(void);
|
||||||
|
|
|
@ -39,4 +39,8 @@ int g_dnl_register(const char *s);
|
||||||
void g_dnl_unregister(void);
|
void g_dnl_unregister(void);
|
||||||
void g_dnl_set_serialnumber(char *);
|
void g_dnl_set_serialnumber(char *);
|
||||||
|
|
||||||
|
bool g_dnl_detach(void);
|
||||||
|
void g_dnl_trigger_detach(void);
|
||||||
|
void g_dnl_clear_detach(void);
|
||||||
|
|
||||||
#endif /* __G_DOWNLOAD_H_ */
|
#endif /* __G_DOWNLOAD_H_ */
|
||||||
|
|
|
@ -244,6 +244,26 @@ int gpt_fill_header(block_dev_desc_t *dev_desc, gpt_header *gpt_h,
|
||||||
*/
|
*/
|
||||||
int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
|
int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
|
||||||
disk_partition_t *partitions, const int parts_count);
|
disk_partition_t *partitions, const int parts_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is_valid_gpt_buf() - Ensure that the Primary GPT information is valid
|
||||||
|
*
|
||||||
|
* @param dev_desc - block device descriptor
|
||||||
|
* @param buf - buffer which contains the MBR and Primary GPT info
|
||||||
|
*
|
||||||
|
* @return - '0' on success, otherwise error
|
||||||
|
*/
|
||||||
|
int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write_mbr_and_gpt_partitions() - write MBR, Primary GPT and Backup GPT
|
||||||
|
*
|
||||||
|
* @param dev_desc - block device descriptor
|
||||||
|
* @param buf - buffer which contains the MBR and Primary GPT info
|
||||||
|
*
|
||||||
|
* @return - '0' on success, otherwise error
|
||||||
|
*/
|
||||||
|
int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _PART_H */
|
#endif /* _PART_H */
|
||||||
|
|
Loading…
Add table
Reference in a new issue