9
0
Fork 0

scripts: Add imx-usb-loader tool

This adds host tools for i.MX to generate the i.MX internal
flash header format and a tool to upload these images to an
i.MX SoC via USB.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Sascha Hauer 2013-03-13 14:30:42 +01:00
parent 2307901376
commit 134a788ac5
9 changed files with 2330 additions and 0 deletions

View File

@ -256,6 +256,15 @@ ifeq ($(machine-y),zynq)
KBUILD_IMAGE := barebox.zynq
endif
CFG_barebox.imx := $(src)/arch/arm/boards/$(board-y)/flash-header.imxcfg
barebox.imx: $(KBUILD_BINARY) FORCE
$(call if_changed,imx_image)
ifeq ($(CONFIG_ARCH_IMX_INTERNAL_BOOT_USE_IMXIMAGE),y)
KBUILD_TARGET := barebox.imx
KBUILD_IMAGE := barebox.imx
endif
pbl := arch/arm/pbl
$(pbl)/zbarebox.S $(pbl)/zbarebox.bin $(pbl)/zbarebox: barebox.bin
$(Q)$(MAKE) $(build)=$(pbl) $@

View File

@ -66,6 +66,7 @@ config BOARDINFO
choice
prompt "Select boot mode"
depends on !ARCH_IMX_INTERNAL_BOOT_USE_IMXIMAGE
help
i.MX processors support two different boot modes. With the internal
boot mode the boot medium contains a header describing the image to
@ -93,6 +94,21 @@ config ARCH_IMX_EXTERNAL_BOOT
endchoice
config ARCH_IMX_IMXIMAGE
bool
help
if enabled the imx-image tool is compiled
config ARCH_IMX_INTERNAL_BOOT_USE_IMXIMAGE
select ARCH_IMX_IMXIMAGE
bool
help
Traditionally the i.MX specific format for internal bootmode
was generated using C structs inside the binary. Now there is
a tool available to generate the imx-image format. Boards using
this tool must select this option. This is recommended for new
boards.
choice
depends on ARCH_IMX_INTERNAL_BOOT
prompt "Internal boot source"
@ -596,6 +612,13 @@ endmenu
menu "i.MX specific settings"
config ARCH_IMX_USBLOADER
bool "compile imx-usb-loader"
help
imx-usb-loader is a tool to upload and start imximages to an i.MX SoC
in ROM boot mode. It requires libusb, so make sure you have the libusb
devel package installed on your machine.
config IMX_IIM
tristate "IIM fusebox device"
depends on !ARCH_IMX21 && !ARCH_IMX21

View File

@ -13,6 +13,7 @@ hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-am35xx-spi-image
hostprogs-$(CONFIG_ARCH_S5PCxx) += s5p_cksum
hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader
hostprogs-$(CONFIG_ARCH_ZYNQ) += zynq_mkimage
subdir-$(CONFIG_ARCH_IMX) += imx
HOSTLOADLIBES_omap4_usbboot = -lpthread
omap4_usbboot-objs := usb_linux.o omap4_usbboot.o

View File

@ -308,3 +308,28 @@ quiet_cmd_check_file_size = CHKSIZE $@
echo "$@ size $$size > of the maximum size $$max_size" >&2; \
exit 1 ; \
fi;
quiet_cmd_imximage__S_dcd= DCD_S $@
cmd_imximage_S_dcd= \
( \
echo '\#include <asm-generic/barebox.lds.h>'; \
echo '.balign STRUCT_ALIGNMENT'; \
echo '.global $(subst -,_,$(*F))_start'; \
echo '$(subst -,_,$(*F))_start:'; \
echo '.incbin "$<" '; \
echo '$(subst -,_,$(*F))_end:'; \
echo '.global $(subst -,_,$(*F))_end'; \
echo '.balign STRUCT_ALIGNMENT'; \
) > $@
quiet_cmd_dcd = DCD $@
cmd_dcd = $(objtree)/scripts/imx/imx-image -d -o $@ -c $<
$(obj)/%.dcd: $(obj)/%.imxcfg FORCE
$(call if_changed,dcd)
$(obj)/%.S: $(obj)/%.dcd
$(call cmd,imximage_S_dcd)
quiet_cmd_imx_image = IMX-IMG $@
cmd_imx_image = $(obj)/scripts/imx/imx-image -b -c $(CFG_$(@F)) -f $< -o $@

2
scripts/imx/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
imx-usb-loader
imx-image

10
scripts/imx/Makefile Normal file
View File

@ -0,0 +1,10 @@
hostprogs-$(CONFIG_ARCH_IMX_IMXIMAGE) += imx-image
hostprogs-$(CONFIG_ARCH_IMX_USBLOADER) += imx-usb-loader
always := $(hostprogs-y)
HOSTCFLAGS_imx-usb-loader.o = `pkg-config --cflags libusb-1.0`
HOSTLOADLIBES_imx-usb-loader = `pkg-config --libs libusb-1.0`
imx-usb-loader-objs := imx-usb-loader.o
imx-image-objs := imx-image.o

89
scripts/imx/README Normal file
View File

@ -0,0 +1,89 @@
imx-usb-loader Tools
The Freescale i.MX SoCs support bootstrapping from USB. These are host
side utilities handling this bootstrap process.
The imx-usb-loader tool is used to upload and start i.MX images. These
are images containing a DCD (Device Configuration Data) table. To generate
these images from raw binaries use the imx-image tool.
imx-image
---------
The imx-image tool can be used to generate imximages from raw binaries.
It requires an configuration file describing how to setup the SDRAM on
a particular board. This mainly consists of a poke table. The recognized
options in this file are:
soc <soctype> soctype can be one of imx35, imx51, imx53, imx6
loadaddr <adr> The address the binary is uploaded to
dcdofs <ofs> The offset of the image header in the image. This should be:
0x400 - MMC/SD, NAND, serial ROM, PATA, SATA
0x1000 - NOR Flash
0x100 - OneNAND
wm 8 <adr> <value> do a byte memory write
wm 16 <adr> <value> do a short memory write
wm 32 <adr> <value> do a word memory write
check <width> <cond> <addr> <mask> Poll until condition becomes true.
with <cond> being one of:
while_all_bits_clear,
while_all_bits_set,
while_any_bit_clear,
while_any_bit_set
the i.MX SoCs support a wide range of fancy things doing with the flash header.
We limit ourselves to a very simple case, that is the flash header has a fixed
size of 0x1000 bytes. The application is expected right thereafter, so if you
specify a loadaddr of 0x80000000 in the config file, the first 0x1000 bytes
are occupied by the flash header. The raw image inside the imximage will then
end up at 0x80001000 from where it is then executed.
Example config file, suitable for an Eukra cpuimx35:
soc imx35
dcdofs 0x400
loadaddr 0x80000000
wm 32 0x53F80004 0x00821000
wm 32 0x53F80004 0x00821000
wm 32 0xb8001010 0x00000004
wm 32 0xB8001010 0x0000000C
wm 32 0xb8001004 0x0009572B
wm 32 0xb8001000 0x92220000
wm 8 0x80000400 0xda
wm 32 0xb8001000 0xa2220000
wm 32 0x80000000 0x12344321
wm 32 0x80000000 0x12344321
wm 32 0xb8001000 0xb2220000
wm 8 0x80000033 0xda
wm 8 0x82000000 0xda
wm 32 0xb8001000 0x82224080
wm 32 0xb8001010 0x00000004
example call:
imx-image -c cpuimx35.cfg -f raw.bin -o imximage.bin
imx-usb-loader
--------------
This utility is used to upload an imximage to a board. Some bootloaders directly
generate this file format, with others you can generate such an image with the
imx-image tool. The only required argument is the image file to upload. imx-usb-loader
will then look for a supported device, upload the file and execute it.
example usage:
imx-usb-loader imximage.bin
Some technical notes: The i.MX SoCs USB ROM boot mode supports doing register writes
and file uploads. The files are usually uploaded to SDRAM. For this to work the SDRAM
has to be initialized first. The information necessary to do this is contained in the
imximage itself, more exactly in the DCD table. The imx-usb-loader parses this table
and translates the DCD into register writes, basically it resembles what the i.MX would
do in ROM code when the same image would be loaded from another bootsource like SD/MMC
cards. Still the i.MX needs the DCD table to be uploaded. The i.MX would execute the DCD
data again, which would result in corrupting the just configured SDRAM. The imx-usb-loader
prevents this by setting the DCD length to 0x0 before uploading the image.
The i.MX Boot ROM supports different types of images to upload. The imx-usb-loader currently
only handles the simple case of uploading a single image which is executed right after
downloading.

744
scripts/imx/imx-image.c Normal file
View File

@ -0,0 +1,744 @@
/*
* (C) Copyright 2013 Sascha Hauer, Pengutronix
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* 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.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <endian.h>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
#define MAX_DCD 1024
static uint32_t image_load_addr;
static uint32_t image_dcd_offset;
static uint32_t dcdtable[MAX_DCD];
static int curdcd;
static int header_version;
static int add_barebox_header;
/*
* ============================================================================
* i.MX flash header v1 handling. Found on i.MX35 and i.MX51
* ============================================================================
*/
struct imx_flash_header {
uint32_t app_code_jump_vector;
uint32_t app_code_barker;
uint32_t app_code_csf;
uint32_t dcd_ptr_ptr;
uint32_t super_root_key;
uint32_t dcd;
uint32_t app_dest;
uint32_t dcd_barker;
uint32_t dcd_block_len;
} __attribute__((packed));
#define FLASH_HEADER_OFFSET 0x400
#define DCD_BARKER 0xb17219e9
static uint32_t bb_header[] = {
0xea0003fe, /* b 0x1000 */
0xeafffffe, /* 1: b 1b */
0xeafffffe, /* 1: b 1b */
0xeafffffe, /* 1: b 1b */
0xeafffffe, /* 1: b 1b */
0xeafffffe, /* 1: b 1b */
0xeafffffe, /* 1: b 1b */
0xeafffffe, /* 1: b 1b */
0x65726162, /* 'bare' */
0x00786f62, /* 'box\0' */
0x00000000,
0x00000000,
0x55555555,
0x55555555,
0x55555555,
0x55555555,
0x55555555,
0x55555555,
0x55555555,
0x55555555,
};
static int add_header_v1(void *buf, int offset, uint32_t loadaddr, uint32_t imagesize)
{
struct imx_flash_header *hdr;
int dcdsize = curdcd * sizeof(uint32_t);
if (add_barebox_header)
memcpy(buf, bb_header, sizeof(bb_header));
buf += offset;
hdr = buf;
hdr->app_code_jump_vector = loadaddr + 0x1000;
hdr->app_code_barker = 0x000000b1;
hdr->app_code_csf = 0x0;
hdr->dcd_ptr_ptr = loadaddr + offset + offsetof(struct imx_flash_header, dcd);
hdr->super_root_key = 0x0;
hdr->dcd = loadaddr + offset + offsetof(struct imx_flash_header, dcd_barker);
hdr->app_dest = loadaddr;
hdr->dcd_barker = DCD_BARKER;
hdr->dcd_block_len = dcdsize;
buf += sizeof(struct imx_flash_header);
memcpy(buf, dcdtable, dcdsize);
buf += dcdsize;
*(uint32_t *)buf = imagesize;
return 0;
}
static int write_mem_v1(uint32_t addr, uint32_t val, int width)
{
if (curdcd > MAX_DCD - 3) {
fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD);
return -ENOMEM;
}
dcdtable[curdcd++] = width;
dcdtable[curdcd++] = addr;
dcdtable[curdcd++] = val;
return 0;
}
/*
* ============================================================================
* i.MX flash header v2 handling. Found on i.MX53 and i.MX6
* ============================================================================
*/
struct imx_boot_data {
uint32_t start;
uint32_t size;
uint32_t plugin;
} __attribute__((packed));
#define TAG_IVT_HEADER 0xd1
#define IVT_VERSION 0x40
#define TAG_DCD_HEADER 0xd2
#define DCD_VERSION 0x40
#define TAG_WRITE 0xcc
#define TAG_CHECK 0xcf
struct imx_ivt_header {
uint8_t tag;
uint16_t length;
uint8_t version;
} __attribute__((packed));
struct imx_flash_header_v2 {
struct imx_ivt_header header;
uint32_t entry;
uint32_t reserved1;
uint32_t dcd_ptr;
uint32_t boot_data_ptr;
uint32_t self;
uint32_t csf;
uint32_t reserved2;
struct imx_boot_data boot_data;
struct imx_ivt_header dcd_header;
} __attribute__((packed));
static int add_header_v2(void *buf, int offset, uint32_t loadaddr, uint32_t imagesize)
{
struct imx_flash_header_v2 *hdr;
int dcdsize = curdcd * sizeof(uint32_t);
if (add_barebox_header)
memcpy(buf, bb_header, sizeof(bb_header));
buf += offset;
hdr = buf;
hdr->header.tag = TAG_IVT_HEADER;
hdr->header.length = htobe16(32);
hdr->header.version = IVT_VERSION;
hdr->entry = loadaddr + 0x1000;
hdr->dcd_ptr = loadaddr + 0x400 + offsetof(struct imx_flash_header_v2, dcd_header);
hdr->boot_data_ptr = loadaddr + 0x400 + offsetof(struct imx_flash_header_v2, boot_data);
hdr->self = loadaddr + 0x400;
hdr->boot_data.start = loadaddr;
hdr->boot_data.size = imagesize;
hdr->dcd_header.tag = TAG_DCD_HEADER;
hdr->dcd_header.length = htobe16(sizeof(uint32_t) + dcdsize);
hdr->dcd_header.version = DCD_VERSION;
buf += sizeof(*hdr);
memcpy(buf, dcdtable, dcdsize);
return 0;
}
static void usage(const char *prgname)
{
fprintf(stderr, "usage: %s [OPTIONS]\n\n"
"-c <config> specify configuration file\n"
"-f <input> input image file\n"
"-o <output> output file\n"
"-b add barebox header to image. If used, barebox recognizes\n"
" the image as regular barebox image which can be used as\n"
" second stage image\n"
"-h this help\n", prgname);
exit(1);
}
#define MAXARGS 5
static int parse_line(char *line, char *argv[])
{
int nargs = 0;
while (nargs < MAXARGS) {
/* skip any white space */
while ((*line == ' ') || (*line == '\t'))
++line;
if (*line == '\0') /* end of line, no more args */
argv[nargs] = NULL;
if (*line == '\0') { /* end of line, no more args */
argv[nargs] = NULL;
return nargs;
}
argv[nargs++] = line; /* begin of argument string */
/* find end of string */
while (*line && (*line != ' ') && (*line != '\t'))
++line;
if (*line == '\0') { /* end of line, no more args */
argv[nargs] = NULL;
return nargs;
}
*line++ = '\0'; /* terminate current arg */
}
printf("** Too many args (max. %d) **\n", MAXARGS);
return nargs;
}
struct command {
const char *name;
int (*parse)(int argc, char *argv[]);
};
static uint32_t last_cmd;
static int last_cmd_len;
static uint32_t *last_dcd;
static void check_last_dcd(uint32_t cmd)
{
if (last_dcd) {
if (last_cmd == cmd) {
return;
} else {
uint32_t l = be32toh(*last_dcd);
l |= last_cmd_len << 8;
*last_dcd = htobe32(l);
last_dcd = NULL;
}
}
if (!cmd)
return;
if (!last_dcd) {
last_dcd = &dcdtable[curdcd++];
*last_dcd = htobe32(cmd);
last_cmd_len = sizeof(uint32_t);
last_cmd = cmd;
}
}
static int write_mem_v2(uint32_t addr, uint32_t val, int width)
{
uint32_t cmd;
cmd = (TAG_WRITE << 24) | width;
if (curdcd > MAX_DCD - 3) {
fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD);
return -ENOMEM;
}
check_last_dcd(cmd);
last_cmd_len += sizeof(uint32_t) * 2;
dcdtable[curdcd++] = htobe32(addr);
dcdtable[curdcd++] = htobe32(val);
return 0;
}
static const char *check_cmds[] = {
"while_all_bits_clear", /* while ((*address & mask) == 0); */
"while_all_bits_set" , /* while ((*address & mask) == mask); */
"while_any_bit_clear", /* while ((*address & mask) != mask); */
"while_any_bit_set", /* while ((*address & mask) != 0); */
};
static void do_cmd_check_usage(void)
{
fprintf(stderr,
"usage: check <width> <cmd> <addr> <mask>\n"
"<width> access width in bytes [1|2|4]\n"
"with <cmd> one of:\n"
"while_all_bits_clear: while ((*addr & mask) == 0)\n"
"while_all_bits_set: while ((*addr & mask) == mask)\n"
"while_any_bit_clear: while ((*addr & mask) != mask)\n"
"while_any_bit_set: while ((*addr & mask) != 0)\n");
}
static int do_cmd_check(int argc, char *argv[])
{
uint32_t addr, mask, cmd;
int i, width;
const char *scmd;
if (argc < 5) {
do_cmd_check_usage();
return -EINVAL;
}
width = strtoul(argv[1], NULL, 0) >> 3;
scmd = argv[2];
addr = strtoul(argv[3], NULL, 0);
mask = strtoul(argv[4], NULL, 0);
switch (width) {
case 1:
case 2:
case 4:
break;
default:
fprintf(stderr, "illegal width %d\n", width);
return -EINVAL;
};
if (curdcd > MAX_DCD - 3) {
fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD);
return -ENOMEM;
}
for (i = 0; i < ARRAY_SIZE(check_cmds); i++) {
if (!strcmp(scmd, check_cmds[i]))
break;
}
if (i == ARRAY_SIZE(check_cmds)) {
do_cmd_check_usage();
return -EINVAL;
}
cmd = (TAG_CHECK << 24) | (i << 3) | width;
check_last_dcd(cmd);
last_cmd_len += sizeof(uint32_t) * 2;
dcdtable[curdcd++] = htobe32(addr);
dcdtable[curdcd++] = htobe32(mask);
return 0;
}
static int do_cmd_write_mem(int argc, char *argv[])
{
uint32_t addr, val, width;
if (argc != 4) {
fprintf(stderr, "usage: wm [8|16|32] <addr> <val>\n");
return -EINVAL;
}
width = strtoul(argv[1], NULL, 0);
addr = strtoul(argv[2], NULL, 0);
val = strtoul(argv[3], NULL, 0);
width >>= 3;
switch (width) {
case 1:
case 2:
case 4:
break;
default:
fprintf(stderr, "illegal width %d\n", width);
return -EINVAL;
};
switch (header_version) {
case 1:
return write_mem_v1(addr, val, width);
case 2:
return write_mem_v2(addr, val, width);
default:
return -EINVAL;
}
}
static int do_loadaddr(int argc, char *argv[])
{
if (argc < 2)
return -EINVAL;
image_load_addr = strtoul(argv[1], NULL, 0);
return 0;
}
static int do_dcd_offset(int argc, char *argv[])
{
if (argc < 2)
return -EINVAL;
image_dcd_offset = strtoul(argv[1], NULL, 0);
return 0;
}
struct soc_type {
char *name;
int header_version;
};
static struct soc_type socs[] = {
{ .name = "imx35", .header_version = 1, },
{ .name = "imx51", .header_version = 1, },
{ .name = "imx53", .header_version = 2, },
{ .name = "imx6", .header_version = 2, },
};
static int do_soc(int argc, char *argv[])
{
char *soc;
int i;
if (argc < 2)
return -EINVAL;
soc = argv[1];
for (i = 0; i < ARRAY_SIZE(socs); i++) {
if (!strcmp(socs[i].name, soc)) {
header_version = socs[i].header_version;
return 0;
}
}
fprintf(stderr, "unkown SoC type \"%s\". Known SoCs are:\n", soc);
for (i = 0; i < ARRAY_SIZE(socs); i++)
fprintf(stderr, "%s ", socs[i].name);
fprintf(stderr, "\n");
return -EINVAL;
}
struct command cmds[] = {
{
.name = "wm",
.parse = do_cmd_write_mem,
}, {
.name = "check",
.parse = do_cmd_check,
}, {
.name = "loadaddr",
.parse = do_loadaddr,
}, {
.name = "dcdofs",
.parse = do_dcd_offset,
}, {
.name = "soc",
.parse = do_soc,
},
};
static int parse_config(const char *filename)
{
FILE *f;
int lineno = 0;
char *line = NULL, *tmp;
size_t len;
char *argv[MAXARGS];
int nargs, i, ret;
f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "Error: %s - Can't open DCD file\n", filename);
exit(1);
}
while ((getline(&line, &len, f)) > 0) {
lineno++;
tmp = strchr(line, '#');
if (tmp)
*tmp = 0;
tmp = strrchr(line, '\n');
if (tmp)
*tmp = 0;
nargs = parse_line(line, argv);
if (!nargs)
continue;
ret = -ENOENT;
for (i = 0; i < ARRAY_SIZE(cmds); i++) {
if (!strcmp(cmds[i].name, argv[0])) {
ret = cmds[i].parse(nargs, argv);
if (ret) {
fprintf(stderr, "error in line %d: %s\n",
lineno, strerror(-ret));
return ret;
}
break;
}
}
if (ret == -ENOENT) {
fprintf(stderr, "no such command: %s\n", argv[0]);
return ret;
}
}
return 0;
}
static int xread(int fd, void *buf, int len)
{
int ret;
while (len) {
ret = read(fd, buf, len);
if (ret < 0)
return ret;
if (!ret)
return EOF;
buf += ret;
len -= ret;
}
return 0;
}
static int xwrite(int fd, void *buf, int len)
{
int ret;
while (len) {
ret = write(fd, buf, len);
if (ret < 0)
return ret;
buf += ret;
len -= ret;
}
return 0;
}
static int write_dcd(const char *outfile)
{
int outfd, ret;
int dcdsize = curdcd * sizeof(uint32_t);
outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (outfd < 0) {
perror("open");
exit(1);
}
ret = xwrite(outfd, dcdtable, dcdsize);
if (ret < 0) {
perror("write");
exit(1);
}
return 0;
}
int main(int argc, char *argv[])
{
int opt, ret;
char *configfile = NULL;
char *imagename = NULL;
char *outfile = NULL;
void *buf;
size_t image_size = 0;
struct stat s;
int infd, outfd;
int dcd_only = 0;
while ((opt = getopt(argc, argv, "c:hf:o:bd")) != -1) {
switch (opt) {
case 'c':
configfile = optarg;
break;
case 'f':
imagename = optarg;
break;
case 'o':
outfile = optarg;
break;
case 'b':
add_barebox_header = 1;
break;
case 'd':
dcd_only = 1;
break;
case 'h':
usage(argv[0]);
default:
exit(1);
}
}
if (!imagename && !dcd_only) {
fprintf(stderr, "image name not given\n");
exit(1);
}
if (!configfile) {
fprintf(stderr, "config file not given\n");
exit(1);
}
if (!outfile) {
fprintf(stderr, "output file not given\n");
exit(1);
}
if (!dcd_only) {
ret = stat(imagename, &s);
if (ret) {
perror("stat");
exit(1);
}
image_size = s.st_size;
}
ret = parse_config(configfile);
if (ret)
exit(1);
buf = calloc(4096, 1);
if (!buf)
exit(1);
if (!image_dcd_offset) {
fprintf(stderr, "no dcd offset given ('dcdofs'). Defaulting to 0x400\n");
image_dcd_offset = 0x400;
}
if (!header_version) {
fprintf(stderr, "no SoC given. (missing 'soc' in config)\n");
exit(1);
}
if (header_version == 2)
check_last_dcd(0);
if (dcd_only) {
ret = write_dcd(outfile);
if (ret)
exit(1);
exit (0);
}
switch (header_version) {
case 1:
add_header_v1(buf, image_dcd_offset, image_load_addr, image_size + 0x1000);
break;
case 2:
add_header_v2(buf, image_dcd_offset, image_load_addr, image_size + 0x1000);
break;
default:
fprintf(stderr, "Congratulations! You're welcome to implement header version %d\n",
header_version);
exit(1);
}
outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (outfd < 0) {
perror("open");
exit(1);
}
ret = xwrite(outfd, buf, 4096);
if (ret < 0) {
perror("write");
exit(1);
}
infd = open(imagename, O_RDONLY);
if (infd < 0) {
perror("open");
exit(1);
}
while (image_size) {
int now = image_size < 4096 ? image_size : 4096;
ret = xread(infd, buf, now);
if (ret) {
perror("read");
exit(1);
}
ret = xwrite(outfd, buf, now);
if (ret) {
perror("write");
exit(1);
}
image_size -= now;
}
ret = close(outfd);
if (ret) {
perror("close");
exit(1);
}
exit(0);
}

1427
scripts/imx/imx-usb-loader.c Normal file

File diff suppressed because it is too large Load Diff