From: Fabien Parent <[email protected]>

Add support for generating images that can boot on UFS storage for
MediaTek SoCs.

The UFS device header is 4 KiB instead of 1.5 KiB, and the size field
of its generic boot header covers the whole device header.

Signed-off-by: Fabien Parent <[email protected]>
[dlechner: rebase, fix header size check when verifying, document the
 ufs media type, use mtk_image_verify_gfh()]
Signed-off-by: David Lechner <[email protected]>
---
 doc/README.mediatek |  1 +
 tools/mtk_image.c   | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/mtk_image.h   | 16 +++++++--
 3 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/doc/README.mediatek b/doc/README.mediatek
index 246579d4be2..d38709408b7 100644
--- a/doc/README.mediatek
+++ b/doc/README.mediatek
@@ -107,6 +107,7 @@ To generate these two headers with mkimage:
                nor  : Serial NOR
                emmc : eMMC
                sdmmc: SD
+               ufs  : UFS
 
           nandinfo: Desired NAND device type, a combination of page size, oob 
size and
                     optional device capacity. Valid types are:
diff --git a/tools/mtk_image.c b/tools/mtk_image.c
index 1b1aed59924..ac9c86df6bd 100644
--- a/tools/mtk_image.c
+++ b/tools/mtk_image.c
@@ -36,6 +36,9 @@ static const struct brom_img_type {
        }, {
                .name = "spim-nand",
                .type = BRLYT_TYPE_SNAND
+       }, {
+               .name = "ufs",
+               .type = BRLYT_TYPE_UFS
        }
 };
 
@@ -262,6 +265,8 @@ static int mtk_image_vrec_header(struct image_tool_params 
*params,
 
        if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
                tparams->header_size = hdr_nand_size;
+       else if (hdr_media == BRLYT_TYPE_UFS)
+               tparams->header_size = sizeof(struct ufs_device_header);
        else
                tparams->header_size = sizeof(struct gen_device_header);
 
@@ -357,6 +362,65 @@ static int mtk_image_verify_gen_header(const uint8_t *ptr, 
int print)
        return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print);
 }
 
+static int mtk_image_verify_ufs_header(const uint8_t *ptr, int print)
+{
+       union gen_boot_header *gbh = (union gen_boot_header *)ptr;
+       uint32_t gfh_offset, total_size, devh_size;
+       struct brom_layout_header *bh;
+       struct gfh_header *gfh;
+       const char *bootmedia;
+
+       if (!strcmp(gbh->name, UFS_BOOT_NAME))
+               bootmedia = "UFS";
+       else
+               return -1;
+
+       if (print)
+               printf("Boot Media:   %s\n", bootmedia);
+
+       devh_size = sizeof(struct ufs_device_header);
+
+       if (le32_to_cpu(gbh->version) != 1 ||
+           le32_to_cpu(gbh->size) != devh_size)
+               return -1;
+
+       bh = (struct brom_layout_header *)(ptr + sizeof(union gen_boot_header));
+
+       if (strcmp(bh->name, BRLYT_NAME))
+               return -1;
+
+       if (le32_to_cpu(bh->magic) != BRLYT_MAGIC ||
+           le32_to_cpu(bh->type) != BRLYT_TYPE_UFS)
+               return -1;
+
+       if (img_gen) {
+               gfh_offset = devh_size;
+       } else {
+               gfh_offset = le32_to_cpu(bh->header_size);
+
+               if (gfh_offset + sizeof(struct gfh_header) > img_size) {
+                       /*
+                        * This may happen if the hdr_offset used to generate
+                        * this image is not zero.
+                        * Since device header size is not fixed, we can't
+                        * cover all possible cases.
+                        * Assuming the image is valid only if the real
+                        * device header size equals to devh_size.
+                        */
+                       total_size = le32_to_cpu(bh->total_size);
+
+                       if (total_size - gfh_offset > img_size - devh_size)
+                               return -1;
+
+                       gfh_offset = devh_size;
+               }
+       }
+
+       gfh = (struct gfh_header *)(ptr + gfh_offset);
+
+       return mtk_image_verify_gfh(gfh, GFH_FLASH_TYPE_GEN, print);
+}
+
 static int mtk_image_verify_nand_header(const uint8_t *ptr, int print)
 {
        struct brom_layout_header *bh;
@@ -504,6 +568,8 @@ static int mtk_image_verify_header(unsigned char *ptr, int 
image_size,
 
        if (is_mtk_nand_header(ptr))
                return mtk_image_verify_nand_header(ptr, 0);
+       else if (!strcmp((char *)ptr, UFS_BOOT_NAME))
+               return mtk_image_verify_ufs_header(ptr, 0);
        else
                return mtk_image_verify_gen_header(ptr, 0);
 
@@ -530,6 +596,8 @@ static void mtk_image_print_header(const void *ptr, struct 
image_tool_params *pa
 
        if (is_mtk_nand_header(ptr))
                mtk_image_verify_nand_header(ptr, 1);
+       else if (!strcmp((char *)ptr, UFS_BOOT_NAME))
+               mtk_image_verify_ufs_header(ptr, 1);
        else
                mtk_image_verify_gen_header(ptr, 1);
 }
@@ -658,6 +726,33 @@ static void mtk_image_set_gen_header(void *ptr, off_t 
filesize,
                 filesize - sizeof(struct gen_device_header) - SHA256_SUM_LEN);
 }
 
+static void mtk_image_set_ufs_header(void *ptr, off_t filesize,
+                                    uint32_t loadaddr)
+{
+       struct ufs_device_header *hdr = (struct ufs_device_header *)ptr;
+       struct gfh_header *gfh;
+
+       /* Generic device header */
+       snprintf(hdr->boot.name, sizeof(hdr->boot.name), "%s", UFS_BOOT_NAME);
+       hdr->boot.version = cpu_to_le32(1);
+       hdr->boot.size = cpu_to_le32(sizeof(*hdr));
+
+       /* BRLYT header */
+       put_brom_layout_header(&hdr->brlyt, hdr_media);
+       hdr->brlyt.header_size = cpu_to_le32(hdr_offset + sizeof(*hdr));
+       hdr->brlyt.total_size = cpu_to_le32(hdr_offset + filesize);
+       hdr->brlyt.header_size_2 = hdr->brlyt.header_size;
+       hdr->brlyt.total_size_2 = hdr->brlyt.total_size;
+
+       /* GFH header */
+       gfh = (struct gfh_header *)(ptr + sizeof(*hdr));
+       put_ghf_header(gfh, filesize, sizeof(*hdr),
+                      loadaddr, GFH_FLASH_TYPE_GEN);
+
+       /* Generate SHA256 hash */
+       put_hash((uint8_t *)gfh, filesize - sizeof(*hdr) - SHA256_SUM_LEN);
+}
+
 static void mtk_image_set_nand_header(void *ptr, off_t filesize,
                                      uint32_t loadaddr)
 {
@@ -754,6 +849,8 @@ static void mtk_image_set_header(void *ptr, struct stat 
*sbuf, int ifd,
 
        if (hdr_media == BRLYT_TYPE_NAND || hdr_media == BRLYT_TYPE_SNAND)
                mtk_image_set_nand_header(ptr, sbuf->st_size, params->addr);
+       else if (hdr_media == BRLYT_TYPE_UFS)
+               mtk_image_set_ufs_header(ptr, sbuf->st_size, params->addr);
        else
                mtk_image_set_gen_header(ptr, sbuf->st_size, params->addr);
 }
diff --git a/tools/mtk_image.h b/tools/mtk_image.h
index 54a838de863..8b4a601aec6 100644
--- a/tools/mtk_image.h
+++ b/tools/mtk_image.h
@@ -11,7 +11,7 @@
 
 /* Device header definitions, all fields are little-endian */
 
-/* Header for NOR/SD/eMMC */
+/* Header for NOR/SD/eMMC/UFS */
 union gen_boot_header {
        struct {
                char name[12];
@@ -25,6 +25,7 @@ union gen_boot_header {
 #define EMMC_BOOT_NAME         "EMMC_BOOT"
 #define SF_BOOT_NAME           "SF_BOOT"
 #define SDMMC_BOOT_NAME                "SDMMC_BOOT"
+#define UFS_BOOT_NAME          "UFS_BOOT"
 
 /* BootROM layout header */
 struct brom_layout_header {
@@ -48,7 +49,8 @@ enum brlyt_img_type {
        BRLYT_TYPE_EMMC = 0x10005,
        BRLYT_TYPE_NOR = 0x10007,
        BRLYT_TYPE_SDMMC = 0x10008,
-       BRLYT_TYPE_SNAND = 0x10009
+       BRLYT_TYPE_SNAND = 0x10009,
+       BRLYT_TYPE_UFS = 0x1000c
 };
 
 /* Combined device header for NOR/SD/eMMC */
@@ -61,6 +63,16 @@ struct gen_device_header {
        };
 };
 
+/* Device header for UFS */
+struct ufs_device_header {
+       union gen_boot_header boot;
+
+       union {
+               struct brom_layout_header brlyt;
+               uint8_t brlyt_pad[0xE00];
+       };
+};
+
 /* BootROM header definitions */
 struct gfh_common_header {
        uint32_t magic_version;

-- 
2.53.0

Reply via email to