mkdtimg: reuse identical FDT blobs in dtbo image
When multiple dt_table_entries uses the same FDT, do
not keep multiple copies in the output dtbo partition
image. Instead, keep dt_offset in the dt_table_entries
point to the same blob.
Update mkdtimg_testdata.sh to test the above case too.
Bug: 36792954
Test: run mkdtimg_testdata.sh
Change-Id: I3413b52e1174154d9f6146efd8cead3f50c0f256
diff --git a/utils/src/mkdtimg_core.c b/utils/src/mkdtimg_core.c
index de02b19..b8930d5 100644
--- a/utils/src/mkdtimg_core.c
+++ b/utils/src/mkdtimg_core.c
@@ -34,6 +34,9 @@
uint32_t entry_count;
uint32_t entry_offset;
uint32_t dt_offset;
+
+ char (*past_filenames)[1024];
+ uint32_t *past_dt_offsets;
};
@@ -161,11 +164,10 @@
return 0;
}
-static size_t output_img_entry(FILE *img_fp,
- size_t entry_offset, size_t dt_offset,
- const char *fdt_filename,
- struct dt_options *options) {
- size_t ret = 0;
+static int32_t output_img_entry(FILE *img_fp, size_t entry_offset,
+ size_t dt_offset, const char *fdt_filename,
+ struct dt_options *options, int reuse_fdt) {
+ int32_t ret = -1;
void *fdt = NULL;
size_t fdt_file_size;
@@ -200,11 +202,13 @@
fwrite(&entry, sizeof(entry), 1, img_fp);
/* Output FDT */
- fseek(img_fp, dt_offset, SEEK_SET);
- fwrite(fdt, fdt_file_size, 1, img_fp);
-
- /* return the fdt_file_size */
- ret = fdt_file_size;
+ if (!reuse_fdt) {
+ fseek(img_fp, dt_offset, SEEK_SET);
+ fwrite(fdt, fdt_file_size, 1, img_fp);
+ ret = fdt_file_size;
+ } else {
+ ret = 0;
+ }
end:
if (fdt) free(fdt);
@@ -215,6 +219,12 @@
struct dt_image_writer *dt_image_writer_start(FILE *img_fp, uint32_t entry_count) {
struct dt_image_writer *writer = malloc(sizeof(struct dt_image_writer));
+ if (!writer) goto error;
+ writer->past_filenames = calloc(entry_count, sizeof(*writer->past_filenames));
+ if (!writer->past_filenames) goto error;
+ writer->past_dt_offsets =
+ calloc(entry_count, sizeof(*writer->past_dt_offsets));
+ if (!writer->past_dt_offsets) goto error;
writer->img_fp = img_fp;
init_dt_global_options(&writer->global_options);
init_dt_options(&writer->entry_options);
@@ -224,6 +234,14 @@
writer->dt_offset =
writer->entry_offset + sizeof(struct dt_table_entry) * entry_count;
return writer;
+
+error:
+ fprintf(stderr, "Unable to start writer\n");
+ if (!writer) return NULL;
+ if (writer->past_filenames) free(writer->past_filenames);
+ if (writer->past_dt_offsets) free(writer->past_dt_offsets);
+ free(writer);
+ return NULL;
}
static int set_dt_options(struct dt_options *options,
@@ -270,14 +288,31 @@
return 0;
}
- uint32_t dt_size = output_img_entry(
- writer->img_fp,
- writer->entry_offset,
- writer->dt_offset,
- writer->entry_filename,
- &writer->entry_options);
- if (dt_size == 0) {
- return -1;
+ int reuse_fdt;
+ int fdt_idx;
+ uint32_t dt_offset;
+
+ for (fdt_idx = 0; writer->past_filenames[fdt_idx][0] != '\0'; fdt_idx++) {
+ if (strcmp(writer->past_filenames[fdt_idx], writer->entry_filename) == 0)
+ break;
+ }
+
+ if (writer->past_filenames[fdt_idx][0] != '\0') {
+ reuse_fdt = 1;
+ dt_offset = writer->past_dt_offsets[fdt_idx];
+ } else {
+ reuse_fdt = 0;
+ dt_offset = writer->dt_offset;
+ }
+ int32_t dt_size = output_img_entry(writer->img_fp, writer->entry_offset,
+ dt_offset, writer->entry_filename,
+ &writer->entry_options, reuse_fdt);
+ if (dt_size == -1) return -1;
+
+ if (!reuse_fdt) {
+ strncpy(writer->past_filenames[fdt_idx], writer->entry_filename,
+ sizeof(writer->past_filenames[fdt_idx]) - 1);
+ writer->past_dt_offsets[fdt_idx] = dt_offset;
}
writer->entry_offset += sizeof(struct dt_table_entry);
@@ -324,6 +359,8 @@
ret = 0;
end:
+ free(writer->past_filenames);
+ free(writer->past_dt_offsets);
free(writer);
return ret;
diff --git a/utils/tests/data/mkdtimg.cfg b/utils/tests/data/mkdtimg.cfg
index 8c0b024..3cf2a81 100644
--- a/utils/tests/data/mkdtimg.cfg
+++ b/utils/tests/data/mkdtimg.cfg
@@ -11,3 +11,6 @@
board2v1.dts.dtb
rev=0x201 # override with another value
+
+board1v1.dts.dtb
+ custom0=0xdef # override with another value
diff --git a/utils/tests/mkdtimg_testdata.sh b/utils/tests/mkdtimg_testdata.sh
index fab930d..fd0594b 100755
--- a/utils/tests/mkdtimg_testdata.sh
+++ b/utils/tests/mkdtimg_testdata.sh
@@ -6,11 +6,18 @@
board1v1_1.dts
board2v1.dts
"
+DTB_LIST=(
+ "board1v1.dts.dtb"
+ "board1v1_1.dts.dtb"
+ "board2v1.dts.dtb"
+ "board1v1.dts.dtb"
+)
CONFIG="${SRCDIR}/mkdtimg.cfg"
ALIGN=4
OUTDIR="out"
+OUTDTB_CFG="${OUTDIR}/dump_cfg.dtb"
OUTDTB="${OUTDIR}/dump.dtb"
mkdir -p "$OUTDIR"
@@ -23,14 +30,21 @@
IMG="${OUTDIR}/cfg_create.img"
mkdtimg cfg_create "$IMG" "${CONFIG}" --dtb-dir="$OUTDIR"
-mkdtimg dump "$IMG" -b "$OUTDTB" | tee "${OUTDIR}/cfg_create.dump"
+mkdtimg dump "$IMG" -b "$OUTDTB_CFG" | tee "${OUTDIR}/cfg_create.dump"
+for index in ${!DTB_LIST[@]}; do
+ diff ${OUTDIR}/${DTB_LIST[$index]} ${OUTDTB_CFG}.$index
+done
IMG="${OUTDIR}/create.img"
mkdtimg create "$IMG" \
--page_size=4096 --id=/:board_id --rev=/:board_rev --custom0=0xabc \
"${OUTDIR}/board1v1.dts.dtb" \
"${OUTDIR}/board1v1_1.dts.dtb" --id=/:another_board_id \
- "${OUTDIR}/board2v1.dts.dtb" --rev=0x201
-mkdtimg dump "$IMG" | tee "${OUTDIR}/create.dump"
+ "${OUTDIR}/board2v1.dts.dtb" --rev=0x201 \
+ "${OUTDIR}/board1v1.dts.dtb" --custom0=0xdef
+mkdtimg dump "$IMG" -b "$OUTDTB" | tee "${OUTDIR}/create.dump"
+for index in ${!DTB_LIST[@]}; do
+ diff ${OUTDIR}/${DTB_LIST[$index]} ${OUTDTB}.$index
+done
diff "${OUTDIR}/cfg_create.dump" "${OUTDIR}/create.dump"