diff options
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | packaging/system-tools.spec | 33 | ||||
-rw-r--r-- | src/dtbtool/CMakeLists.txt | 9 | ||||
-rwxr-xr-x | src/dtbtool/dtbtool.c | 703 | ||||
-rw-r--r-- | src/mkdzimage/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/mkdzimage/dzimage.h | 35 | ||||
-rw-r--r-- | src/mkdzimage/mkdzimage.c | 189 |
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; +} |