[U-Boot] [PATCH 4/4] cmd: dtimg: Get start and size based on --id and --rev
Eugeniu Rosca
erosca at de.adit-jv.com
Fri Nov 29 19:29:19 UTC 2019
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 <erosca at 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
More information about the U-Boot
mailing list