Commit 0ff7e585df83470139739533bdbf41114f395470

Authored by Steve Rae
Committed by Lukasz Majewski
1 parent e1f6b0a02d

fastboot: handle flash write to GPT partitions

Implement a feature to allow fastboot to write the downloaded image
to the space reserved for the Protective MBR and the Primary GUID
Partition Table.
Additionally, prepare and write the Backup GUID Partition Table.

Signed-off-by: Steve Rae <srae@broadcom.com>
Tested-by: Lukasz Majewski <l.majewski@samsung.com>
[Test HW: Exynos4412 - Trats2]

Showing 4 changed files with 145 additions and 3 deletions Side-by-side Diff

... ... @@ -1773,6 +1773,15 @@
1773 1773 regarding the non-volatile storage device. Define this to
1774 1774 the eMMC device that fastboot should use to store the image.
1775 1775  
  1776 + CONFIG_FASTBOOT_GPT_NAME
  1777 + The fastboot "flash" command supports writing the downloaded
  1778 + image to the Protective MBR and the Primary GUID Partition
  1779 + Table. (Additionally, this downloaded image is post-processed
  1780 + to generate and write the Backup GUID Partition Table.)
  1781 + This occurs when the specified "partition name" on the
  1782 + "fastboot flash" command line matches this value.
  1783 + Default is GPT_ENTRY_NAME (currently "gpt") if undefined.
  1784 +
1776 1785 - Journaling Flash filesystem support:
1777 1786 CONFIG_JFFS2_NAND, CONFIG_JFFS2_NAND_OFF, CONFIG_JFFS2_NAND_SIZE,
1778 1787 CONFIG_JFFS2_NAND_DEV
... ... @@ -4,12 +4,17 @@
4 4 * SPDX-License-Identifier: GPL-2.0+
5 5 */
6 6  
  7 +#include <config.h>
7 8 #include <common.h>
8 9 #include <fb_mmc.h>
9 10 #include <part.h>
10 11 #include <aboot.h>
11 12 #include <sparse_format.h>
12 13  
  14 +#ifndef CONFIG_FASTBOOT_GPT_NAME
  15 +#define CONFIG_FASTBOOT_GPT_NAME GPT_ENTRY_NAME
  16 +#endif
  17 +
13 18 /* The 64 defined bytes plus the '\0' */
14 19 #define RESPONSE_LEN (64 + 1)
15 20  
... ... @@ -62,7 +67,6 @@
62 67 void fb_mmc_flash_write(const char *cmd, void *download_buffer,
63 68 unsigned int download_bytes, char *response)
64 69 {
65   - int ret;
66 70 block_dev_desc_t *dev_desc;
67 71 disk_partition_t info;
68 72  
... ... @@ -76,8 +80,24 @@
76 80 return;
77 81 }
78 82  
79   - ret = get_partition_info_efi_by_name(dev_desc, cmd, &info);
80   - if (ret) {
  83 + if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) {
  84 + printf("%s: updating MBR, Primary and Backup GPT(s)\n",
  85 + __func__);
  86 + if (is_valid_gpt_buf(dev_desc, download_buffer)) {
  87 + printf("%s: invalid GPT - refusing to write to flash\n",
  88 + __func__);
  89 + fastboot_fail("invalid GPT partition");
  90 + return;
  91 + }
  92 + if (write_mbr_and_gpt_partitions(dev_desc, download_buffer)) {
  93 + printf("%s: writing GPT partitions failed\n", __func__);
  94 + fastboot_fail("writing GPT partitions failed");
  95 + return;
  96 + }
  97 + printf("........ success\n");
  98 + fastboot_okay("");
  99 + return;
  100 + } else if (get_partition_info_efi_by_name(dev_desc, cmd, &info)) {
81 101 error("cannot find partition: '%s'\n", cmd);
82 102 fastboot_fail("cannot find partition");
83 103 return;
... ... @@ -161,6 +161,8 @@
161 161 val = le64_to_cpu(gpt_h->my_lba);
162 162 gpt_h->my_lba = gpt_h->alternate_lba;
163 163 gpt_h->alternate_lba = cpu_to_le64(val);
  164 + gpt_h->partition_entry_lba =
  165 + cpu_to_le64(le64_to_cpu(gpt_h->last_usable_lba) + 1);
164 166 gpt_h->header_crc32 = 0;
165 167  
166 168 calc_crc32 = efi_crc32((const unsigned char *)gpt_h,
... ... @@ -544,6 +546,97 @@
544 546 free(gpt_e);
545 547 free(gpt_h);
546 548 return ret;
  549 +}
  550 +
  551 +int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf)
  552 +{
  553 + gpt_header *gpt_h;
  554 + gpt_entry *gpt_e;
  555 +
  556 + /* determine start of GPT Header in the buffer */
  557 + gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
  558 + dev_desc->blksz);
  559 + if (validate_gpt_header(gpt_h, GPT_PRIMARY_PARTITION_TABLE_LBA,
  560 + dev_desc->lba))
  561 + return -1;
  562 +
  563 + /* determine start of GPT Entries in the buffer */
  564 + gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
  565 + dev_desc->blksz);
  566 + if (validate_gpt_entries(gpt_h, gpt_e))
  567 + return -1;
  568 +
  569 + return 0;
  570 +}
  571 +
  572 +int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf)
  573 +{
  574 + gpt_header *gpt_h;
  575 + gpt_entry *gpt_e;
  576 + int gpt_e_blk_cnt;
  577 + lbaint_t lba;
  578 + int cnt;
  579 +
  580 + if (is_valid_gpt_buf(dev_desc, buf))
  581 + return -1;
  582 +
  583 + /* determine start of GPT Header in the buffer */
  584 + gpt_h = buf + (GPT_PRIMARY_PARTITION_TABLE_LBA *
  585 + dev_desc->blksz);
  586 +
  587 + /* determine start of GPT Entries in the buffer */
  588 + gpt_e = buf + (le64_to_cpu(gpt_h->partition_entry_lba) *
  589 + dev_desc->blksz);
  590 + gpt_e_blk_cnt = BLOCK_CNT((le32_to_cpu(gpt_h->num_partition_entries) *
  591 + le32_to_cpu(gpt_h->sizeof_partition_entry)),
  592 + dev_desc);
  593 +
  594 + /* write MBR */
  595 + lba = 0; /* MBR is always at 0 */
  596 + cnt = 1; /* MBR (1 block) */
  597 + if (dev_desc->block_write(dev_desc->dev, lba, cnt, buf) != cnt) {
  598 + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
  599 + __func__, "MBR", cnt, lba);
  600 + return 1;
  601 + }
  602 +
  603 + /* write Primary GPT */
  604 + lba = GPT_PRIMARY_PARTITION_TABLE_LBA;
  605 + cnt = 1; /* GPT Header (1 block) */
  606 + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
  607 + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
  608 + __func__, "Primary GPT Header", cnt, lba);
  609 + return 1;
  610 + }
  611 +
  612 + lba = le64_to_cpu(gpt_h->partition_entry_lba);
  613 + cnt = gpt_e_blk_cnt;
  614 + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
  615 + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
  616 + __func__, "Primary GPT Entries", cnt, lba);
  617 + return 1;
  618 + }
  619 +
  620 + prepare_backup_gpt_header(gpt_h);
  621 +
  622 + /* write Backup GPT */
  623 + lba = le64_to_cpu(gpt_h->partition_entry_lba);
  624 + cnt = gpt_e_blk_cnt;
  625 + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_e) != cnt) {
  626 + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
  627 + __func__, "Backup GPT Entries", cnt, lba);
  628 + return 1;
  629 + }
  630 +
  631 + lba = le64_to_cpu(gpt_h->my_lba);
  632 + cnt = 1; /* GPT Header (1 block) */
  633 + if (dev_desc->block_write(dev_desc->dev, lba, cnt, gpt_h) != cnt) {
  634 + printf("%s: failed writing '%s' (%d blks at 0x" LBAF ")\n",
  635 + __func__, "Backup GPT Header", cnt, lba);
  636 + return 1;
  637 + }
  638 +
  639 + return 0;
547 640 }
548 641 #endif
549 642  
... ... @@ -244,6 +244,26 @@
244 244 */
245 245 int gpt_restore(block_dev_desc_t *dev_desc, char *str_disk_guid,
246 246 disk_partition_t *partitions, const int parts_count);
  247 +
  248 +/**
  249 + * is_valid_gpt_buf() - Ensure that the Primary GPT information is valid
  250 + *
  251 + * @param dev_desc - block device descriptor
  252 + * @param buf - buffer which contains the MBR and Primary GPT info
  253 + *
  254 + * @return - '0' on success, otherwise error
  255 + */
  256 +int is_valid_gpt_buf(block_dev_desc_t *dev_desc, void *buf);
  257 +
  258 +/**
  259 + * write_mbr_and_gpt_partitions() - write MBR, Primary GPT and Backup GPT
  260 + *
  261 + * @param dev_desc - block device descriptor
  262 + * @param buf - buffer which contains the MBR and Primary GPT info
  263 + *
  264 + * @return - '0' on success, otherwise error
  265 + */
  266 +int write_mbr_and_gpt_partitions(block_dev_desc_t *dev_desc, void *buf);
247 267 #endif
248 268  
249 269 #endif /* _PART_H */