Currently, it is only possible to get the ${index}'s entry of a DTB/DTBO
image [*]. The "dtimg" command is agnostic on the "id" and "rev" fields
and is unable to take them as input for a more fine-grained DTB/DTBO
search/retrieval.

This is a major limitation, as users would like [**] to employ the
"id"/"rev" fields to e.g. differentiate between DTBs/DTBOs
associated to multiple HW revisions or several platforms.

Given a sample DTBO image [***], the new options work like below:

 => dtimg start 0x48000000 0 --id invalid
    Error: Bad value '--id=invalid'
 => dtimg start 0x48000000 0 --id 0x100
    Error: No #0 entry having id=0x100 && rev=0x0
 => dtimg start 0x48000000 0 --id 00779000
    0x480006ac
 => dtimg start 0x48000000 1 --id 00779000
    0x48000b46
 => dtimg start 0x48000000 2 --id 00779000
    Error: No #2 entry having id=0x779000 && rev=0x0
 => dtimg start 0x48000000 99 --id 00779000
    Error: index >= dt_entry_count (99 >= 6)
 => dtimg start 0x48000000 0
    0x480000e0
 => dtimg start 0x48000000 1
    0x480000e0
 => dtimg start 0x48000000 2
    0x480004d0
 => dtimg start 0x48000000 3
    0x480005be
 => dtimg start 0x48000000 4
    0x480006ac
 => dtimg start 0x48000000 5
    0x48000b46
 => dtimg start 0x48000000 6
    Error: index >= dt_entry_count (6 >= 6)
 => dtimg size 0x48000000 0 --id 00779000
    0x49a
 => dtimg size 0x48000000 1 --id 00779000
    0x248

[*] https://source.android.com/devices/architecture/dto/partitions
[**] https://patchwork.ozlabs.org/patch/958594/#2302310
[***] Sample/dummy DTBO image:
 => dtimg dump 0x48000000
 dt_table_header:
                magic = d7b7ab1e
           total_size = 3470
          header_size = 32
        dt_entry_size = 32
       dt_entry_count = 6
    dt_entries_offset = 32
            page_size = 4096
              version = 0
 dt_table_entry[0]:
              dt_size = 1008
            dt_offset = 224
                   id = 0b779530
                  rev = 00000000
            custom[0] = 00000000
            custom[1] = 00000000
            custom[2] = 00000000
            custom[3] = 00000000
            (FDT)size = 1008
      (FDT)compatible = (unknown)
 dt_table_entry[1]:
              dt_size = 1008
            dt_offset = 224
                   id = 0b779520
                  rev = 00000000
            custom[0] = 00000000
            custom[1] = 00000000
            custom[2] = 00000000
            custom[3] = 00000000
            (FDT)size = 1008
      (FDT)compatible = (unknown)
 dt_table_entry[2]:
              dt_size = 238
            dt_offset = 1232
                   id = 0b779530
                  rev = 00000000
            custom[0] = 00000000
            custom[1] = 00000000
            custom[2] = 00000000
            custom[3] = 00000000
            (FDT)size = 238
      (FDT)compatible = (unknown)
 dt_table_entry[3]:
              dt_size = 238
            dt_offset = 1470
                   id = 0b779520
                  rev = 00000000
            custom[0] = 00000000
            custom[1] = 00000000
            custom[2] = 00000000
            custom[3] = 00000000
            (FDT)size = 238
      (FDT)compatible = (unknown)
 dt_table_entry[4]:
              dt_size = 1178
            dt_offset = 1708
                   id = 00779000
                  rev = 00000000
            custom[0] = 00000000
            custom[1] = 00000000
            custom[2] = 00000000
            custom[3] = 00000000
            (FDT)size = 1178
      (FDT)compatible = (unknown)
 dt_table_entry[5]:
              dt_size = 584
            dt_offset = 2886
                   id = 00779000
                  rev = 00000000
            custom[0] = 00000000
            custom[1] = 00000000
            custom[2] = 00000000
            custom[3] = 00000000
            (FDT)size = 584
      (FDT)compatible = (unknown)

Signed-off-by: Eugeniu Rosca <ero...@de.adit-jv.com>
---
 cmd/dtimg.c                | 81 +++++++++++++++++++++++++++++++++++---
 common/image-android-dt.c  | 64 ++++++++++++++++++++++++++++--
 include/image-android-dt.h |  5 ++-
 3 files changed, 138 insertions(+), 12 deletions(-)

diff --git a/cmd/dtimg.c b/cmd/dtimg.c
index 5348a4ad46e8..10e909ce551b 100644
--- a/cmd/dtimg.c
+++ b/cmd/dtimg.c
@@ -7,6 +7,7 @@
 #include <env.h>
 #include <image-android-dt.h>
 #include <common.h>
+#include <linux/ctype.h>
 
 enum cmd_dtimg_info {
        CMD_DTIMG_START = 0,
@@ -48,6 +49,61 @@ static int do_dtimg_dump(cmd_tbl_t *cmdtp, int flag, int 
argc,
        return CMD_RET_SUCCESS;
 }
 
+static int dtimg_get_opthex(int *argcp, char * const *argvp[], u32 *valp)
+{
+       char *endp;
+       u32 val;
+
+       if (!argcp || !argvp || !valp)
+               return CMD_RET_FAILURE;
+
+       if (*argcp < 2) {
+               printf("Error: Option '%s' expects an argument\n", (*argvp)[0]);
+               return CMD_RET_FAILURE;
+       }
+
+       val = simple_strtoul((*argvp)[1], &endp, 16);
+       if (*endp != '\0') {
+               printf("Error: Bad value '%s=%s'\n", (*argvp)[0], (*argvp)[1]);
+               return CMD_RET_FAILURE;
+       }
+
+       *valp = val;
+       (*argcp)--;
+       (*argvp)++;
+
+       return CMD_RET_SUCCESS;
+}
+
+static int dtimg_get_opt(int argc, char * const argv[],
+                        struct dt_table_entry *ep, char **envstrp)
+{
+       if (!ep || argc < 0 || !argv || !envstrp)
+               return CMD_RET_FAILURE;
+
+       for (; argc > 0; argc--, argv++) {
+               int ret;
+
+               if (!strcmp(argv[0], "--id")) {
+                       ret = dtimg_get_opthex(&argc, &argv, &ep->id);
+                       if (ret != CMD_RET_SUCCESS)
+                               return ret;
+               } else if (!strcmp(argv[0], "--rev")) {
+                       ret = dtimg_get_opthex(&argc, &argv, &ep->rev);
+                       if (ret != CMD_RET_SUCCESS)
+                               return ret;
+               } else if (argc == 1 && argv[0][0] != '-' &&
+                          !isdigit(argv[0][0])) {
+                       *envstrp = argv[0];
+               } else {
+                       printf("Error: Option '%s' not supported\n", argv[0]);
+                       return CMD_RET_FAILURE;
+               }
+       }
+
+       return CMD_RET_SUCCESS;
+}
+
 static int dtimg_get_fdt(int argc, char * const argv[], enum cmd_dtimg_info 
cmd)
 {
        ulong hdr_addr;
@@ -55,6 +111,8 @@ static int dtimg_get_fdt(int argc, char * const argv[], enum 
cmd_dtimg_info cmd)
        char *endp;
        ulong fdt_addr;
        u32 fdt_size;
+       struct dt_table_entry entry = { 0 };
+       char *envstr = NULL;
        ulong envval;
        int ret;
 
@@ -70,7 +128,18 @@ static int dtimg_get_fdt(int argc, char * const argv[], 
enum cmd_dtimg_info cmd)
                return CMD_RET_FAILURE;
        }
 
-       if (!android_dt_get_fdt_by_index(hdr_addr, index, &fdt_addr, &fdt_size))
+       /*
+        * Consume all processed mandatory arguments.
+        * Prepare for parsing the optional ones.
+        */
+       argc -= 3;
+       argv += 3;
+
+       ret = dtimg_get_opt(argc, argv, &entry, &envstr);
+       if (ret != CMD_RET_SUCCESS)
+               return ret;
+
+       if (!android_dt_get_fdt(hdr_addr, index, &entry, &fdt_addr, &fdt_size))
                return CMD_RET_FAILURE;
 
        switch (cmd) {
@@ -85,11 +154,11 @@ static int dtimg_get_fdt(int argc, char * const argv[], 
enum cmd_dtimg_info cmd)
                return CMD_RET_FAILURE;
        }
 
-       if (argv[3]) {
-               ret = env_set_hex(argv[3], envval);
+       if (envstr) {
+               ret = env_set_hex(envstr, envval);
                if (ret)
                        printf("Error(%d) env-setting '%s=0x%lx'\n",
-                              ret, argv[3], envval);
+                              ret, envstr, envval);
        } else {
                printf("0x%lx\n", envval);
        }
@@ -111,8 +180,8 @@ static int do_dtimg_size(cmd_tbl_t *cmdtp, int flag, int 
argc,
 
 static cmd_tbl_t cmd_dtimg_sub[] = {
        U_BOOT_CMD_MKENT(dump, 2, 0, do_dtimg_dump, "", ""),
-       U_BOOT_CMD_MKENT(start, 4, 0, do_dtimg_start, "", ""),
-       U_BOOT_CMD_MKENT(size, 4, 0, do_dtimg_size, "", ""),
+       U_BOOT_CMD_MKENT(start, 8, 0, do_dtimg_start, "", ""),
+       U_BOOT_CMD_MKENT(size, 8, 0, do_dtimg_size, "", ""),
 };
 
 static int do_dtimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
diff --git a/common/image-android-dt.c b/common/image-android-dt.c
index a2d52df4a2a9..91e6b4eca23a 100644
--- a/common/image-android-dt.c
+++ b/common/image-android-dt.c
@@ -5,7 +5,6 @@
  */
 
 #include <image-android-dt.h>
-#include <dt_table.h>
 #include <common.h>
 #include <linux/libfdt.h>
 #include <mapmem.h>
@@ -38,14 +37,15 @@ bool android_dt_check_header(ulong hdr_addr)
  *
  * @return true on success or false on error
  */
-bool android_dt_get_fdt_by_index(ulong hdr_addr, u32 index, ulong *addr,
-                                u32 *size)
+bool android_dt_get_fdt(ulong hdr_addr, u32 index,
+                       struct dt_table_entry *ep, ulong *addr, u32 *size)
 {
        const struct dt_table_header *hdr;
        const struct dt_table_entry *e;
        u32 entry_count, entries_offset, entry_size;
        ulong e_addr;
-       u32 dt_offset, dt_size;
+       u32 dt_offset, dt_size, dt_id, dt_rev;
+       int i, cnt;
 
        hdr = map_sysmem(hdr_addr, sizeof(*hdr));
        entry_count = fdt32_to_cpu(hdr->dt_entry_count);
@@ -59,6 +59,62 @@ bool android_dt_get_fdt_by_index(ulong hdr_addr, u32 index, 
ulong *addr,
                return false;
        }
 
+       /*
+        * In case of a NULL dt_table_entry _or_ if both its 'id' and 'rev'
+        * fields are empty/zero, return the ${index}'th DTB/DTBO entry
+        */
+       if (!ep || (!ep->id && !ep->rev))
+               goto found;
+
+       /*
+        * - In case of non-zero value received in both 'id' and 'rev' fields,
+        *   return the ${cnt}'th DTB/DTBO entry matching both fields
+        * - In case of non-zero value received in 'id' and zero in 'rev',
+        *   return the ${cnt}'th DTB/DTBO entry matching the 'id' field only
+        * - In case of non-zero value received in 'rev' and zero in 'id',
+        *   return the ${cnt}'th DTB/DTBO entry matching the 'rev' field only
+        * In any of the above cases: 0 <= ${cnt} <= ${index} < entry_count
+        */
+       for (i = 0, cnt = -1; i < entry_count; i++) {
+               e_addr = hdr_addr + entries_offset + i * entry_size;
+               e = map_sysmem(e_addr, sizeof(*e));
+               dt_id = fdt32_to_cpu(e->id);
+               dt_rev = fdt32_to_cpu(e->rev);
+               unmap_sysmem(e);
+
+               if (ep->id && ep->rev) {
+                       if (ep->id == dt_id && ep->rev == dt_rev) {
+                               cnt++;
+                               if (cnt == index) {
+                                       index = i;
+                                       goto found;
+                               }
+                       }
+               } else if (ep->id) {
+                       if (ep->id == dt_id) {
+                               cnt++;
+                               if (cnt == index) {
+                                       index = i;
+                                       goto found;
+                               }
+                       }
+               } else if (ep->rev) {
+                       if (ep->rev == dt_rev) {
+                               cnt++;
+                               if (cnt == index) {
+                                       index = i;
+                                       goto found;
+                               }
+                       }
+               }
+       }
+
+       printf("Error: No #%d entry having id=0x%x && rev=0x%x\n",
+              index, ep->id, ep->rev);
+
+       return false;
+
+found:
        e_addr = hdr_addr + entries_offset + index * entry_size;
        e = map_sysmem(e_addr, sizeof(*e));
        dt_offset = fdt32_to_cpu(e->dt_offset);
diff --git a/include/image-android-dt.h b/include/image-android-dt.h
index 9a3aa8fa30fb..15f6115eedf0 100644
--- a/include/image-android-dt.h
+++ b/include/image-android-dt.h
@@ -8,10 +8,11 @@
 #define IMAGE_ANDROID_DT_H
 
 #include <linux/types.h>
+#include <dt_table.h>
 
 bool android_dt_check_header(ulong hdr_addr);
-bool android_dt_get_fdt_by_index(ulong hdr_addr, u32 index, ulong *addr,
-                                u32 *size);
+bool android_dt_get_fdt(ulong hdr_addr, u32 index,
+                       struct dt_table_entry *ep, ulong *addr, u32 *size);
 
 #if !defined(CONFIG_SPL_BUILD)
 void android_dt_print_contents(ulong hdr_addr);
-- 
2.24.0

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to