summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt6
-rw-r--r--packaging/system-tools.spec33
-rw-r--r--src/dtbtool/CMakeLists.txt9
-rwxr-xr-xsrc/dtbtool/dtbtool.c703
-rw-r--r--src/mkdzimage/CMakeLists.txt9
-rw-r--r--src/mkdzimage/dzimage.h35
-rw-r--r--src/mkdzimage/mkdzimage.c189
7 files changed, 984 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..bf70f59
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,6 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+MESSAGE("build system tools")
+
+ADD_SUBDIRECTORY(src/dtbtool)
+ADD_SUBDIRECTORY(src/mkdzimage)
diff --git a/packaging/system-tools.spec b/packaging/system-tools.spec
new file mode 100644
index 0000000..c933f9d
--- /dev/null
+++ b/packaging/system-tools.spec
@@ -0,0 +1,33 @@
+Name: system-tools
+Version: 0.0.1
+Release: 0
+Summary: Tizen kernel and system tools
+Group: libs
+License: Qualcomm Proprietary License
+Source0: %{name}-%{version}.tar.gz
+BuildRequires: cmake
+
+%if "%{?tizen_profile_name}" == "tv"
+ExcludeArch: %{arm} %ix86 x86_64
+%endif
+
+%description
+System tools includes all application related with Tizen kernel
+
+%prep
+%setup -q
+
+%build
+export LDFLAGS+="-Wl,--rpath=%{_prefix}/lib -Wl,--as-needed"
+LDFLAGS="$LDFLAGS" cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
+make
+
+%install
+
+%make_install
+
+%files
+%defattr(-,root,root,-)
+%{_bindir}/dtbtool
+%{_bindir}/mkdzimage
diff --git a/src/dtbtool/CMakeLists.txt b/src/dtbtool/CMakeLists.txt
new file mode 100644
index 0000000..f27dff1
--- /dev/null
+++ b/src/dtbtool/CMakeLists.txt
@@ -0,0 +1,9 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(dtbtool C)
+
+SET(DTBTOOL "dtbtool")
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ DTBSRCS)
+
+ADD_EXECUTABLE(${DTBTOOL} ${DTBSRCS})
+
+INSTALL(TARGETS ${DTBTOOL} DESTINATION bin)
diff --git a/src/dtbtool/dtbtool.c b/src/dtbtool/dtbtool.c
new file mode 100755
index 0000000..f676ec3
--- /dev/null
+++ b/src/dtbtool/dtbtool.c
@@ -0,0 +1,703 @@
+/*
+ * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _GNU_SOURCE
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <errno.h>
+#include <unistd.h>
+
+#define QCDT 0
+#define QCDT_MAGIC "QCDT" /* Master DTB magic */
+#define QCDT_VERSION 1 /* QCDT version */
+#define QCDT_DT_TAG "qcom,msm-id = <"
+
+#define SPRD 1
+#define SPRD_MAGIC "SPRD" /* Master DTB magic */
+#define SPRD_VERSION 1 /* SPRD version */
+#define SPRD_DT_TAG "sprd,sc-id = <"
+
+#define EXYNOS 2
+#define EXYNOS_MAGIC "EXYN" /* Master DTB magic */
+#define EXYNOS_VERSION 1 /* EXYNOS version */
+#define EXYNOS_DT_TAG "samsung,exynos-id = <"
+
+#define PAGE_SIZE_DEF 2048
+#define PAGE_SIZE_MAX (1024*1024)
+
+#define log_err(x...) printf(x)
+#define log_info(x...) printf(x)
+#define log_dbg(x...) { if (verbose) printf(x); }
+
+#define COPY_BLK 1024 /* File copy block size */
+
+#define RC_SUCCESS 0
+#define RC_ERROR -1
+
+struct chipInfo_t {
+ uint32_t chipset;
+ uint32_t platform;
+ uint32_t revNum;
+ uint32_t dtb_size;
+ char *dtb_file;
+ struct chipInfo_t *prev;
+ struct chipInfo_t *next;
+ struct chipInfo_t *master;
+ int wroteDtb;
+ uint32_t master_offset;
+ struct chipInfo_t *t_next;
+};
+
+struct chipInfo_t *chip_list;
+
+char *input_dir;
+char *output_file;
+char *dtc_path;
+int verbose;
+int page_size = PAGE_SIZE_DEF;
+
+void print_help()
+{
+ log_info("dtbTool [options] -o <output file> <input DTB path>\n");
+ log_info(" options:\n");
+ log_info(" --output-file/-o output file\n");
+ log_info(" --dtc-path/-p path to dtc\n");
+ log_info(" --page-size/-s page size in bytes\n");
+ log_info(" --verbose/-v verbose\n");
+ log_info(" --help/-h this help screen\n");
+}
+
+int parse_commandline(int argc, char *const argv[])
+{
+ int c;
+
+ struct option long_options[] = {
+ {"output-file", 1, 0, 'o'},
+ {"dtc-path", 1, 0, 'p'},
+ {"page-size", 1, 0, 's'},
+ {"verbose", 0, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ while ((c = getopt_long(argc, argv, "-o:p:s:vh", long_options, NULL))
+ != -1) {
+ switch (c) {
+ case 1:
+ if (!input_dir)
+ input_dir = optarg;
+ break;
+ case 'o':
+ output_file = optarg;
+ break;
+ case 'p':
+ dtc_path = optarg;
+ break;
+ case 's':
+ page_size = atoi(optarg);
+ if ((page_size <= 0) || (page_size > (PAGE_SIZE_MAX))) {
+ log_err("Invalid page size (> 0 and <=1MB\n");
+ return RC_ERROR;
+ }
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'h':
+ default:
+ return RC_ERROR;
+ }
+ }
+
+ if (!output_file) {
+ log_err("Output file must be specified\n");
+ return RC_ERROR;
+ }
+
+ if (!input_dir)
+ input_dir = "./";
+
+ if (!dtc_path)
+ dtc_path = "";
+
+ return RC_SUCCESS;
+}
+
+/* Unique entry sorted list add (by chipset->platform->rev) */
+int chip_add(struct chipInfo_t *c)
+{
+ struct chipInfo_t *x = chip_list;
+
+ if (!chip_list) {
+ chip_list = c;
+ c->next = NULL;
+ c->prev = NULL;
+ return RC_SUCCESS;
+ }
+
+ while (1) {
+ if ((c->chipset < x->chipset) ||
+ ((c->chipset == x->chipset) &&
+ ((c->platform < x->platform) ||
+ ((c->platform == x->platform) &&
+ (c->revNum < x->revNum))))) {
+ if (!x->prev) {
+ c->next = x;
+ c->prev = NULL;
+ x->prev = c;
+ chip_list = c;
+ break;
+ } else {
+ c->next = x;
+ c->prev = x->prev;
+ x->prev->next = c;
+ x->prev = c;
+ break;
+ }
+ }
+ if ((c->chipset == x->chipset) &&
+ (c->platform == x->platform) &&
+ (c->revNum == x->revNum)) {
+ return RC_ERROR; /* duplicate */
+ }
+ if (!x->next) {
+ c->prev = x;
+ c->next = NULL;
+ x->next = c;
+ break;
+ }
+ x = x->next;
+ }
+ return RC_SUCCESS;
+}
+
+void chip_deleteall()
+{
+ struct chipInfo_t *c = chip_list, *t;
+
+ while (c) {
+ t = c;
+ c = c->next;
+ if (t->dtb_file)
+ free(t->dtb_file);
+ free(t);
+ }
+}
+
+/* Extract 'qcom,msm-id' or 'sprd,sc-id' or 'exynos,exynos-id'parameter triplet from DTB
+ qcom,msm-id = <x y z>;
+ sprd,sc-id = <x y z>;
+ exynos,exynos-id = <x y z>;
+ */
+struct chipInfo_t *getChipInfo(const char *filename, int *num, int *dt_type)
+{
+ const char str1[] = "dtc -I dtb -O dts \"";
+ const char str2[] = "\" 2>&1";
+ char *buf, *pos;
+ char *line = NULL;
+ size_t line_size;
+ FILE *pfile;
+ int llen;
+ struct chipInfo_t *chip = NULL, *tmp;
+ uint32_t data[3] = {0, 0, 0};
+ char *tok, *sptr = NULL;
+ int i, count = 0, entryValid, entryEnded;
+
+ line_size = 1024;
+ line = (char *)malloc(line_size);
+ if (!line) {
+ log_err("Out of memory\n");
+ return NULL;
+ }
+
+ llen = sizeof(char) * (strlen(dtc_path) +
+ strlen(str1) +
+ strlen(str2) +
+ strlen(filename) + 1);
+ buf = (char *)malloc(llen);
+ if (!buf) {
+ log_err("Out of memory\n");
+ free(line);
+ return NULL;
+ }
+
+ strncpy(buf, dtc_path, llen);
+ strncat(buf, str1, llen);
+ strncat(buf, filename, llen);
+ strncat(buf, str2, llen);
+
+ pfile = popen(buf, "r");
+ free(buf);
+
+ if (pfile == NULL) {
+ log_err("... skip, fail to decompile dtb\n");
+ } else {
+ /* Find "qcom,msm-id" or "sprd,sc-id" or "exynos,exynos-id" */
+ while ((llen = getline(&line, &line_size, pfile)) != -1) {
+ if ((pos = strstr(line, QCDT_DT_TAG)) != NULL) {
+ *dt_type = QCDT;
+ pos += strlen(QCDT_DT_TAG);
+
+ entryEnded = 0;
+ while (1) {
+ entryValid = 1;
+ for (i = 0; i < 3; i++) {
+ tok = strtok_r(pos, " \t", &sptr);
+ pos = NULL;
+ if (tok != NULL) {
+ if (*tok == '>') {
+ entryEnded = 1;
+ entryValid = 0;
+ break;
+ }
+ data[i] = strtoul(tok, NULL, 0);
+ } else {
+ data[i] = 0;
+ entryValid = 0;
+ entryEnded = 1;
+ }
+ }
+ if (entryEnded) {
+ free(line);
+ pclose(pfile);
+ *num = count;
+ return chip;
+ }
+ if (entryValid) {
+ tmp = (struct chipInfo_t *)
+ malloc(sizeof(struct chipInfo_t));
+ if (!tmp) {
+ log_err("Out of memory\n");
+ break;
+ }
+ if (!chip) {
+ chip = tmp;
+ chip->t_next = NULL;
+ } else {
+ tmp->t_next = chip->t_next;
+ chip->t_next = tmp;
+ }
+ tmp->chipset = data[0];
+ tmp->platform = data[1];
+ tmp->revNum = data[2];
+ tmp->dtb_size = 0;
+ tmp->dtb_file = NULL;
+ tmp->master = chip;
+ tmp->wroteDtb = 0;
+ tmp->master_offset = 0;
+ count++;
+ }
+ }
+
+ log_err("... skip, incorrect '%s' format\n", QCDT_DT_TAG);
+ break;
+ }else if ((pos = strstr(line, SPRD_DT_TAG)) != NULL) {
+ *dt_type = SPRD;
+ pos += strlen(SPRD_DT_TAG);
+
+ entryEnded = 0;
+ while (1) {
+ entryValid = 1;
+ for (i = 0; i < 3; i++) {
+ tok = strtok_r(pos, " \t", &sptr);
+ pos = NULL;
+ if (tok != NULL) {
+ if (*tok == '>') {
+ entryEnded = 1;
+ entryValid = 0;
+ break;
+ }
+ data[i] = strtoul(tok, NULL, 0);
+ } else {
+ data[i] = 0;
+ entryValid = 0;
+ entryEnded = 1;
+ }
+ }
+ if (entryEnded) {
+ free(line);
+ pclose(pfile);
+ *num = count;
+ return chip;
+ }
+ if (entryValid) {
+ tmp = (struct chipInfo_t *)
+ malloc(sizeof(struct chipInfo_t));
+ if (!tmp) {
+ log_err("Out of memory\n");
+ break;
+ }
+ if (!chip) {
+ chip = tmp;
+ chip->t_next = NULL;
+ } else {
+ tmp->t_next = chip->t_next;
+ chip->t_next = tmp;
+ }
+ tmp->chipset = data[0];
+ tmp->platform = data[1];
+ tmp->revNum = data[2];
+ tmp->dtb_size = 0;
+ tmp->dtb_file = NULL;
+ tmp->master = chip;
+ tmp->wroteDtb = 0;
+ tmp->master_offset = 0;
+ count++;
+ }
+ }
+
+ log_err("... skip, incorrect '%s' format\n", SPRD_DT_TAG);
+ break;
+ } else if ((pos = strstr(line, EXYNOS_DT_TAG)) != NULL) {
+ *dt_type = EXYNOS;
+ pos += strlen(EXYNOS_DT_TAG);
+
+ entryEnded = 0;
+ while (1) {
+ entryValid = 1;
+ for (i = 0; i < 3; i++) {
+ tok = strtok_r(pos, " \t", &sptr);
+ pos = NULL;
+ if (tok != NULL) {
+ if (*tok == '>') {
+ entryEnded = 1;
+ entryValid = 0;
+ break;
+ }
+ data[i] = strtoul(tok, NULL, 0);
+ } else {
+ data[i] = 0;
+ entryValid = 0;
+ entryEnded = 1;
+ }
+ }
+ if (entryEnded) {
+ free(line);
+ pclose(pfile);
+ *num = count;
+ return chip;
+ }
+ if (entryValid) {
+ tmp = (struct chipInfo_t *)
+ malloc(sizeof(struct chipInfo_t));
+ if (!tmp) {
+ log_err("Out of memory\n");
+ break;
+ }
+ if (!chip) {
+ chip = tmp;
+ chip->t_next = NULL;
+ } else {
+ tmp->t_next = chip->t_next;
+ chip->t_next = tmp;
+ }
+ tmp->chipset = data[0];
+ tmp->platform = data[1];
+ tmp->revNum = data[2];
+ tmp->dtb_size = 0;
+ tmp->dtb_file = NULL;
+ tmp->master = chip;
+ tmp->wroteDtb = 0;
+ tmp->master_offset = 0;
+ count++;
+ }
+ }
+
+ log_err("... skip, incorrect '%s' format\n", EXYNOS_DT_TAG);
+ break;
+ }
+ }
+
+ pclose(pfile);
+ }
+
+ if (line)
+ free(line);
+
+ return NULL;
+}
+
+int main(int argc, char **argv)
+{
+ char buf[COPY_BLK];
+ struct chipInfo_t *chip, *t_chip;
+ struct dirent *dp;
+ FILE *pInputFile;
+ char *filename;
+ int padding;
+ uint8_t *filler = NULL;
+ int numBytesRead = 0;
+ int totBytesRead = 0;
+ int out_fd;
+ int flen;
+ int dt_type = QCDT;
+ int rc = RC_SUCCESS;
+ int dtb_count = 0, dtb_offset = 0;
+ size_t wrote = 0, expected = 0;
+ struct stat st;
+ uint32_t magic, version;
+ int num;
+ uint32_t dtb_size;
+
+ log_info("DTB combiner:\n");
+
+ if (parse_commandline(argc, argv) != RC_SUCCESS) {
+ print_help();
+ return RC_ERROR;
+ }
+
+ log_info(" Input directory: '%s'\n", input_dir);
+ log_info(" Output file: '%s'\n", output_file);
+
+ DIR *dir = opendir(input_dir);
+ if (!dir) {
+ log_err("Failed to open input directory '%s'\n", input_dir);
+ return RC_ERROR;
+ }
+
+ filler = (uint8_t *)malloc(page_size);
+ if (!filler) {
+ log_err("Out of memory\n");
+ closedir(dir);
+ return RC_ERROR;
+ }
+ memset(filler, 0, page_size);
+
+ /* Open the .dtb files in the specified path, decompile and
+ extract "qcom,msm-id" or "sprd,sc-id" or "exynos,exynos-id" parameter
+ */
+ while ((dp = readdir(dir)) != NULL) {
+ if ((dp->d_type == DT_REG)) {
+ flen = strlen(dp->d_name);
+ if ((flen > 4) &&
+ (strncmp(&dp->d_name[flen-4], ".dtb", 4) == 0)) {
+ log_info("Found file: %s ... \n", dp->d_name);
+
+ flen = strlen(input_dir) + strlen(dp->d_name) + 1;
+ filename = (char *)malloc(flen);
+ if (!filename) {
+ log_err("Out of memory\n");
+ rc = RC_ERROR;
+ break;
+ }
+ strncpy(filename, input_dir, flen);
+ strncat(filename, dp->d_name, flen);
+
+ num = 1;
+ chip = getChipInfo(filename, &num, &dt_type);
+ if (!chip) {
+ log_err("skip, failed to scan for '%s' or '%s' or '%s' tag\n",
+ QCDT_DT_TAG, SPRD_DT_TAG, EXYNOS_DT_TAG);
+ free(filename);
+ continue;
+ }
+
+ if ((stat(filename, &st) != 0) ||
+ (st.st_size == 0)) {
+ log_err("skip, failed to get DTB size\n");
+ free(filename);
+ continue;
+ }
+
+ log_info("chipset: 0x%x, platform: %u, rev: %u\n",
+ chip->chipset, chip->platform, chip->revNum);
+
+ for (t_chip = chip->t_next; t_chip; t_chip = t_chip->t_next) {
+ log_info(" additional chipset: %u, platform: %u, rev: %u\n",
+ t_chip->chipset, t_chip->platform, t_chip->revNum);
+ }
+
+ rc = chip_add(chip);
+ if (rc != RC_SUCCESS) {
+ log_err("... duplicate info, skipped\n");
+ free(filename);
+ continue;
+ }
+
+ dtb_count++;
+
+ chip->dtb_size = st.st_size +
+ (page_size - (st.st_size % page_size));
+ chip->dtb_file = filename;
+
+ for (t_chip = chip->t_next; t_chip; t_chip = t_chip->t_next) {
+ rc = chip_add(t_chip);
+ if (rc != RC_SUCCESS) {
+ log_err("... duplicate info, skipped (chipset %u, platform: %u, rev: %u\n",
+ t_chip->chipset, t_chip->platform, t_chip->revNum);
+ continue;
+ }
+ dtb_count++;
+ }
+ }
+ }
+ }
+ closedir(dir);
+ log_info("=> Found %d unique DTB(s)\n", dtb_count);
+
+ switch (dt_type) {
+ case QCDT:
+ log_info("Start QCDT magic, version DTB... \n");
+ magic = QCDT_MAGIC;
+ version = QCDT_VERSION;
+ break;
+ case SPRD:
+ log_info("Start SPRD magic, version DTB... \n");
+ magic = SPRD_MAGIC;
+ version = SPRD_VERSION;
+ break;
+ case EXYNOS:
+ log_info("Start EXYNOS magic, version DTB... \n");
+ magic = EXYNOS_MAGIC;
+ version = EXYNOS_VERSION;
+ break;
+ default:
+ goto cleanup;
+ }
+
+ if (!dtb_count)
+ goto cleanup;
+
+ /* Generate the master DTB file:
+
+ Simplify write error handling by just checking for actual vs
+ expected bytes written at the end.
+ */
+
+ log_info("Generating master DTB...\n");
+
+ out_fd = open(output_file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
+ if (out_fd < 0) {
+ log_err("Cannot create '%s'\n", output_file);
+ rc = RC_ERROR;
+ goto cleanup;
+ }
+
+ /* Write header info */
+ wrote += write(out_fd, magic, sizeof(uint8_t) * 4); /* magic */
+ wrote += write(out_fd, &version, sizeof(uint32_t)); /* version */
+ wrote += write(out_fd, (uint32_t *)&dtb_count, sizeof(uint32_t));
+ /* #DTB */
+
+ /* Calculate offset of first DTB block */
+ dtb_offset = 12 + /* header */
+ (20 * dtb_count) + /* DTB table entries */
+ 4; /* end of table indicator */
+ /* Round up to page size */
+ padding = page_size - (dtb_offset % page_size);
+ dtb_offset += padding;
+ expected = dtb_offset;
+
+ /* Write index table:
+ chipset
+ platform
+ soc rev
+ dtb offset
+ dtb size
+ */
+ for (chip = chip_list; chip; chip = chip->next) {
+ wrote += write(out_fd, &chip->chipset, sizeof(uint32_t));
+ wrote += write(out_fd, &chip->platform, sizeof(uint32_t));
+ wrote += write(out_fd, &chip->revNum, sizeof(uint32_t));
+ if (chip->master->master_offset != 0) {
+ wrote += write(out_fd, &chip->master->master_offset, sizeof(uint32_t));
+ } else {
+ wrote += write(out_fd, &expected, sizeof(uint32_t));
+ chip->master->master_offset = expected;
+ expected += chip->master->dtb_size;
+ }
+ wrote += write(out_fd, &chip->master->dtb_size, sizeof(uint32_t));
+ }
+
+ rc = RC_SUCCESS;
+ wrote += write(out_fd, &rc, sizeof(uint32_t)); /* end of table indicator */
+ if (padding > 0)
+ wrote += write(out_fd, filler, padding);
+
+ /* Write DTB's */
+ for (chip = chip_list; chip; chip = chip->next) {
+ if (chip->master->wroteDtb) {
+ continue;
+ }
+
+ chip->master->wroteDtb = 1;
+ filename = chip->master->dtb_file;
+ dtb_size = chip->master->dtb_size;
+
+ log_dbg("(writing '%s' - %u bytes) \n", filename, dtb_size);
+ pInputFile = fopen(filename, "r");
+ if (pInputFile != NULL) {
+ totBytesRead = 0;
+ while ((numBytesRead = fread(buf, 1, COPY_BLK, pInputFile)) > 0) {
+ wrote += write(out_fd, buf, numBytesRead);
+ totBytesRead += numBytesRead;
+ }
+ fclose(pInputFile);
+ padding = page_size - (totBytesRead % page_size);
+ if ((uint32_t)(totBytesRead + padding) != dtb_size) {
+ log_err("DTB size mismatch, please re-run: expected %d vs actual %d (%s)\n",
+ dtb_size, totBytesRead + padding,
+ filename);
+ rc = RC_ERROR;
+ break;
+ }
+ if (padding > 0)
+ wrote += write(out_fd, filler, padding);
+ } else {
+ log_err("failed to open DTB '%s'\n", filename);
+ rc = RC_ERROR;
+ break;
+ }
+ }
+ close(out_fd);
+
+ if (expected != wrote) {
+ log_err("error writing output file, please rerun: size mismatch %d vs %d\n",
+ expected, wrote);
+ rc = RC_ERROR;
+ } else
+ log_dbg("Total wrote %u bytes\n", wrote);
+
+ if (rc != RC_SUCCESS)
+ unlink(output_file);
+ else
+ log_info("completed\n");
+
+cleanup:
+ free(filler);
+ chip_deleteall();
+ return rc;
+}
diff --git a/src/mkdzimage/CMakeLists.txt b/src/mkdzimage/CMakeLists.txt
new file mode 100644
index 0000000..e7c3044
--- /dev/null
+++ b/src/mkdzimage/CMakeLists.txt
@@ -0,0 +1,9 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(mkdzimage C)
+
+SET(MKDZIMAGE "mkdzimage")
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ MKDZIMAGESRCS)
+
+ADD_EXECUTABLE(${MKDZIMAGE} ${MKDZIMAGESRCS})
+
+INSTALL(TARGETS ${MKDZIMAGE} DESTINATION bin)
diff --git a/src/mkdzimage/dzimage.h b/src/mkdzimage/dzimage.h
new file mode 100644
index 0000000..3ddd90f
--- /dev/null
+++ b/src/mkdzimage/dzimage.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DZIMAGE_H_
+#define _DZIMAGE_H_
+
+#define ALIGN_SIZE 2048
+#define MAX_NAME 512
+#define MAGIC_NUM 0x54495A4E
+
+struct dzimage_hdr {
+ unsigned int magic_num;
+ unsigned int kernel_addr;
+ unsigned int kernel_size;
+ unsigned int dt_addr;
+ unsigned int dt_size;
+ unsigned int tags_addr;
+ unsigned int page_size;
+ unsigned char cmdline[MAX_NAME];
+};
+
+#endif /* _DZIMAGE_H_ */ \ No newline at end of file
diff --git a/src/mkdzimage/mkdzimage.c b/src/mkdzimage/mkdzimage.c
new file mode 100644
index 0000000..28cc0af
--- /dev/null
+++ b/src/mkdzimage/mkdzimage.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2012, 2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "dzimage.h"
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "o:k:d:a:";
+
+static void usage(char *name)
+{
+ fprintf(stderr, "usage: %s [-okda]\n", name);
+ fprintf(stderr, "\t -o\toutput filename\n");
+ fprintf(stderr, "\t -k\tkernel filename\n");
+ fprintf(stderr, "\t -d\tdevice tree filename\n");
+ fprintf(stderr, "\t -a\tatags address\n");
+ exit(0);
+}
+
+static void *load_file(char *file, unsigned int *total)
+{
+ FILE *fp;
+ void *data;
+ int ret, size;
+
+ fp = fopen(file, "rb");
+ if (!fp)
+ goto out;
+
+ ret = fseek(fp, 0x0, SEEK_END);
+ if (ret < 0)
+ goto close;
+
+ size = ftell(fp);
+ if (size < 1)
+ goto close;
+
+ ret = fseek(fp, 0x0, SEEK_SET);
+ if (ret < 0)
+ goto out;
+
+ data = malloc(size);
+ if (!data)
+ goto out;
+
+ if (fread(data, sizeof(char), size, fp) != sizeof(char) *size)
+ goto free_data;
+
+ *total = size;
+
+ fclose(fp);
+
+ return data;
+
+free_data:
+ free(data);
+close:
+ fclose(fp);
+out:
+ return NULL;
+}
+
+static unsigned char align_data[ALIGN_SIZE] = { 0, };
+static void write_align(FILE *fp, unsigned int align_size, unsigned int cur_size)
+{
+ unsigned int write_size;
+
+ if (!fp)
+ return;
+
+ cur_size = cur_size % align_size;
+ write_size = align_size - cur_size;
+
+ if (!cur_size || !write_size)
+ return;
+
+ fwrite(align_data, write_size, sizeof(unsigned char), fp);
+}
+
+int main(int argc, char **argv)
+{
+ struct dzimage_hdr hdr;
+ char out_name[MAX_NAME+1];
+ char kern_name[MAX_NAME+1];
+ char dt_name[MAX_NAME+1];
+ unsigned int kern_addr = 0x00008000;
+ unsigned int atags_addr = 0x01e00000;
+ void *kern_data, *dt_data;
+ FILE *fp;
+ int c;
+
+ memset(&hdr, 0x0, sizeof(hdr));
+ memset(out_name, 0x0, MAX_NAME+1);
+ memset(kern_name, 0x0, MAX_NAME+1);
+ memset(dt_name, 0x0, MAX_NAME+1);
+
+ opterr = 0;
+ while ((c = getopt(argc, argv, optstr)) != -1) {
+ switch (c) {
+ case 'o':
+ strcpy(out_name, optarg);
+ break;
+ case 'k':
+ strcpy(kern_name, optarg);
+ break;
+ case 'd':
+ strcpy(dt_name, optarg);
+ break;
+ case 'a':
+ sscanf(optarg, "%d", &atags_addr);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ printf("out_name[%s]\n", out_name);
+ printf("kern_name[%s]\n", kern_name);
+ printf("dt_name[%s]\n", dt_name);
+
+ hdr.magic_num = MAGIC_NUM;
+ hdr.kernel_addr = kern_addr;
+ hdr.tags_addr = atags_addr;
+ hdr.page_size = ALIGN_SIZE;
+
+ kern_data = load_file(kern_name, &hdr.kernel_size);
+ if (!kern_data) {
+ fprintf(stderr, "failed to load %s\n", kern_name);
+ goto kern_load;
+ }
+
+ hdr.dt_addr = kern_addr + hdr.kernel_size;
+ dt_data = load_file(dt_name, &hdr.dt_size);
+ if (!dt_data) {
+ fprintf(stderr, "failed to load %s\n", dt_name);
+ goto dt_load;
+ }
+
+ fp = fopen(out_name, "wb");
+ if (!fp) {
+ fprintf(stderr, "failed to open %s\n", out_name);
+ goto clear;
+ }
+
+ fwrite(&hdr, sizeof(hdr), sizeof(unsigned char), fp);
+ write_align(fp, ALIGN_SIZE, sizeof(hdr));
+
+ fwrite(kern_data, hdr.kernel_size, sizeof(unsigned char), fp);
+ write_align(fp, ALIGN_SIZE, hdr.kernel_size);
+
+ fwrite(dt_data, hdr.dt_size, sizeof(unsigned char), fp);
+ write_align(fp, ALIGN_SIZE, hdr.dt_size);
+
+ fclose(fp);
+
+ free(kern_data);
+ free(dt_data);
+
+ return 0;
+
+clear:
+ free(dt_data);
+dt_load:
+ free(kern_data);
+kern_load:
+ exit(0);
+ return 1;
+}