Newer
Older
* fdtextract -- Tool to extract sub images from FIT image.
*
* Copyright (C) 2021 IOPSYS Software Solutions AB. All rights reserved.
*
* Author: jonas.hoglund@iopsys.eu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
static const char usage_synopsis[] = "fdtextract [options] <file>";
static const char usage_short_opts[] = "le:o:s:a:" USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = {
{"list", no_argument, NULL, 'l'},
{"extract", a_argument, NULL, 'e'},
{"out", a_argument, NULL, 'o'},
USAGE_COMMON_LONG_OPTS
};
static const char * const usage_opts_help[] = {
"List images embedded in FIT",
"Extract image from FIT",
static int list_images(char *buf)
{
int ndepth = 0, count = 0, noffset;
const char *name;
noffset = fdt_next_node(buf, noffset, &ndepth);
while (ndepth > 0) {
if (ndepth == 1) {
name = fdt_get_name(buf, noffset, NULL);
printf("[%d]: %s\n", count, name);
count++;
}
noffset = fdt_next_node(buf, noffset, &ndepth);
}
/* Extract an image embedded in the FIT. */
static int extract_image(const char *file, char *name, char *out)
unsigned int data_size, data_offset;
const fdt32_t *val;
char *buf;
size_t len;
buf = utilfdt_read(file, &len);
if (!buf) {
die("could not read: %s\n", file);
}
snprintf(path, MAX_PATH_LEN, "/images/%s", name);
noffset = fdt_path_offset(buf, path);
if (noffset < 0) {
fprintf(stderr, "Error: could not find image: %s.\n", name);
/* Get offset of image. Try both relative and absolute offset. */
val = fdt_getprop(buf, noffset, "data-offset", NULL);
if(val) {
/* Relative offset */
data_offset = fdt32_to_cpu(*val);
data_offset += ((fdt_totalsize(buf) + 3) & ~3);
} else {
/* Absolute offset */
val = fdt_getprop(buf, noffset, "data-position", NULL);
fprintf(stderr, "Error: could get offset of image: %s.\n", name);
return -1;
}
data_offset = fdt32_to_cpu(*val);
}
/* Size */
val = fdt_getprop(buf, noffset, "data-size", NULL);
if (!val) {
fprintf(stderr, "Error: could get size of image: %s.\n", name);
return -1;
}
data_size = fdt32_to_cpu(*val);
/* If output file is provided, write to that file. If not, write
to stdout. */
if (out) {
fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd < 0) {
fprintf(stderr, "Error opening output file %s.\n", out);
return errno;
}
} else {
fd = STDOUT_FILENO;
count = write(fd, buf + data_offset, data_size);
if (count < data_size) {
fprintf(stderr, "Error writing output file %s.\n", out);
/* Print the sha256 hash on an image embedded in the FIT. */
static int get_hash(char *buf, char *name)
{
char path[MAX_PATH_LEN];
int noffset, i;
snprintf(path, MAX_PATH_LEN, "/images/%s/hash-1", name);
noffset = fdt_path_offset(buf, path);
if (noffset < 0) {
fprintf(stderr, "Error: could not find image hash: %s.\n", name);
algo = fdt_getprop(buf, noffset, "algo", NULL);
if (strcmp(algo, "sha256")) {
fprintf(stderr, "Error: unknown hash algorithm %s\n", val);
val = (uint8_t *)fdt_getprop(buf, noffset, "value", NULL);
for (i=0; i<SHA_256_LEN; i++)
/* Print out an attribute of the root node. */
static int get_attribute(char *buf, char *name)
{
int noffset;
const char *val = NULL;
/* Get path of root node. */
noffset = fdt_path_offset(buf, "/");
if (noffset < 0) {
fprintf(stderr, "Error: could not find image hash: %s.\n", name);
return -1;
}
/* Print the property value. */
val = fdt_getprop(buf, noffset, name, NULL);
if (!val) {
fprintf(stderr, "Error: could not find property %s.\n", name);
return -1;
}
printf("%s\n", val);
return 0;
}
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
char *read_header(const char *file)
{
char *buf;
int fd, total_size;
size_t len;
fd = open(file, O_RDONLY);
if (fd < 0)
return NULL;
/* Read minimal static struct */
buf = malloc(FDT_V1_SIZE);
if (!buf)
return NULL;
len = read(fd, buf, FDT_V1_SIZE);
if (len < FDT_V1_SIZE)
return NULL;
/* Read rest of header */
total_size = fdt_totalsize(buf);
buf = realloc(buf, total_size);
if (!buf)
return NULL;
len = read(fd, buf + FDT_V1_SIZE, total_size - FDT_V1_SIZE);
if (len < total_size - FDT_V1_SIZE)
return NULL;
return buf;
}
bool list = false, extract = false,
hash = false, attribute = false;
while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
case_USAGE_COMMON_FLAGS
case 'l':
list = true;
break;
case 'e':
extract = true;
name = optarg;
break;
case 'o':
out = optarg;
case 's':
hash = true;
name = optarg;
break;
case 'a':
attribute = true;
name = optarg;
break;
}
}
if (optind != argc - 1)
usage("missing input filename");
file = argv[optind];
buf = read_header(file);
die("could not read header from: %s\n", file);
/* Pass the pointer to the header to read attributes. */
if (attribute)
ret = get_attribute(buf, name);
/* Let extract image read the entire file. */
if (extract)
ret = extract_image(file, name, out);