summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-02-08 08:26:35 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2016-02-08 08:26:35 +0100
commit6435fb09d8af3aeae7c6f8428f5e7ade15aca6f5 (patch)
tree47688a764f75d4c90ef2f233e214bea2d3110ffb /scripts
parent129fb7d893a067232b28a471c4d24a0638404c95 (diff)
parent1db47f7616b1b9940e34c9b1d3ba17de36e957a0 (diff)
downloadbarebox-6435fb09d8af3aeae7c6f8428f5e7ade15aca6f5.tar.gz
barebox-6435fb09d8af3aeae7c6f8428f5e7ade15aca6f5.tar.xz
Merge branch 'for-next/hab'
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile1
-rw-r--r--scripts/Makefile.lib4
-rwxr-xr-xscripts/habv4/gencsf.sh47
-rw-r--r--scripts/habv4/habv4-imx28.csf.in33
-rw-r--r--scripts/habv4/habv4-imx6.csf.in37
-rw-r--r--scripts/imx/Makefile8
-rw-r--r--scripts/imx/imx-image.c826
-rw-r--r--scripts/imx/imx-usb-loader.c671
-rw-r--r--scripts/imx/imx.c444
-rw-r--r--scripts/imx/imx.h72
-rw-r--r--scripts/include/asm-generic/atomic-gcc.h63
-rw-r--r--scripts/include/asm-generic/barrier.h44
-rw-r--r--scripts/include/asm-generic/bitops.h29
-rw-r--r--scripts/include/asm-generic/bitops/__ffs.h43
-rw-r--r--scripts/include/asm-generic/bitops/__fls.h1
-rw-r--r--scripts/include/asm-generic/bitops/arch_hweight.h1
-rw-r--r--scripts/include/asm-generic/bitops/atomic.h22
-rw-r--r--scripts/include/asm-generic/bitops/const_hweight.h1
-rw-r--r--scripts/include/asm-generic/bitops/find.h33
-rw-r--r--scripts/include/asm-generic/bitops/fls.h1
-rw-r--r--scripts/include/asm-generic/bitops/fls64.h1
-rw-r--r--scripts/include/asm-generic/bitops/hweight.h7
-rw-r--r--scripts/include/asm/atomic.h10
-rw-r--r--scripts/include/asm/barrier.h27
-rw-r--r--scripts/include/asm/bug.h25
-rw-r--r--scripts/include/linux/atomic.h6
-rw-r--r--scripts/include/linux/bitmap.h68
-rw-r--r--scripts/include/linux/bitops.h58
-rw-r--r--scripts/include/linux/compiler.h118
-rw-r--r--scripts/include/linux/err.h49
-rw-r--r--scripts/include/linux/export.h10
-rw-r--r--scripts/include/linux/kernel.h109
-rw-r--r--scripts/include/linux/list.h771
-rw-r--r--scripts/include/linux/log2.h185
-rw-r--r--scripts/include/linux/poison.h1
-rw-r--r--scripts/include/linux/string.h15
-rw-r--r--scripts/include/linux/types.h83
-rw-r--r--scripts/include/tools/be_byteshift.h70
-rw-r--r--scripts/include/tools/endian.h56
-rw-r--r--scripts/include/tools/le_byteshift.h70
-rw-r--r--scripts/mxsimage.c4
41 files changed, 3194 insertions, 930 deletions
diff --git a/scripts/Makefile b/scripts/Makefile
index a3f6222d08..aeedcac58b 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -20,6 +20,7 @@ hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader
hostprogs-$(CONFIG_ARCH_ZYNQ) += zynq_mkimage
hostprogs-$(CONFIG_ARCH_SOCFPGA) += socfpga_mkimage
hostprogs-$(CONFIG_ARCH_MXS) += mxsimage mxsboot
+HOSTCFLAGS += -I$(srctree)/scripts/include/
HOSTLOADLIBES_mxsimage = `pkg-config --libs openssl`
HOSTCFLAGS_mxs-usb-loader.o = `pkg-config --cflags libusb-1.0`
HOSTLOADLIBES_mxs-usb-loader = `pkg-config --libs libusb-1.0`
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index e991f33691..27365d8df8 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -430,8 +430,8 @@ $(obj)/%.dcd.S: $(obj)/%.dcd
imximg-tmp = $(subst $(comma),_,$(dot-target).imxcfg.tmp)
quiet_cmd_imx_image = IMX-IMG $@
- cmd_imx_image = $(CPP) $(imxcfg_cpp_flags) -o $(imximg-tmp) $(CFG_$(@F)) ; \
- $(objtree)/scripts/imx/imx-image -o $@ -b -c $(imximg-tmp) -f $<
+ cmd_imx_image = $(CPP) $(imxcfg_cpp_flags) -o $(imximg-tmp) $(2) ; \
+ $(objtree)/scripts/imx/imx-image -o $@ -b -c $(imximg-tmp) $(3) -f $<
quiet_cmd_kwb_image = KWB $@
cmd_kwb_image = scripts/kwbimage -p $< $(OPTS_$(@F)) -o $@
diff --git a/scripts/habv4/gencsf.sh b/scripts/habv4/gencsf.sh
deleted file mode 100755
index 2c1c34add4..0000000000
--- a/scripts/habv4/gencsf.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-
-set -e
-
-while getopts "f:c:i:o:" opt; do
- case $opt in
- f)
- file=$OPTARG
- ;;
- c)
- cfg=$OPTARG
- ;;
- i)
- in=$OPTARG
- ;;
- o)
- out=$OPTARG
- ;;
- \?)
- echo "Invalid option: -$OPTARG" >&2
- exit 1
- ;;
- esac
-done
-
-if [ ! -e $file -o ! -e $cfg -o ! -e $in ]; then
- echo "file not found!"
- exit 1
-fi
-
-#
-# extract and set as shell vars:
-# loadaddr=
-# dcdofs=
-#
-eval $(sed -n -e "s/^[[:space:]]*\(loadaddr\|dcdofs\)[[:space:]]*\(0x[0-9]*\)/\1=\2/p" $cfg)
-
-length=$(stat -c '%s' $file)
-
-sed -e "s:@TABLE_BIN@:$TABLE_BIN:" \
- -e "s:@CSF_CRT_PEM@:$CSF_CRT_PEM:" \
- -e "s:@IMG_CRT_PEM@:$IMG_CRT_PEM:" \
- -e "s:@LOADADDR@:$loadaddr:" \
- -e "s:@OFFSET@:0:" \
- -e "s:@LENGTH@:$length:" \
- -e "s:@FILE@:$file:" \
- $in > $out
diff --git a/scripts/habv4/habv4-imx28.csf.in b/scripts/habv4/habv4-imx28.csf.in
deleted file mode 100644
index 5efd25b1e5..0000000000
--- a/scripts/habv4/habv4-imx28.csf.in
+++ /dev/null
@@ -1,33 +0,0 @@
-[Header]
-Version = 4.0
-Hash Algorithm = sha256
-Engine Configuration = 0
-Certificate Format = X509
-Signature Format = CMS
-Engine = DCP
-
-[Install SRK]
-File = "@TABLE_BIN@"
-# SRK index within SRK-Table 0..3
-Source index = 0
-
-[Install CSFK]
-File = "@CSF_CRT_PEM@"
-
-[Authenticate CSF]
-
-[Install Key]
-# verification key index in key store (0, 2...5)
-Verification index = 0
-# target key index in key store (2...5)
-Target index = 2
-File = "@IMG_CRT_PEM@"
-
-[Authenticate Data]
-# verification key index in key store (2...5)
-Verification index = 2
-# "starting load address in memory"
-# "starting offset within the source file"
-# "length (in bytes)"
-# "file (binary)"
-Blocks = @LOADADDR@ @OFFSET@ @LENGTH@ "@FILE@"
diff --git a/scripts/habv4/habv4-imx6.csf.in b/scripts/habv4/habv4-imx6.csf.in
deleted file mode 100644
index 11a5db9494..0000000000
--- a/scripts/habv4/habv4-imx6.csf.in
+++ /dev/null
@@ -1,37 +0,0 @@
-[Header]
-Version = 4.1
-Hash Algorithm = sha256
-Engine Configuration = 0
-Certificate Format = X509
-Signature Format = CMS
-Engine = CAAM
-
-[Install SRK]
-File = "@TABLE_BIN@"
-# SRK index within SRK-Table 0..3
-Source index = 0
-
-[Install CSFK]
-File = "@CSF_CRT_PEM@"
-
-[Authenticate CSF]
-
-[Unlock]
-Engine = CAAM
-Features = RNG
-
-[Install Key]
-# verification key index in key store (0, 2...5)
-Verification index = 0
-# target key index in key store (2...5)
-Target index = 2
-File = "@IMG_CRT_PEM@"
-
-[Authenticate Data]
-# verification key index in key store (2...5)
-Verification index = 2
-# "starting load address in memory"
-# "starting offset within the source file"
-# "length (in bytes)"
-# "file (binary)"
-Blocks = @LOADADDR@ @OFFSET@ @LENGTH@ "@FILE@"
diff --git a/scripts/imx/Makefile b/scripts/imx/Makefile
index ee0acc1514..d9f0c51298 100644
--- a/scripts/imx/Makefile
+++ b/scripts/imx/Makefile
@@ -7,6 +7,10 @@ HOSTCFLAGS_imx-usb-loader.o = `pkg-config --cflags libusb-1.0`
HOSTLOADLIBES_imx-usb-loader = `pkg-config --libs libusb-1.0`
HOSTCFLAGS_imx-image.o = -I$(srctree)
+ifdef CONFIG_ARCH_IMX_IMXIMAGE_SSL_SUPPORT
+HOSTCFLAGS_imx-image.o += -DIMXIMAGE_SSL_SUPPORT
+HOSTLOADLIBES_imx-image = `pkg-config --libs openssl`
+endif
-imx-usb-loader-objs := imx-usb-loader.o
-imx-image-objs := imx-image.o
+imx-usb-loader-objs := imx-usb-loader.o imx.o
+imx-image-objs := imx-image.o imx.o
diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c
index e8d9dbf23e..20815bfb98 100644
--- a/scripts/imx/imx-image.c
+++ b/scripts/imx/imx-image.c
@@ -15,6 +15,7 @@
* GNU General Public License for more details.
*
*/
+#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
@@ -26,45 +27,29 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <endian.h>
+#include <linux/kernel.h>
+#include <sys/file.h>
-#include <include/filetype.h>
+#include "imx.h"
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
-#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#include <include/filetype.h>
#define MAX_DCD 1024
-#define HEADER_LEN 0x1000 /* length of the blank area + IVT + DCD */
#define CSF_LEN 0x2000 /* length of the CSF (needed for HAB) */
-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 cpu_type;
static int add_barebox_header;
-static int prepare_sign;
+static int create_usb_image;
+static char *prgname;
/*
* ============================================================================
* 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 */
@@ -89,11 +74,141 @@ static uint32_t bb_header[] = {
0x55555555,
};
-static int add_header_v1(void *buf, int offset, uint32_t loadaddr, uint32_t imagesize)
+struct hab_rsa_public_key {
+ uint8_t rsa_exponent[4]; /* RSA public exponent */
+ uint32_t rsa_modulus; /* RSA modulus pointer */
+ uint16_t exponent_size; /* Exponent size in bytes */
+ uint16_t modulus_size; /* Modulus size in bytes*/
+ uint8_t init_flag; /* Indicates if key initialized */
+};
+
+#ifdef IMXIMAGE_SSL_SUPPORT
+#define PUBKEY_ALGO_LEN 2048
+
+#include <openssl/x509v3.h>
+#include <openssl/bn.h>
+#include <openssl/asn1.h>
+#include <openssl/x509.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/pem.h>
+#include <openssl/bio.h>
+
+static int extract_key(const char *certfile, uint8_t **modulus, int *modulus_len,
+ uint8_t **exponent, int *exponent_len)
+{
+ char buf[PUBKEY_ALGO_LEN];
+ int pubkey_algonid;
+ const char *sslbuf;
+ EVP_PKEY *pkey;
+ FILE *fp;
+ X509 *cert;
+ RSA *rsa_key;
+
+ fp = fopen(certfile, "r");
+ if (!fp) {
+ fprintf(stderr, "unable to open certfile: %s\n", certfile);
+ return -errno;
+ }
+
+ cert = PEM_read_X509(fp, NULL, NULL, NULL);
+ if (!cert) {
+ fprintf(stderr, "unable to parse certificate in: %s\n", certfile);
+ fclose(fp);
+ return -errno;
+ }
+
+ fclose(fp);
+
+ pubkey_algonid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm);
+ if (pubkey_algonid == NID_undef) {
+ fprintf(stderr, "unable to find specified public key algorithm name.\n");
+ return -EINVAL;
+ }
+
+ if (pubkey_algonid != NID_rsaEncryption)
+ return -EINVAL;
+
+ sslbuf = OBJ_nid2ln(pubkey_algonid);
+ strncpy(buf, sslbuf, PUBKEY_ALGO_LEN);
+
+ pkey = X509_get_pubkey(cert);
+ if (!pkey) {
+ fprintf(stderr, "unable to extract public key from certificate");
+ return -EINVAL;
+ }
+
+ rsa_key = pkey->pkey.rsa;
+ if (!rsa_key) {
+ fprintf(stderr, "unable to extract RSA public key");
+ return -EINVAL;
+ }
+
+ *modulus_len = BN_num_bytes(rsa_key->n);
+ *modulus = malloc(*modulus_len);
+ BN_bn2bin(rsa_key->n, *modulus);
+
+ *exponent_len = BN_num_bytes(rsa_key->e);
+ *exponent = malloc(*exponent_len);
+ BN_bn2bin(rsa_key->e, *exponent);
+
+ EVP_PKEY_free(pkey);
+ X509_free(cert);
+
+ return 0;
+}
+
+static int add_srk(void *buf, int offset, uint32_t loadaddr, const char *srkfile)
+{
+ struct imx_flash_header *hdr = buf + offset;
+ struct hab_rsa_public_key *key = buf + 0xc00;
+ uint8_t *exponent = NULL, *modulus = NULL, *modulus_dest;
+ int exponent_len = 0, modulus_len = 0;
+ int ret;
+
+ hdr->super_root_key = loadaddr + 0xc00;
+
+ key->init_flag = 1;
+ key->exponent_size = htole16(3);
+
+ ret = extract_key(srkfile, &modulus, &modulus_len, &exponent, &exponent_len);
+ if (ret)
+ return ret;
+
+ modulus_dest = (void *)(key + 1);
+
+ memcpy(modulus_dest, modulus, modulus_len);
+
+ key->modulus_size = htole16(modulus_len);
+ key->rsa_modulus = htole32(hdr->super_root_key + sizeof(*key));
+
+ if (exponent_len > 4)
+ return -EINVAL;
+
+ key->exponent_size = exponent_len;
+ memcpy(&key->rsa_exponent, exponent, key->exponent_size);
+
+ return 0;
+}
+#else
+static int add_srk(void *buf, int offset, uint32_t loadaddr, const char *srkfile)
+{
+ fprintf(stderr, "This version of imx-image is compiled without SSL support\n");
+
+ return -EINVAL;
+}
+#endif /* IMXIMAGE_SSL_SUPPORT */
+
+static int dcd_ptr_offset;
+static uint32_t dcd_ptr_content;
+
+static int add_header_v1(struct config_data *data, void *buf)
{
struct imx_flash_header *hdr;
int dcdsize = curdcd * sizeof(uint32_t);
uint32_t *psize = buf + ARM_HEAD_SIZE_OFFSET;
+ int offset = data->image_dcd_offset;
+ uint32_t loadaddr = data->image_load_addr;
+ uint32_t imagesize = data->load_size;
if (add_barebox_header) {
memcpy(buf, bb_header, sizeof(bb_header));
@@ -108,10 +223,17 @@ static int add_header_v1(void *buf, int offset, uint32_t loadaddr, uint32_t imag
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->dcd = loadaddr + offset + offsetof(struct imx_flash_header, dcd_barker);
+
hdr->app_dest = loadaddr;
hdr->dcd_barker = DCD_BARKER;
- hdr->dcd_block_len = dcdsize;
+ if (create_usb_image) {
+ dcd_ptr_offset = offsetof(struct imx_flash_header, dcd_block_len) + offset;
+ hdr->dcd_block_len = 0;
+ dcd_ptr_content = dcdsize;
+ } else {
+ hdr->dcd_block_len = dcdsize;
+ }
buf += sizeof(struct imx_flash_header);
@@ -119,6 +241,11 @@ static int add_header_v1(void *buf, int offset, uint32_t loadaddr, uint32_t imag
buf += dcdsize;
+ if (data->csf) {
+ hdr->app_code_csf = loadaddr + imagesize;
+ imagesize += CSF_LEN;
+ }
+
*(uint32_t *)buf = imagesize;
return 0;
@@ -144,45 +271,14 @@ static int write_mem_v1(uint32_t addr, uint32_t val, int width)
* ============================================================================
*/
-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)
+static int add_header_v2(struct config_data *data, void *buf)
{
struct imx_flash_header_v2 *hdr;
int dcdsize = curdcd * sizeof(uint32_t);
uint32_t *psize = buf + ARM_HEAD_SIZE_OFFSET;
+ int offset = data->image_dcd_offset;
+ uint32_t loadaddr = data->image_load_addr;
+ uint32_t imagesize = data->load_size;
if (add_barebox_header)
memcpy(buf, bb_header, sizeof(bb_header));
@@ -196,13 +292,18 @@ static int add_header_v2(void *buf, int offset, uint32_t loadaddr, uint32_t imag
hdr->entry = loadaddr + HEADER_LEN;
hdr->dcd_ptr = loadaddr + offset + offsetof(struct imx_flash_header_v2, dcd_header);
+ if (create_usb_image) {
+ dcd_ptr_content = hdr->dcd_ptr;
+ dcd_ptr_offset = offsetof(struct imx_flash_header_v2, dcd_ptr) + offset;
+ hdr->dcd_ptr = 0;
+ }
hdr->boot_data_ptr = loadaddr + offset + offsetof(struct imx_flash_header_v2, boot_data);
hdr->self = loadaddr + offset;
hdr->boot_data.start = loadaddr;
hdr->boot_data.size = imagesize;
- if (prepare_sign) {
+ if (data->csf) {
hdr->csf = loadaddr + imagesize;
hdr->boot_data.size += CSF_LEN;
}
@@ -230,55 +331,10 @@ static void usage(const char *prgname)
"-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"
- "-p prepare image for signing\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_write_cmd;
static int last_cmd_len;
static uint32_t *last_dcd;
@@ -324,67 +380,64 @@ static int write_mem_v2(uint32_t addr, uint32_t val, int width)
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)
+static int xread(int fd, void *buf, int len)
{
- 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");
+ 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 do_cmd_check(int argc, char *argv[])
+static int xwrite(int fd, void *buf, int len)
{
- uint32_t addr, mask, cmd;
- int i, width;
- const char *scmd;
+ int ret;
- if (argc < 5) {
- do_cmd_check_usage();
- return -EINVAL;
+ while (len) {
+ ret = write(fd, buf, len);
+ if (ret < 0)
+ return ret;
+ buf += ret;
+ len -= ret;
}
- width = strtoul(argv[1], NULL, 0) >> 3;
- scmd = argv[2];
- addr = strtoul(argv[3], NULL, 0);
- mask = strtoul(argv[4], NULL, 0);
+ return 0;
+}
- switch (width) {
- case 1:
- case 2:
- case 4:
- break;
- default:
- fprintf(stderr, "illegal width %d\n", width);
- return -EINVAL;
- };
+static int write_dcd(const char *outfile)
+{
+ int outfd, ret;
+ int dcdsize = curdcd * sizeof(uint32_t);
- if (curdcd > MAX_DCD - 3) {
- fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD);
- return -ENOMEM;
+ outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ if (outfd < 0) {
+ perror("open");
+ exit(1);
}
- for (i = 0; i < ARRAY_SIZE(check_cmds); i++) {
- if (!strcmp(scmd, check_cmds[i]))
- break;
+ ret = xwrite(outfd, dcdtable, dcdsize);
+ if (ret < 0) {
+ perror("write");
+ exit(1);
}
- if (i == ARRAY_SIZE(check_cmds)) {
- do_cmd_check_usage();
- return -EINVAL;
- }
+ return 0;
+}
- cmd = (TAG_CHECK << 24) | (i << 3) | width | ((sizeof(uint32_t) * 3) << 8);
+static int check(struct config_data *data, uint32_t cmd, uint32_t addr, uint32_t mask)
+{
+ if (curdcd > MAX_DCD - 3) {
+ fprintf(stderr, "At maximum %d dcd entried are allowed\n", MAX_DCD);
+ return -ENOMEM;
+ }
check_last_dcd(cmd);
@@ -395,47 +448,9 @@ static int do_cmd_check(int argc, char *argv[])
return 0;
}
-static int do_cmd_write_mem(int argc, char *argv[])
+static int write_mem(struct config_data *data, uint32_t addr, uint32_t val, int width)
{
- uint32_t addr, val, width;
- char *end;
-
- if (argc != 4) {
- fprintf(stderr, "usage: wm [8|16|32] <addr> <val>\n");
- return -EINVAL;
- }
-
- width = strtoul(argv[1], &end, 0);
- if (*end != '\0') {
- fprintf(stderr, "illegal width token \"%s\"\n", argv[1]);
- return -EINVAL;
- }
-
- addr = strtoul(argv[2], &end, 0);
- if (*end != '\0') {
- fprintf(stderr, "illegal address token \"%s\"\n", argv[2]);
- return -EINVAL;
- }
-
- val = strtoul(argv[3], &end, 0);
- if (*end != '\0') {
- fprintf(stderr, "illegal value token \"%s\"\n", argv[3]);
- return -EINVAL;
- }
-
- width >>= 3;
-
- switch (width) {
- case 1:
- case 2:
- case 4:
- break;
- default:
- fprintf(stderr, "illegal width %d\n", width);
- return -EINVAL;
- };
-
- switch (header_version) {
+ switch (data->header_version) {
case 1:
return write_mem_v1(addr, val, width);
case 2:
@@ -445,218 +460,158 @@ static int do_cmd_write_mem(int argc, char *argv[])
}
}
-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;
- int cpu_type;
-};
-
-static struct soc_type socs[] = {
- { .name = "imx25", .header_version = 1, .cpu_type = 25},
- { .name = "imx35", .header_version = 1, .cpu_type = 35 },
- { .name = "imx51", .header_version = 1, .cpu_type = 51 },
- { .name = "imx53", .header_version = 2, .cpu_type = 53 },
- { .name = "imx6", .header_version = 2, .cpu_type = 6 },
-};
-
-static int do_soc(int argc, char *argv[])
+/*
+ * This uses the Freescale Code Signing Tool (CST) to sign the image.
+ * The cst is expected to be executable as 'cst' or if exists, the content
+ * of the environment variable 'CST' is used.
+ */
+static int hab_sign(struct config_data *data)
{
- char *soc;
- int i;
+ int fd, outfd, ret, lockfd;
+ char *csffile, *command;
+ struct stat s;
+ char *cst;
+ void *buf;
- if (argc < 2)
- return -EINVAL;
+ cst = getenv("CST");
+ if (!cst)
+ cst = "cst";
- soc = argv[1];
+ ret = asprintf(&csffile, "%s.csfbin", data->outfile);
+ if (ret < 0)
+ exit(1);
- for (i = 0; i < ARRAY_SIZE(socs); i++) {
- if (!strcmp(socs[i].name, soc)) {
- header_version = socs[i].header_version;
- cpu_type = socs[i].cpu_type;
- return 0;
+ ret = stat(csffile, &s);
+ if (!ret) {
+ if (S_ISREG(s.st_mode)) {
+ ret = unlink(csffile);
+ if (ret) {
+ fprintf(stderr, "Cannot remove %s: %s\n",
+ csffile, strerror(errno));
+ return -errno;
+ }
+ } else {
+ fprintf(stderr, "%s exists and is no regular file\n",
+ csffile);
+ return -EINVAL;
}
}
- 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 char *readcmd(FILE *f)
-{
- static char *buf;
- char *str;
- ssize_t ret;
+ ret = asprintf(&command, "%s -o %s", cst, csffile);
+ if (ret < 0)
+ return -ENOMEM;
- if (!buf) {
- buf = malloc(4096);
- if (!buf)
- return NULL;
+ /*
+ * The cst uses "csfsig.bin" as temporary file. This of course breaks when it's
+ * called multiple times as often happens with parallel builds. Until cst learns
+ * how to properly create temporary files without races lock accesses to this
+ * file.
+ */
+ lockfd = open(prgname, O_RDONLY);
+ if (lockfd < 0) {
+ fprintf(stderr, "Cannot open csfsig.bin: %s\n", strerror(errno));
+ return -errno;
}
- str = buf;
- *str = 0;
-
- while (1) {
- ret = fread(str, 1, 1, f);
- if (!ret)
- return strlen(buf) ? buf : NULL;
-
- if (*str == '\n' || *str == ';') {
- *str = 0;
- return buf;
- }
-
- str++;
+ ret = flock(lockfd, LOCK_EX);
+ if (ret) {
+ fprintf(stderr, "Cannot lock csfsig.bin: %s\n", strerror(errno));
+ return -errno;
}
-}
-static int parse_config(const char *filename)
-{
- FILE *f;
- int lineno = 0;
- char *line = NULL, *tmp;
- char *argv[MAXARGS];
- int nargs, i, ret = 0;
-
- f = fopen(filename, "r");
+ FILE *f = popen(command, "w");
if (!f) {
- fprintf(stderr, "Error: %s - Can't open DCD file\n", filename);
- exit(1);
+ perror("popen");
+ return -errno;
}
- while (1) {
- line = readcmd(f);
- if (!line)
- break;
-
- lineno++;
-
- tmp = strchr(line, '#');
- if (tmp)
- *tmp = 0;
+ fwrite(data->csf, 1, strlen(data->csf) + 1, f);
- nargs = parse_line(line, argv);
- if (!nargs)
- continue;
+ pclose(f);
- ret = -ENOENT;
+ flock(lockfd, LOCK_UN);
+ close(lockfd);
- 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));
- goto cleanup;
- }
- break;
- }
- }
+ /*
+ * the Freescale code signing tool doesn't fail if there
+ * are errors in the command sequence file, it just doesn't
+ * produce any output, so we have to check for existence of
+ * the output file rather than checking the return value of
+ * the cst call.
+ */
+ fd = open(csffile, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n", csffile, strerror(errno));
+ fprintf(stderr, "%s failed\n", cst);
+ return -errno;
+ }
- if (ret == -ENOENT) {
- fprintf(stderr, "no such command: %s\n", argv[0]);
- goto cleanup;
- }
+ ret = fstat(fd, &s);
+ if (ret < 0) {
+ fprintf(stderr, "stat failed: %s\n", strerror(errno));
+ return -errno;
}
-cleanup:
- fclose(f);
- return ret;
-}
+ buf = malloc(CSF_LEN);
+ if (!buf)
+ return -ENOMEM;
-static int xread(int fd, void *buf, int len)
-{
- int ret;
+ memset(buf, 0x5a, CSF_LEN);
- while (len) {
- ret = read(fd, buf, len);
- if (ret < 0)
- return ret;
- if (!ret)
- return EOF;
- buf += ret;
- len -= ret;
+ if (s.st_size > CSF_LEN) {
+ fprintf(stderr, "CSF file size exceeds maximum CSF len of %d bytes\n",
+ CSF_LEN);
}
- return 0;
-}
+ ret = xread(fd, buf, s.st_size);
+ if (ret < 0) {
+ fprintf(stderr, "read failed: %s\n", strerror(errno));
+ return -errno;
+ }
-static int xwrite(int fd, void *buf, int len)
-{
- int ret;
+ outfd = open(data->outfile, O_WRONLY | O_APPEND);
- while (len) {
- ret = write(fd, buf, len);
- if (ret < 0)
- return ret;
- buf += ret;
- len -= ret;
+ ret = xwrite(outfd, buf, CSF_LEN);
+ if (ret < 0) {
+ fprintf(stderr, "write failed: %s\n", strerror(errno));
+ return -errno;
+ }
+
+ ret = close(outfd);
+ if (ret) {
+ perror("close");
+ exit(1);
}
return 0;
}
-static int write_dcd(const char *outfile)
+static void *read_file(const char *filename, size_t *size)
{
- int outfd, ret;
- int dcdsize = curdcd * sizeof(uint32_t);
+ int fd, ret;
+ void *buf;
+ struct stat s;
- outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
- if (outfd < 0) {
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
perror("open");
exit(1);
}
- ret = xwrite(outfd, dcdtable, dcdsize);
- if (ret < 0) {
- perror("write");
+ ret = fstat(fd, &s);
+ if (ret)
+ return NULL;
+
+ *size = s.st_size;
+ buf = malloc(*size);
+ if (!buf)
exit(1);
- }
- return 0;
+ xread(fd, buf, *size);
+
+ close(fd);
+
+ return buf;
}
int main(int argc, char *argv[])
@@ -664,16 +619,23 @@ 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, load_size, insize;
+ size_t insize;
void *infile;
struct stat s;
- int infd, outfd;
+ int outfd;
int dcd_only = 0;
int now = 0;
+ int sign_image = 0;
+ struct config_data data = {
+ .image_dcd_offset = 0xffffffff,
+ .write_mem = write_mem,
+ .check = check,
+ };
- while ((opt = getopt(argc, argv, "c:hf:o:bdp")) != -1) {
+ prgname = argv[0];
+
+ while ((opt = getopt(argc, argv, "c:hf:o:bdus")) != -1) {
switch (opt) {
case 'c':
configfile = optarg;
@@ -682,7 +644,7 @@ int main(int argc, char *argv[])
imagename = optarg;
break;
case 'o':
- outfile = optarg;
+ data.outfile = optarg;
break;
case 'b':
add_barebox_header = 1;
@@ -690,8 +652,11 @@ int main(int argc, char *argv[])
case 'd':
dcd_only = 1;
break;
- case 'p':
- prepare_sign = 1;
+ case 's':
+ sign_image = 1;
+ break;
+ case 'u':
+ create_usb_image = 1;
break;
case 'h':
usage(argv[0]);
@@ -710,7 +675,7 @@ int main(int argc, char *argv[])
exit(1);
}
- if (!outfile) {
+ if (!data.outfile) {
fprintf(stderr, "output file not given\n");
exit(1);
}
@@ -722,83 +687,81 @@ int main(int argc, char *argv[])
exit(1);
}
- image_size = s.st_size;
+ data.image_size = s.st_size;
}
- ret = parse_config(configfile);
+ /*
+ * Add HEADER_LEN to the image size for the blank aera + IVT + DCD.
+ * Align up to a 4k boundary, because:
+ * - at least i.MX5 NAND boot only reads full NAND pages and misses the
+ * last partial NAND page.
+ * - i.MX6 SPI NOR boot corrupts the last few bytes of an image loaded
+ * in ver funy ways when the image size is not 4 byte aligned
+ */
+ data.load_size = roundup(data.image_size + HEADER_LEN, 0x1000);
+
+ ret = parse_config(&data, configfile);
if (ret)
exit(1);
+ if (!sign_image)
+ data.csf = NULL;
+
+ if (create_usb_image && !data.csf) {
+ fprintf(stderr, "Warning: the -u option only has effect with signed images\n");
+ create_usb_image = 0;
+ }
+
buf = calloc(1, HEADER_LEN);
if (!buf)
exit(1);
- if (!image_dcd_offset) {
- fprintf(stderr, "no dcd offset given ('dcdofs'). Defaulting to 0x%08x\n",
- FLASH_HEADER_OFFSET);
- image_dcd_offset = FLASH_HEADER_OFFSET;
+ if (data.image_dcd_offset == 0xffffffff) {
+ if (create_usb_image)
+ data.image_dcd_offset = 0x0;
+ else
+ data.image_dcd_offset = FLASH_HEADER_OFFSET;
}
- if (!header_version) {
+ if (!data.header_version) {
fprintf(stderr, "no SoC given. (missing 'soc' in config)\n");
exit(1);
}
- if (header_version == 2)
+ if (data.header_version == 2)
check_last_dcd(0);
if (dcd_only) {
- ret = write_dcd(outfile);
+ ret = write_dcd(data.outfile);
if (ret)
exit(1);
exit (0);
}
- /*
- * Add HEADER_LEN to the image size for the blank aera + IVT + DCD.
- * Align up to a 4k boundary, because:
- * - at least i.MX5 NAND boot only reads full NAND pages and misses the
- * last partial NAND page.
- * - i.MX6 SPI NOR boot corrupts the last few bytes of an image loaded
- * in ver funy ways when the image size is not 4 byte aligned
- */
- load_size = roundup(image_size + HEADER_LEN, 0x1000);
-
- if (cpu_type == 35)
- load_size += HEADER_LEN;
-
- switch (header_version) {
+ switch (data.header_version) {
case 1:
- add_header_v1(buf, image_dcd_offset, image_load_addr, load_size);
+ add_header_v1(&data, buf);
+ if (data.srkfile) {
+ ret = add_srk(buf, data.image_dcd_offset, data.image_load_addr,
+ data.srkfile);
+ if (ret)
+ exit(1);
+ }
break;
case 2:
- add_header_v2(buf, image_dcd_offset, image_load_addr, load_size);
+ add_header_v2(&data, buf);
break;
default:
fprintf(stderr, "Congratulations! You're welcome to implement header version %d\n",
- header_version);
- exit(1);
- }
-
- infd = open(imagename, O_RDONLY);
- if (infd < 0) {
- perror("open");
+ data.header_version);
exit(1);
}
- ret = fstat(infd, &s);
- if (ret)
- return ret;
-
- insize = s.st_size;
- infile = malloc(insize);
+ infile = read_file(imagename, &insize);
if (!infile)
exit(1);
- xread(infd, infile, insize);
- close(infd);
-
- outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
+ outfd = open(data.outfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (outfd < 0) {
perror("open");
exit(1);
@@ -810,7 +773,7 @@ int main(int argc, char *argv[])
exit(1);
}
- if (cpu_type == 35) {
+ if (data.cpu_type == 35) {
ret = xwrite(outfd, buf, HEADER_LEN);
if (ret < 0) {
perror("write");
@@ -826,7 +789,7 @@ int main(int argc, char *argv[])
/* pad until next 4k boundary */
now = 4096 - (insize % 4096);
- if (prepare_sign && now) {
+ if (data.csf && now) {
memset(buf, 0x5a, now);
ret = xwrite(outfd, buf, now);
@@ -842,5 +805,34 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (data.csf) {
+ ret = hab_sign(&data);
+ if (ret)
+ exit(1);
+ }
+
+ if (create_usb_image) {
+ uint32_t *dcd;
+
+ infile = read_file(data.outfile, &insize);
+
+ dcd = infile + dcd_ptr_offset;
+ *dcd = dcd_ptr_content;
+
+ outfd = open(data.outfile, O_WRONLY | O_TRUNC);
+ if (outfd < 0) {
+ fprintf(stderr, "Cannot open %s: %s\n", data.outfile, strerror(errno));
+ exit(1);
+ }
+
+ ret = xwrite(outfd, infile, insize);
+ if (ret < 0) {
+ perror("write");
+ exit (1);
+ }
+
+ close(outfd);
+ }
+
exit(0);
}
diff --git a/scripts/imx/imx-usb-loader.c b/scripts/imx/imx-usb-loader.c
index 195b27b8ee..ed27831386 100644
--- a/scripts/imx/imx-usb-loader.c
+++ b/scripts/imx/imx-usb-loader.c
@@ -32,10 +32,21 @@
#include <stdlib.h>
#include <libusb.h>
#include <getopt.h>
+#include <linux/kernel.h>
+
+#include "imx.h"
#define get_min(a, b) (((a) < (b)) ? (a) : (b))
+#define FT_APP 0xaa
+#define FT_CSF 0xcc
+#define FT_DCD 0xee
+#define FT_LOAD_ONLY 0x00
+
int verbose;
+static int skip_image_dcd;
+static struct libusb_device_handle *usb_dev_handle;
+static struct usb_id *usb_id;
struct mach_id {
struct mach_id * next;
@@ -53,11 +64,6 @@ struct mach_id {
unsigned short max_transfer;
};
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-#ifndef offsetof
-#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
-#endif
-
struct usb_work {
char filename[256];
unsigned char dcd;
@@ -194,9 +200,10 @@ static libusb_device *find_imx_dev(libusb_device **devs, struct mach_id **pp_id)
return NULL;
}
-static void dump_long(unsigned char *src, unsigned cnt, unsigned addr)
+static void dump_long(const void *src, unsigned cnt, unsigned addr)
{
- unsigned *p = (unsigned *)src;
+ const unsigned *p = (unsigned *)src;
+
while (cnt >= 32) {
printf("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
addr, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
@@ -215,9 +222,9 @@ static void dump_long(unsigned char *src, unsigned cnt, unsigned addr)
}
}
-static void dump_bytes(unsigned char *src, unsigned cnt, unsigned addr)
+static void dump_bytes(const void *src, unsigned cnt, unsigned addr)
{
- unsigned char *p = src;
+ const unsigned char *p = src;
int i;
while (cnt >= 16) {
@@ -297,12 +304,11 @@ static long get_file_size(FILE *xfile)
* EP2IN - bulk in
* (max packet size of 512 bytes)
*/
-static int transfer(struct libusb_device_handle *h, int report, unsigned char *p, unsigned cnt,
- int* last_trans, struct usb_id *p_id)
+static int transfer(int report, unsigned char *p, unsigned cnt, int *last_trans)
{
int err;
- if (cnt > p_id->mach_id->max_transfer)
- cnt = p_id->mach_id->max_transfer;
+ if (cnt > usb_id->mach_id->max_transfer)
+ cnt = usb_id->mach_id->max_transfer;
if (verbose > 4) {
printf("report=%i\n", report);
@@ -310,9 +316,10 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
dump_bytes(p, cnt, 0);
}
- if (p_id->mach_id->mode == MODE_BULK) {
+ if (usb_id->mach_id->mode == MODE_BULK) {
*last_trans = 0;
- err = libusb_bulk_transfer(h, (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
+ err = libusb_bulk_transfer(usb_dev_handle,
+ (report < 3) ? 1 : 2 + EP_IN, p, cnt, last_trans, 1000);
} else {
unsigned char tmp[1028];
@@ -320,7 +327,7 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
if (report < 3) {
memcpy(&tmp[1], p, cnt);
- err = libusb_control_transfer(h,
+ err = libusb_control_transfer(usb_dev_handle,
CTRL_OUT,
HID_SET_REPORT,
(HID_REPORT_TYPE_OUTPUT << 8) | report,
@@ -332,7 +339,8 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
} else {
*last_trans = 0;
memset(&tmp[1], 0, cnt);
- err = libusb_interrupt_transfer(h, 1 + EP_IN, tmp, cnt + 1, last_trans, 1000);
+ err = libusb_interrupt_transfer(usb_dev_handle,
+ 1 + EP_IN, tmp, cnt + 1, last_trans, 1000);
if (err >= 0) {
if (tmp[0] == (unsigned char)report) {
if (*last_trans > 1) {
@@ -354,7 +362,7 @@ static int transfer(struct libusb_device_handle *h, int report, unsigned char *p
return err;
}
-int do_status(libusb_device_handle *h, struct usb_id *p_id)
+int do_status(void)
{
int last_trans;
unsigned char tmp[64];
@@ -369,14 +377,14 @@ int do_status(libusb_device_handle *h, struct usb_id *p_id)
};
for (;;) {
- err = transfer(h, 1, (unsigned char*)status_command, 16, &last_trans, p_id);
+ err = transfer(1, (unsigned char*)status_command, 16, &last_trans);
if (verbose > 2)
printf("report 1, wrote %i bytes, err=%i\n", last_trans, err);
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 3, tmp, 64, &last_trans, p_id);
+ err = transfer(3, tmp, 64, &last_trans);
if (verbose > 2) {
printf("report 3, read %i bytes, err=%i\n", last_trans, err);
@@ -392,8 +400,8 @@ int do_status(libusb_device_handle *h, struct usb_id *p_id)
break;
}
- if (p_id->mach_id->mode == MODE_HID) {
- err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id);
+ if (usb_id->mach_id->mode == MODE_HID) {
+ err = transfer(4, tmp, sizeof(tmp), &last_trans);
if (err)
printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
@@ -402,43 +410,9 @@ int do_status(libusb_device_handle *h, struct usb_id *p_id)
return err;
}
-struct boot_data {
- uint32_t dest;
- uint32_t image_len;
- uint32_t plugin;
-};
-
-struct imx_flash_header_v2 {
-#define IVT_BARKER 0x402000d1
- uint32_t barker;
- uint32_t start_addr;
- uint32_t reserv1;
- uint32_t dcd_ptr;
- uint32_t boot_data_ptr; /* struct boot_data * */
- uint32_t self_ptr; /* struct imx_flash_header_v2 *, this - boot_data.start = offset linked at */
- uint32_t app_code_csf;
- uint32_t reserv2;
-};
-
-/*
- * MX51 header type
- */
-struct imx_flash_header_v1 {
- uint32_t app_start_addr;
-#define APP_BARKER 0xb1
-#define DCD_BARKER 0xb17219e9
- uint32_t app_barker;
- uint32_t csf_ptr;
- uint32_t dcd_ptr_ptr;
- uint32_t srk_ptr;
- uint32_t dcd_ptr;
- uint32_t app_dest_ptr;
-};
-
#define V(a) (((a) >> 24) & 0xff), (((a) >> 16) & 0xff), (((a) >> 8) & 0xff), ((a) & 0xff)
-static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned addr, unsigned char *dest, unsigned cnt)
+static int read_memory(unsigned addr, unsigned char *dest, unsigned cnt)
{
static unsigned char read_reg_command[] = {
1,
@@ -466,7 +440,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
read_reg_command[10] = (unsigned char)(cnt);
for (;;) {
- err = transfer(h, 1, read_reg_command, 16, &last_trans, p_id);
+ err = transfer(1, read_reg_command, 16, &last_trans);
if (!err)
break;
printf("read_reg_command err=%i, last_trans=%i\n", err, last_trans);
@@ -476,7 +450,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
retry++;
}
- err = transfer(h, 3, tmp, 4, &last_trans, p_id);
+ err = transfer(3, tmp, 4, &last_trans);
if (err) {
printf("r3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
@@ -487,7 +461,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
while (rem) {
tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
- err = transfer(h, 4, tmp, 64, &last_trans, p_id);
+ err = transfer(4, tmp, 64, &last_trans);
if (err) {
printf("r4 in err=%i, last_trans=%i %02x %02x %02x %02x cnt=%u rem=%d\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3], cnt, rem);
@@ -511,8 +485,7 @@ static int read_memory(struct libusb_device_handle *h, struct usb_id *p_id,
return err;
}
-static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned addr, unsigned val, int width)
+static int write_memory(unsigned addr, unsigned val, int width)
{
int retry = 0;
int last_trans;
@@ -555,7 +528,7 @@ static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
write_reg_command[14] = (unsigned char)(val);
for (;;) {
- err = transfer(h, 1, write_reg_command, 16, &last_trans, p_id);
+ err = transfer(1, write_reg_command, 16, &last_trans);
if (!err)
break;
printf("write_reg_command err=%i, last_trans=%i\n", err, last_trans);
@@ -567,7 +540,7 @@ static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
if (err) {
printf("w3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
@@ -576,25 +549,109 @@ static int write_memory(struct libusb_device_handle *h, struct usb_id *p_id,
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id);
+ err = transfer(4, tmp, sizeof(tmp), &last_trans);
if (err)
printf("w4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
return err;
}
-static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_id,
- struct imx_flash_header_v2 *hdr, unsigned char *file_start, unsigned cnt)
+static int load_file(void *buf, unsigned len, unsigned dladdr, unsigned char type)
+{
+ static unsigned char dl_command[] = {
+ 0x04,
+ 0x04,
+ V(0), /* address */
+ 0x00, /* format */
+ V(0x00000020), /* data count */
+ V(0), /* data */
+ 0xaa, /* type */
+ };
+ int last_trans, err;
+ int retry = 0;
+ unsigned transfer_size = 0;
+ unsigned char tmp[64];
+ void *p;
+ int cnt;
+
+ dl_command[2] = (unsigned char)(dladdr >> 24);
+ dl_command[3] = (unsigned char)(dladdr >> 16);
+ dl_command[4] = (unsigned char)(dladdr >> 8);
+ dl_command[5] = (unsigned char)(dladdr);
+
+ dl_command[7] = (unsigned char)(len >> 24);
+ dl_command[8] = (unsigned char)(len >> 16);
+ dl_command[9] = (unsigned char)(len >> 8);
+ dl_command[10] = (unsigned char)(len);
+ dl_command[15] = type;
+
+ for (;;) {
+ err = transfer(1, dl_command, 16, &last_trans);
+ if (!err)
+ break;
+
+ printf("dl_command err=%i, last_trans=%i\n", err, last_trans);
+
+ if (retry > 5)
+ return -4;
+ retry++;
+ }
+
+ retry = 0;
+
+ if (usb_id->mach_id->mode == MODE_BULK) {
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
+ if (err)
+ printf("in err=%i, last_trans=%i %02x %02x %02x %02x\n",
+ err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
+ }
+
+ p = buf;
+ cnt = len;
+
+ while (1) {
+ int now = get_min(cnt, usb_id->mach_id->max_transfer);
+
+ if (!now)
+ break;
+
+ err = transfer(2, p, now, &now);
+ if (err) {
+ printf("dl_command err=%i, last_trans=%i\n", err, last_trans);
+ return err;
+ }
+
+ p += now;
+ cnt -= now;
+ }
+
+ if (usb_id->mach_id->mode == MODE_HID) {
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
+ if (err)
+ printf("3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
+ err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
+ err = transfer(4, tmp, sizeof(tmp), &last_trans);
+ if (err)
+ printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
+ err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
+ } else {
+ do_status();
+ }
+
+ return transfer_size;
+}
+
+static int write_dcd_table_ivt(struct imx_flash_header_v2 *hdr, unsigned char *file_start, unsigned cnt)
{
unsigned char *dcd_end;
unsigned m_length;
-#define cvt_dest_to_src (((unsigned char *)hdr) - hdr->self_ptr)
+#define cvt_dest_to_src (((unsigned char *)hdr) - hdr->self)
unsigned char* dcd;
unsigned char* file_end = file_start + cnt;
int err = 0;
if (!hdr->dcd_ptr) {
- printf("No dcd table, barker=%x\n", hdr->barker);
+ printf("No dcd table in this ivt\n");
return 0; /* nothing to do */
}
@@ -646,7 +703,7 @@ static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_
unsigned val = (dcd[4] << 24) | (dcd[5] << 16) | (dcd[6] << 8) | dcd[7];
dcd += 8;
- err = write_memory(h, p_id, addr, val, 4);
+ err = write_memory(addr, val, 4);
if (err < 0)
return err;
}
@@ -654,27 +711,27 @@ static int write_dcd_table_ivt(struct libusb_device_handle *h, struct usb_id *p_
return err;
}
-static int get_dcd_range_old(struct imx_flash_header_v1 *hdr,
+static int get_dcd_range_old(struct imx_flash_header *hdr,
unsigned char *file_start, unsigned cnt,
unsigned char **pstart, unsigned char **pend)
{
unsigned char *dcd_end;
unsigned m_length;
-#define cvt_dest_to_src_old (((unsigned char *)&hdr->dcd_ptr) - hdr->dcd_ptr_ptr)
+#define cvt_dest_to_src_old (((unsigned char *)&hdr->dcd) - hdr->dcd_ptr_ptr)
unsigned char* dcd;
unsigned val;
unsigned char* file_end = file_start + cnt;
- if (!hdr->dcd_ptr) {
- printf("No dcd table, barker=%x\n", hdr->app_barker);
- *pstart = *pend = ((unsigned char *)hdr) + sizeof(struct imx_flash_header_v1);
+ if (!hdr->dcd) {
+ printf("No dcd table, barker=%x\n", hdr->app_code_barker);
+ *pstart = *pend = ((unsigned char *)hdr) + sizeof(struct imx_flash_header);
return 0; /* nothing to do */
}
- dcd = hdr->dcd_ptr + cvt_dest_to_src_old;
+ dcd = hdr->dcd + cvt_dest_to_src_old;
if ((dcd < file_start) || ((dcd + 8) > file_end)) {
- printf("bad dcd_ptr %08x\n", hdr->dcd_ptr);
+ printf("bad dcd_ptr %08x\n", hdr->dcd);
return -1;
}
@@ -701,8 +758,7 @@ static int get_dcd_range_old(struct imx_flash_header_v1 *hdr,
return 0;
}
-static int write_dcd_table_old(struct libusb_device_handle *h, struct usb_id *p_id,
- struct imx_flash_header_v1 *hdr, unsigned char *file_start, unsigned cnt)
+static int write_dcd_table_old(struct imx_flash_header *hdr, unsigned char *file_start, unsigned cnt)
{
unsigned val;
unsigned char *dcd_end;
@@ -723,14 +779,14 @@ static int write_dcd_table_old(struct libusb_device_handle *h, struct usb_id *p_
case 1:
if (verbose > 1)
printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val);
- err = write_memory(h, p_id, addr, val, 1);
+ err = write_memory(addr, val, 1);
if (err < 0)
return err;
break;
case 4:
if (verbose > 1)
printf("type=%08x *0x%08x = 0x%08x\n", type, addr, val);
- err = write_memory(h, p_id, addr, val, 4);
+ err = write_memory(addr, val, 4);
if (err < 0)
return err;
break;
@@ -747,117 +803,79 @@ static int write_dcd_table_old(struct libusb_device_handle *h, struct usb_id *p_
return err;
}
-static int verify_memory(struct libusb_device_handle *h, struct usb_id *p_id,
- FILE *xfile, unsigned offset, unsigned addr, unsigned size,
- unsigned char *verify_buffer, unsigned verify_cnt)
+static int verify_memory(const void *buf, unsigned len, unsigned addr)
{
- int mismatch = 0;
- unsigned char file_buf[1024];
- fseek(xfile, offset + verify_cnt, SEEK_SET);
-
- while (size) {
- unsigned char mem_buf[64];
- unsigned char *p = file_buf;
- int cnt = addr & 0x3f;
- int request = get_min(size, sizeof(file_buf));
-
- if (cnt) {
- cnt = 64 - cnt;
- if (request > cnt)
- request = cnt;
- }
+ int ret, mismatch = 0;
+ void *readbuf;
+ unsigned offset = 0, now;
- if (verify_cnt) {
- p = verify_buffer;
- cnt = get_min(request, verify_cnt);
- verify_buffer += cnt;
- verify_cnt -= cnt;
- } else {
- cnt = fread(p, 1, request, xfile);
- if (cnt <= 0) {
- printf("Unexpected end of file, request=0x%0x, size=0x%x, cnt=%i\n",
- request, size, cnt);
- return -1;
- }
- }
-
- size -= cnt;
-
- while (cnt) {
- int ret;
+ readbuf = malloc(len);
+ if (!readbuf)
+ return -ENOMEM;
- request = get_min(cnt, sizeof(mem_buf));
-
- ret = read_memory(h, p_id, addr, mem_buf, request);
- if (ret < 0)
- return ret;
-
- if (memcmp(p, mem_buf, request)) {
- unsigned char * m = mem_buf;
- if (!mismatch)
- printf("!!!!mismatch\n");
- mismatch++;
-
- while (request) {
- unsigned req = get_min(request, 32);
- if (memcmp(p, m, req)) {
- dump_long(p, req, offset);
- dump_long(m, req, addr);
- printf("\n");
- }
- p += req;
- m+= req;
- offset += req;
- addr += req;
- cnt -= req;
- request -= req;
- }
- if (mismatch >= 5)
- return -1;
- }
- p += request;
- offset += request;
- addr += request;
- cnt -= request;
+ ret = read_memory(addr, readbuf, len);
+ if (ret < 0)
+ goto err;
+
+ while (len) {
+ now = get_min(len, 32);
+
+ if (memcmp(buf + offset, readbuf + offset, now)) {
+ printf("mismatch at offset 0x%08x. expected:\n", offset);
+ dump_long(buf + offset, now, addr + offset);
+ printf("read:\n");
+ dump_long(readbuf + offset, now, addr + offset);
+ ret = -EINVAL;
+ mismatch++;
+ if (mismatch > 4)
+ goto err;
}
+
+ len -= now;
+ offset += now;
}
- return mismatch ? -1 : 0;
+err:
+ free(readbuf);
+
+ return ret;
}
-static int is_header(struct usb_id *p_id, unsigned char *p)
+static int is_header(unsigned char *p)
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
- switch (p_id->mach_id->header_type) {
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
- if (ohdr->app_barker == 0xb1)
+ if (ohdr->app_code_barker == 0xb1)
return 1;
break;
case HDR_MX53:
- if (hdr->barker == IVT_BARKER)
+ if (hdr->header.tag == TAG_IVT_HEADER && hdr->header.version == IVT_VERSION)
return 1;
}
return 0;
}
-static int perform_dcd(struct libusb_device_handle *h, struct usb_id *p_id, unsigned char *p,
- unsigned char *file_start, unsigned cnt)
+static int perform_dcd(unsigned char *p, unsigned char *file_start, unsigned cnt)
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
int ret = 0;
- switch (p_id->mach_id->header_type) {
+ if (skip_image_dcd)
+ return 0;
+
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
- ret = write_dcd_table_old(h, p_id, ohdr, file_start, cnt);
- ohdr->dcd_ptr = 0;
+ ret = write_dcd_table_old(ohdr, file_start, cnt);
+ ohdr->dcd_block_len = 0;
break;
case HDR_MX53:
- ret = write_dcd_table_ivt(h, p_id, hdr, file_start, cnt);
+ ret = write_dcd_table_ivt(hdr, file_start, cnt);
hdr->dcd_ptr = 0;
break;
@@ -866,16 +884,15 @@ static int perform_dcd(struct libusb_device_handle *h, struct usb_id *p_id, unsi
return ret;
}
-static int clear_dcd_ptr(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned char *p, unsigned char *file_start, unsigned cnt)
+static int clear_dcd_ptr(unsigned char *p, unsigned char *file_start, unsigned cnt)
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
- switch (p_id->mach_id->header_type) {
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
- printf("clear dcd_ptr=0x%08x\n", ohdr->dcd_ptr);
- ohdr->dcd_ptr = 0;
+ printf("clear dcd_ptr=0x%08x\n", ohdr->dcd);
+ ohdr->dcd = 0;
break;
case HDR_MX53:
printf("clear dcd_ptr=0x%08x\n", hdr->dcd_ptr);
@@ -885,21 +902,21 @@ static int clear_dcd_ptr(struct libusb_device_handle *h, struct usb_id *p_id,
return 0;
}
-static int get_dl_start(struct usb_id *p_id, unsigned char *p, unsigned char *file_start,
+static int get_dl_start(unsigned char *p, unsigned char *file_start,
unsigned cnt, unsigned *dladdr, unsigned *max_length, unsigned *plugin,
unsigned *header_addr)
{
unsigned char* file_end = file_start + cnt;
- switch (p_id->mach_id->header_type) {
+ switch (usb_id->mach_id->header_type) {
case HDR_MX51:
{
- struct imx_flash_header_v1 *ohdr = (struct imx_flash_header_v1 *)p;
+ struct imx_flash_header *ohdr = (struct imx_flash_header *)p;
unsigned char *dcd_end;
unsigned char* dcd;
int err = get_dcd_range_old(ohdr, file_start, cnt, &dcd, &dcd_end);
- *dladdr = ohdr->app_dest_ptr;
- *header_addr = ohdr->dcd_ptr_ptr - offsetof(struct imx_flash_header_v1, dcd_ptr);
+ *dladdr = ohdr->app_dest;
+ *header_addr = ohdr->dcd_ptr_ptr - offsetof(struct imx_flash_header, dcd);
*plugin = 0;
if (err >= 0)
*max_length = dcd_end[0] | (dcd_end[1] << 8) | (dcd_end[2] << 16) | (dcd_end[3] << 24);
@@ -911,20 +928,18 @@ static int get_dl_start(struct usb_id *p_id, unsigned char *p, unsigned char *fi
unsigned char *bd;
struct imx_flash_header_v2 *hdr = (struct imx_flash_header_v2 *)p;
- *dladdr = hdr->self_ptr;
- *header_addr = hdr->self_ptr;
+ *dladdr = hdr->self;
+ *header_addr = hdr->self;
bd = hdr->boot_data_ptr + cvt_dest_to_src;
if ((bd < file_start) || ((bd + 4) > file_end)) {
printf("bad boot_data_ptr %08x\n", hdr->boot_data_ptr);
return -1;
}
- *dladdr = ((struct boot_data *)bd)->dest;
- *max_length = ((struct boot_data *)bd)->image_len;
- *plugin = ((struct boot_data *)bd)->plugin;
- ((struct boot_data *)bd)->plugin = 0;
-
- hdr->boot_data_ptr = 0;
+ *dladdr = ((struct imx_boot_data *)bd)->start;
+ *max_length = ((struct imx_boot_data *)bd)->size;
+ *plugin = ((struct imx_boot_data *)bd)->plugin;
+ ((struct imx_boot_data *)bd)->plugin = 0;
break;
}
@@ -932,8 +947,7 @@ static int get_dl_start(struct usb_id *p_id, unsigned char *p, unsigned char *fi
return 0;
}
-static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
- struct usb_work *curr, unsigned char *buf, int cnt,
+static int process_header(struct usb_work *curr, unsigned char *buf, int cnt,
unsigned *p_dladdr, unsigned *p_max_length, unsigned *p_plugin,
unsigned *p_header_addr)
{
@@ -946,17 +960,17 @@ static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
for (header_offset = 0; header_offset < header_max; header_offset += header_inc, p += header_inc) {
- if (!is_header(p_id, p))
+ if (!is_header(p))
continue;
- ret = get_dl_start(p_id, p, buf, cnt, p_dladdr, p_max_length, p_plugin, p_header_addr);
+ ret = get_dl_start(p, buf, cnt, p_dladdr, p_max_length, p_plugin, p_header_addr);
if (ret < 0) {
printf("!!get_dl_start returned %i\n", ret);
return ret;
}
if (curr->dcd) {
- ret = perform_dcd(h, p_id, p, buf, cnt);
+ ret = perform_dcd(p, buf, cnt);
if (ret < 0) {
printf("!!perform_dcd returned %i\n", ret);
return ret;
@@ -969,7 +983,7 @@ static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
}
if (curr->clear_dcd) {
- ret = clear_dcd_ptr(h, p_id, p, buf, cnt);
+ ret = clear_dcd_ptr(p, buf, cnt);
if (ret < 0) {
printf("!!clear_dcd returned %i\n", ret);
return ret;
@@ -995,137 +1009,7 @@ static int process_header(struct libusb_device_handle *h, struct usb_id *p_id,
return -ENODEV;
}
-static int load_file(struct libusb_device_handle *h, struct usb_id *p_id,
- unsigned char *p, int cnt, unsigned char *buf, unsigned buf_cnt,
- unsigned dladdr, unsigned fsize, unsigned char type, FILE* xfile)
-{
- static unsigned char dl_command[] = {
- 0x04,
- 0x04,
- V(0), /* address */
- 0x00, /* format */
- V(0x00000020), /* data count */
- V(0), /* data */
- 0xaa, /* type */
- };
- int last_trans, err;
- int retry = 0;
- unsigned transfer_size = 0;
- int max = p_id->mach_id->max_transfer;
- unsigned char tmp[64];
-
- dl_command[2] = (unsigned char)(dladdr >> 24);
- dl_command[3] = (unsigned char)(dladdr >> 16);
- dl_command[4] = (unsigned char)(dladdr >> 8);
- dl_command[5] = (unsigned char)(dladdr);
-
- dl_command[7] = (unsigned char)(fsize >> 24);
- dl_command[8] = (unsigned char)(fsize >> 16);
- dl_command[9] = (unsigned char)(fsize >> 8);
- dl_command[10] = (unsigned char)(fsize);
- dl_command[15] = type;
-
- for (;;) {
- err = transfer(h, 1, dl_command, 16, &last_trans, p_id);
- if (!err)
- break;
-
- printf("dl_command err=%i, last_trans=%i\n", err, last_trans);
-
- if (retry > 5)
- return -4;
- retry++;
- }
-
- retry = 0;
-
- if (p_id->mach_id->mode == MODE_BULK) {
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
- if (err)
- printf("in err=%i, last_trans=%i %02x %02x %02x %02x\n",
- err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
- }
-
- while (1) {
- int retry;
-
- if (cnt > (int)(fsize - transfer_size))
- cnt = (fsize - transfer_size);
-
- if (cnt <= 0)
- break;
-
- retry = 0;
-
- while (cnt) {
- err = transfer(h, 2, p, get_min(cnt, max), &last_trans, p_id);
- if (err) {
- printf("out err=%i, last_trans=%i cnt=0x%x max=0x%x transfer_size=0x%X retry=%i\n",
- err, last_trans, cnt, max, transfer_size, retry);
- if (retry >= 10) {
- printf("Giving up\n");
- return err;
- }
- if (max >= 16)
- max >>= 1;
- else
- max <<= 1;
- usleep(10000);
- retry++;
- continue;
- }
- max = p_id->mach_id->max_transfer;
- retry = 0;
- if (cnt < last_trans) {
- printf("error: last_trans=0x%x, attempted only=0%x\n", last_trans, cnt);
- cnt = last_trans;
- }
- if (!last_trans) {
- printf("Nothing last_trans, err=%i\n", err);
- break;
- }
- p += last_trans;
- cnt -= last_trans;
- transfer_size += last_trans;
- }
-
- if (!last_trans)
- break;
-
- if (feof(xfile))
- break;
-
- cnt = fsize - transfer_size;
- if (cnt <= 0)
- break;
-
- cnt = fread(buf, 1 , get_min(cnt, buf_cnt), xfile);
- p = buf;
- }
-
- if (p_id->mach_id->mode == MODE_HID) {
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
- if (err)
- printf("3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
- err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
- err = transfer(h, 4, tmp, sizeof(tmp), &last_trans, p_id);
- if (err)
- printf("4 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
- err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
- } else {
- do_status(h, p_id);
- }
-
- return transfer_size;
-}
-
-#define FT_APP 0xaa
-#define FT_CSF 0xcc
-#define FT_DCD 0xee
-#define FT_LOAD_ONLY 0x00
-
-static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
- struct usb_work *curr, int verify)
+static int do_irom_download(struct usb_work *curr, int verify)
{
static unsigned char jump_command[] = {0x0b,0x0b, V(0), 0x00, V(0x00000000), V(0), 0x00};
@@ -1137,10 +1021,9 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
int cnt;
unsigned file_base;
int last_trans, err;
-#define BUF_SIZE (1024*16)
unsigned char *buf = NULL;
+ unsigned char *image;
unsigned char *verify_buffer = NULL;
- unsigned verify_cnt;
unsigned char *p;
unsigned char tmp[64];
unsigned dladdr = 0;
@@ -1149,7 +1032,6 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
unsigned header_addr = 0;
unsigned skip = 0;
- unsigned transfer_size=0;
int retry = 0;
xfile = fopen(curr->filename, "rb" );
@@ -1158,26 +1040,29 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
return -5;
}
- buf = malloc(BUF_SIZE);
- if (!buf) {
- printf("error, out of memory\n");
+ fsize = get_file_size(xfile);
+ if (fsize < 0x20) {
+ printf("error, file: %s is too small\n", curr->filename);
ret = -2;
goto cleanup;
}
- fsize = get_file_size(xfile);
-
- cnt = fread(buf, 1 , BUF_SIZE, xfile);
-
- if (cnt < 0x20) {
- printf("error, file: %s is too small\n", curr->filename);
+ buf = malloc(fsize);
+ if (!buf) {
+ printf("error, out of memory\n");
ret = -2;
goto cleanup;
}
+ cnt = fread(buf, 1 , fsize, xfile);
+ if (cnt < fsize) {
+ printf("error, cannot read %s\n", curr->filename);
+ return -1;
+ }
+
max_length = fsize;
- ret = process_header(h, p_id, curr, buf, cnt,
+ ret = process_header(curr, buf, cnt,
&dladdr, &max_length, &plugin, &header_addr);
if (ret < 0)
goto cleanup;
@@ -1206,7 +1091,7 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
type = (curr->plug || curr->jump_mode) ? FT_APP : FT_LOAD_ONLY;
- if (p_id->mach_id->mode == MODE_BULK && type == FT_APP) {
+ if (usb_id->mach_id->mode == MODE_BULK && type == FT_APP) {
/* No jump command, dladdr should point to header */
dladdr = header_addr;
}
@@ -1218,22 +1103,9 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
skip = dladdr - file_base;
- if (skip > cnt) {
- if (skip > fsize) {
- printf("skip(0x%08x) > fsize(0x%08x) file_base=0x%08x, header_offset=0x%x\n",
- skip, fsize, file_base, header_offset);
- ret = -4;
- goto cleanup;
- }
-
- fseek(xfile, skip, SEEK_SET);
- cnt -= skip;
- fsize -= skip;
- skip = 0;
- cnt = fread(buf, 1 , BUF_SIZE, xfile);
- }
+ image = buf + skip;
- p = &buf[skip];
+ p = image;
cnt -= skip;
fsize -= skip;
@@ -1241,13 +1113,7 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
fsize = max_length;
if (verify) {
- /*
- * we need to save header for verification
- * because some of the file is changed
- * before download
- */
- verify_buffer = malloc(cnt);
- verify_cnt = cnt;
+ verify_buffer = malloc(64);
if (!verify_buffer) {
printf("error, out of memory\n");
@@ -1255,9 +1121,9 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
goto cleanup;
}
- memcpy(verify_buffer, p, cnt);
+ memcpy(verify_buffer, p, 64);
- if ((type == FT_APP) && (p_id->mach_id->mode != MODE_HID)) {
+ if ((type == FT_APP) && (usb_id->mach_id->mode != MODE_HID)) {
type = FT_LOAD_ONLY;
verify = 2;
}
@@ -1266,19 +1132,16 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
printf("loading binary file(%s) to %08x, skip=0x%x, fsize=%u type=%d...\n",
curr->filename, dladdr, skip, fsize, type);
- ret = load_file(h, p_id, p, cnt, buf, BUF_SIZE,
- dladdr, fsize, type, xfile);
+ ret = load_file(image, fsize, dladdr, type);
if (ret < 0)
goto cleanup;
printf("binary file successfully loaded\n");
- transfer_size = ret;
-
if (verify) {
printf("verifying file...\n");
- ret = verify_memory(h, p_id, xfile, skip, dladdr, fsize, verify_buffer, verify_cnt);
+ ret = verify_memory(image, fsize, dladdr);
if (ret < 0) {
printf("verifying failed\n");
goto cleanup;
@@ -1287,18 +1150,19 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
printf("file successfully verified\n");
if (verify == 2) {
- if (verify_cnt > 64)
- verify_cnt = 64;
- ret = load_file(h, p_id, verify_buffer, verify_cnt,
- buf, BUF_SIZE, dladdr, verify_cnt,
- FT_APP, xfile);
+ /*
+ * In bulk mode we do not have an explicit jump command,
+ * so we load part of the image again with type FT_APP
+ * this time.
+ */
+ ret = load_file(verify_buffer, 64, dladdr, FT_APP);
if (ret < 0)
goto cleanup;
}
}
- if (p_id->mach_id->mode == MODE_HID && type == FT_APP) {
+ if (usb_id->mach_id->mode == MODE_HID && type == FT_APP) {
printf("jumping to 0x%08x\n", header_addr);
jump_command[2] = (unsigned char)(header_addr >> 24);
@@ -1310,7 +1174,7 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
retry = 0;
for (;;) {
- err = transfer(h, 1, jump_command, 16, &last_trans, p_id);
+ err = transfer(1, jump_command, 16, &last_trans);
if (!err)
break;
@@ -1323,14 +1187,14 @@ static int do_irom_download(struct libusb_device_handle *h, struct usb_id *p_id,
}
memset(tmp, 0, sizeof(tmp));
- err = transfer(h, 3, tmp, sizeof(tmp), &last_trans, p_id);
+ err = transfer(3, tmp, sizeof(tmp), &last_trans);
if (err)
printf("j3 in err=%i, last_trans=%i %02x %02x %02x %02x\n",
err, last_trans, tmp[0], tmp[1], tmp[2], tmp[3]);
}
- ret = (fsize == transfer_size) ? 0 : -16;
+ ret = 0;
cleanup:
fclose(xfile);
free(verify_buffer);
@@ -1339,10 +1203,28 @@ cleanup:
return ret;
}
+static int write_mem(struct config_data *data, uint32_t addr, uint32_t val, int width)
+{
+ printf("wr 0x%08x 0x%08x\n", addr, val);
+
+ return write_memory(addr, val, width);
+}
+
+static int parse_initfile(const char *filename)
+{
+ struct config_data data = {
+ .write_mem = write_mem,
+ };
+
+ return parse_config(&data, filename);
+}
+
static void usage(const char *prgname)
{
fprintf(stderr, "usage: %s [OPTIONS] [FILENAME]\n\n"
"-c check correctness of flashed image\n"
+ "-i <cfgfile> Specify custom SoC initialization file\n"
+ "-s skip DCD included in image\n"
"-v verbose (give multiple times to increase)\n"
"-h this help\n", prgname);
exit(1);
@@ -1350,7 +1232,6 @@ static void usage(const char *prgname)
int main(int argc, char *argv[])
{
- struct usb_id *p_id = NULL;
struct mach_id *mach;
libusb_device **devs;
libusb_device *dev;
@@ -1358,13 +1239,13 @@ int main(int argc, char *argv[])
int err;
int ret = 1;
ssize_t cnt;
- libusb_device_handle *h = NULL;
int config = 0;
int verify = 0;
struct usb_work w = {};
int opt;
+ char *initfile = NULL;
- while ((opt = getopt(argc, argv, "cvh")) != -1) {
+ while ((opt = getopt(argc, argv, "cvhi:s")) != -1) {
switch (opt) {
case 'c':
verify = 1;
@@ -1374,6 +1255,12 @@ int main(int argc, char *argv[])
break;
case 'h':
usage(argv[0]);
+ case 'i':
+ initfile = optarg;
+ break;
+ case 's':
+ skip_image_dcd = 1;
+ break;
default:
exit(1);
}
@@ -1406,7 +1293,7 @@ int main(int argc, char *argv[])
goto out;
}
- err = libusb_open(dev, &h);
+ err = libusb_open(dev, &usb_dev_handle);
if (err) {
fprintf(stderr, "Could not open device vid=0x%x pid=0x%x err=%d\n",
mach->vid, mach->pid, err);
@@ -1415,44 +1302,50 @@ int main(int argc, char *argv[])
libusb_free_device_list(devs, 1);
- libusb_get_configuration(h, &config);
+ libusb_get_configuration(usb_dev_handle, &config);
- if (libusb_kernel_driver_active(h, 0))
- libusb_detach_kernel_driver(h, 0);
+ if (libusb_kernel_driver_active(usb_dev_handle, 0))
+ libusb_detach_kernel_driver(usb_dev_handle, 0);
- err = libusb_claim_interface(h, 0);
+ err = libusb_claim_interface(usb_dev_handle, 0);
if (err) {
printf("Claim failed\n");
goto out;
}
- p_id = malloc(sizeof(*p_id));
- if (!p_id) {
+ usb_id = malloc(sizeof(*usb_id));
+ if (!usb_id) {
perror("malloc");
exit(1);
}
- p_id->mach_id = mach;
+ usb_id->mach_id = mach;
- err = do_status(h, p_id);
+ err = do_status();
if (err) {
printf("status failed\n");
goto out;
}
- err = do_irom_download(h, p_id, &w, verify);
+ if (initfile) {
+ err = parse_initfile(initfile);
+ if (err)
+ goto out;
+ }
+
+ err = do_irom_download(&w, verify);
if (err) {
- err = do_status(h, p_id);
+ err = do_status();
goto out;
}
ret = 0;
out:
- if (p_id)
- free(p_id);
+ if (usb_id)
+ free(usb_id);
- if (h)
- libusb_close(h);
+ if (usb_dev_handle)
+ libusb_close(usb_dev_handle);
libusb_exit(NULL);
diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c
new file mode 100644
index 0000000000..82ef97f80c
--- /dev/null
+++ b/scripts/imx/imx.c
@@ -0,0 +1,444 @@
+/*
+ * (C) Copyright 2016 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.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <linux/kernel.h>
+
+#include "imx.h"
+
+#define MAXARGS 32
+
+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;
+ 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)(struct config_data *data, int argc, char *argv[]);
+};
+
+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(struct config_data *data, int argc, char *argv[])
+{
+ uint32_t addr, mask, cmd;
+ int i, width;
+ const char *scmd;
+
+ if (argc < 5) {
+ do_cmd_check_usage();
+ return -EINVAL;
+ }
+
+ if (!data->check)
+ return -ENOSYS;
+
+ 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;
+ };
+
+ 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 | ((sizeof(uint32_t) * 3) << 8);
+
+ return data->check(data, cmd, addr, mask);
+}
+
+static int do_cmd_write_mem(struct config_data *data, int argc, char *argv[])
+{
+ uint32_t addr, val, width;
+ char *end;
+
+ if (argc != 4) {
+ fprintf(stderr, "usage: wm [8|16|32] <addr> <val>\n");
+ return -EINVAL;
+ }
+
+ width = strtoul(argv[1], &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "illegal width token \"%s\"\n", argv[1]);
+ return -EINVAL;
+ }
+
+ addr = strtoul(argv[2], &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "illegal address token \"%s\"\n", argv[2]);
+ return -EINVAL;
+ }
+
+ val = strtoul(argv[3], &end, 0);
+ if (*end != '\0') {
+ fprintf(stderr, "illegal value token \"%s\"\n", argv[3]);
+ return -EINVAL;
+ }
+
+ width >>= 3;
+
+ switch (width) {
+ case 1:
+ case 2:
+ case 4:
+ break;
+ default:
+ fprintf(stderr, "illegal width %d\n", width);
+ return -EINVAL;
+ };
+
+ return data->write_mem(data, addr, val, width);
+}
+
+static int do_loadaddr(struct config_data *data, int argc, char *argv[])
+{
+ if (argc < 2)
+ return -EINVAL;
+
+ data->image_load_addr = strtoul(argv[1], NULL, 0);
+
+ return 0;
+}
+
+static int do_dcd_offset(struct config_data *data, int argc, char *argv[])
+{
+ if (argc < 2)
+ return -EINVAL;
+
+ data->image_dcd_offset = strtoul(argv[1], NULL, 0);
+
+ return 0;
+}
+
+struct soc_type {
+ char *name;
+ int header_version;
+ int cpu_type;
+};
+
+static struct soc_type socs[] = {
+ { .name = "imx25", .header_version = 1, .cpu_type = 25},
+ { .name = "imx35", .header_version = 1, .cpu_type = 35 },
+ { .name = "imx51", .header_version = 1, .cpu_type = 51 },
+ { .name = "imx53", .header_version = 2, .cpu_type = 53 },
+ { .name = "imx6", .header_version = 2, .cpu_type = 6 },
+};
+
+static int do_soc(struct config_data *data, 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)) {
+ data->header_version = socs[i].header_version;
+ data->cpu_type = socs[i].cpu_type;
+ 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");
+
+ if (data->cpu_type == 35)
+ data->load_size += HEADER_LEN;
+
+ return -EINVAL;
+}
+
+static int hab_add_str(struct config_data *data, const char *str)
+{
+ int len = strlen(str);
+
+ if (data->csf_space < len)
+ return -ENOMEM;
+
+ strcat(data->csf, str);
+
+ data->csf_space -= len;
+
+ return 0;
+}
+
+static int do_hab(struct config_data *data, int argc, char *argv[])
+{
+ int i, ret;
+
+ if (!data->csf) {
+ data->csf_space = 0x10000;
+
+ data->csf = malloc(data->csf_space + 1);
+ if (!data->csf)
+ return -ENOMEM;
+ }
+
+ for (i = 1; i < argc; i++) {
+ ret = hab_add_str(data, argv[i]);
+ if (ret)
+ return ret;
+
+ ret = hab_add_str(data, " ");
+ if (ret)
+ return ret;
+ }
+
+ ret = hab_add_str(data, "\n");
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int do_hab_blocks(struct config_data *data, int argc, char *argv[])
+{
+ char *str;
+ int ret;
+
+ if (!data->csf)
+ return -EINVAL;
+
+ ret = asprintf(&str, "Blocks = 0x%08x 0 %d \"%s\"\n",
+ data->image_load_addr,
+ data->load_size, data->outfile);
+ if (ret < 0)
+ return -ENOMEM;
+
+ ret = hab_add_str(data, str);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int do_super_root_key(struct config_data *data, int argc, char *argv[])
+{
+ int len;
+ char *srkfile;
+
+ if (argc != 2) {
+ fprintf(stderr, "usage: super_root_key <keyfile>\n");
+ return -EINVAL;
+ }
+
+ if (data->cpu_type != 35 && data->cpu_type != 25) {
+ fprintf(stderr, "Warning: The super_root_key command is meaningless "
+ "on non HABv3 based SoCs\n");
+ return 0;
+ }
+
+ srkfile = argv[1];
+
+ if (*srkfile == '"')
+ srkfile++;
+
+ data->srkfile = strdup(srkfile);
+ if (!data->srkfile)
+ return -ENOMEM;
+
+ len = strlen(data->srkfile);
+ if (data->srkfile[len - 1] == '"')
+ data->srkfile[len - 1] = 0;
+
+ return 0;
+}
+
+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,
+ }, {
+ .name = "hab",
+ .parse = do_hab,
+ }, {
+ .name = "hab_blocks",
+ .parse = do_hab_blocks,
+ }, {
+ .name = "super_root_key",
+ .parse = do_super_root_key,
+ },
+};
+
+static char *readcmd(struct config_data *data, FILE *f)
+{
+ static char *buf;
+ char *str;
+ ssize_t ret;
+
+ if (!buf) {
+ buf = malloc(4096);
+ if (!buf)
+ return NULL;
+ }
+
+ str = buf;
+ *str = 0;
+
+ while (1) {
+ ret = fread(str, 1, 1, f);
+ if (!ret)
+ return strlen(buf) ? buf : NULL;
+
+ if (*str == '\n' || *str == ';') {
+ *str = 0;
+ return buf;
+ }
+
+ str++;
+ }
+}
+
+int parse_config(struct config_data *data, const char *filename)
+{
+ FILE *f;
+ int lineno = 0;
+ char *line = NULL, *tmp;
+ char *argv[MAXARGS];
+ int nargs, i, ret = 0;
+
+ f = fopen(filename, "r");
+ if (!f) {
+ fprintf(stderr, "Error: %s - Can't open DCD file\n", filename);
+ exit(1);
+ }
+
+ while (1) {
+ line = readcmd(data, f);
+ if (!line)
+ break;
+
+ lineno++;
+
+ tmp = strchr(line, '#');
+ 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(data, nargs, argv);
+ if (ret) {
+ fprintf(stderr, "error in line %d: %s\n",
+ lineno, strerror(-ret));
+ goto cleanup;
+ }
+ break;
+ }
+ }
+
+ if (ret == -ENOENT) {
+ fprintf(stderr, "no such command: %s\n", argv[0]);
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ fclose(f);
+ return ret;
+}
diff --git a/scripts/imx/imx.h b/scripts/imx/imx.h
new file mode 100644
index 0000000000..85071b4ed3
--- /dev/null
+++ b/scripts/imx/imx.h
@@ -0,0 +1,72 @@
+
+#define HEADER_LEN 0x1000 /* length of the blank area + IVT + DCD */
+
+/*
+ * ============================================================================
+ * i.MX flash header v1 handling. Found on i.MX35 and i.MX51
+ * ============================================================================
+ */
+#define DCD_BARKER 0xb17219e9
+
+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));
+
+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));
+
+struct config_data {
+ uint32_t image_load_addr;
+ uint32_t image_dcd_offset;
+ uint32_t image_size;
+ uint32_t load_size;
+ char *outfile;
+ char *srkfile;
+ int header_version;
+ int cpu_type;
+ int (*check)(struct config_data *data, uint32_t cmd, uint32_t addr, uint32_t mask);
+ int (*write_mem)(struct config_data *data, uint32_t addr, uint32_t val, int width);
+ int csf_space;
+ char *csf;
+};
+
+int parse_config(struct config_data *data, const char *filename);
diff --git a/scripts/include/asm-generic/atomic-gcc.h b/scripts/include/asm-generic/atomic-gcc.h
new file mode 100644
index 0000000000..2ba78c9f57
--- /dev/null
+++ b/scripts/include/asm-generic/atomic-gcc.h
@@ -0,0 +1,63 @@
+#ifndef __TOOLS_ASM_GENERIC_ATOMIC_H
+#define __TOOLS_ASM_GENERIC_ATOMIC_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+/*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ *
+ * Excerpts obtained from the Linux kernel sources.
+ */
+
+#define ATOMIC_INIT(i) { (i) }
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.
+ */
+static inline int atomic_read(const atomic_t *v)
+{
+ return ACCESS_ONCE((v)->counter);
+}
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+static inline void atomic_set(atomic_t *v, int i)
+{
+ v->counter = i;
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+static inline void atomic_inc(atomic_t *v)
+{
+ __sync_add_and_fetch(&v->counter, 1);
+}
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static inline int atomic_dec_and_test(atomic_t *v)
+{
+ return __sync_sub_and_fetch(&v->counter, 1) == 0;
+}
+
+#endif /* __TOOLS_ASM_GENERIC_ATOMIC_H */
diff --git a/scripts/include/asm-generic/barrier.h b/scripts/include/asm-generic/barrier.h
new file mode 100644
index 0000000000..47b933903e
--- /dev/null
+++ b/scripts/include/asm-generic/barrier.h
@@ -0,0 +1,44 @@
+/*
+ * Copied from the kernel sources to tools/perf/:
+ *
+ * Generic barrier definitions, originally based on MN10300 definitions.
+ *
+ * It should be possible to use these on really simple architectures,
+ * but it serves more as a starting point for new ports.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#ifndef __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
+#define __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/compiler.h>
+
+/*
+ * Force strict CPU ordering. And yes, this is required on UP too when we're
+ * talking to devices.
+ *
+ * Fall back to compiler barriers if nothing better is provided.
+ */
+
+#ifndef mb
+#define mb() barrier()
+#endif
+
+#ifndef rmb
+#define rmb() mb()
+#endif
+
+#ifndef wmb
+#define wmb() mb()
+#endif
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __TOOLS_LINUX_ASM_GENERIC_BARRIER_H */
diff --git a/scripts/include/asm-generic/bitops.h b/scripts/include/asm-generic/bitops.h
new file mode 100644
index 0000000000..653d1bad77
--- /dev/null
+++ b/scripts/include/asm-generic/bitops.h
@@ -0,0 +1,29 @@
+#ifndef __TOOLS_ASM_GENERIC_BITOPS_H
+#define __TOOLS_ASM_GENERIC_BITOPS_H
+
+/*
+ * tools/ copied this from include/asm-generic/bitops.h, bit by bit as it needed
+ * some functions.
+ *
+ * For the benefit of those who are trying to port Linux to another
+ * architecture, here are some C-language equivalents. You should
+ * recode these in the native assembly language, if at all possible.
+ *
+ * C language equivalents written by Theodore Ts'o, 9/26/92
+ */
+
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/find.h>
+
+#ifndef _TOOLS_LINUX_BITOPS_H_
+#error only <linux/bitops.h> can be included directly
+#endif
+
+#include <asm-generic/bitops/hweight.h>
+
+#include <asm-generic/bitops/atomic.h>
+
+#endif /* __TOOLS_ASM_GENERIC_BITOPS_H */
diff --git a/scripts/include/asm-generic/bitops/__ffs.h b/scripts/include/asm-generic/bitops/__ffs.h
new file mode 100644
index 0000000000..c94175015a
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/__ffs.h
@@ -0,0 +1,43 @@
+#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
+#define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
+
+#include <asm/types.h>
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __always_inline unsigned long __ffs(unsigned long word)
+{
+ int num = 0;
+
+#if __BITS_PER_LONG == 64
+ if ((word & 0xffffffff) == 0) {
+ num += 32;
+ word >>= 32;
+ }
+#endif
+ if ((word & 0xffff) == 0) {
+ num += 16;
+ word >>= 16;
+ }
+ if ((word & 0xff) == 0) {
+ num += 8;
+ word >>= 8;
+ }
+ if ((word & 0xf) == 0) {
+ num += 4;
+ word >>= 4;
+ }
+ if ((word & 0x3) == 0) {
+ num += 2;
+ word >>= 2;
+ }
+ if ((word & 0x1) == 0)
+ num += 1;
+ return num;
+}
+
+#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ */
diff --git a/scripts/include/asm-generic/bitops/__fls.h b/scripts/include/asm-generic/bitops/__fls.h
new file mode 100644
index 0000000000..2218b9add4
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/__fls.h
@@ -0,0 +1 @@
+#include <../../../../include/asm-generic/bitops/__fls.h>
diff --git a/scripts/include/asm-generic/bitops/arch_hweight.h b/scripts/include/asm-generic/bitops/arch_hweight.h
new file mode 100644
index 0000000000..318bb2b202
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/arch_hweight.h
@@ -0,0 +1 @@
+#include "../../../../include/asm-generic/bitops/arch_hweight.h"
diff --git a/scripts/include/asm-generic/bitops/atomic.h b/scripts/include/asm-generic/bitops/atomic.h
new file mode 100644
index 0000000000..4bccd7c3d5
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/atomic.h
@@ -0,0 +1,22 @@
+#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
+#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
+
+#include <asm/types.h>
+
+static inline void set_bit(int nr, unsigned long *addr)
+{
+ addr[nr / __BITS_PER_LONG] |= 1UL << (nr % __BITS_PER_LONG);
+}
+
+static inline void clear_bit(int nr, unsigned long *addr)
+{
+ addr[nr / __BITS_PER_LONG] &= ~(1UL << (nr % __BITS_PER_LONG));
+}
+
+static __always_inline int test_bit(unsigned int nr, const unsigned long *addr)
+{
+ return ((1UL << (nr % __BITS_PER_LONG)) &
+ (((unsigned long *)addr)[nr / __BITS_PER_LONG])) != 0;
+}
+
+#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ */
diff --git a/scripts/include/asm-generic/bitops/const_hweight.h b/scripts/include/asm-generic/bitops/const_hweight.h
new file mode 100644
index 0000000000..0afd644aff
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/const_hweight.h
@@ -0,0 +1 @@
+#include "../../../../include/asm-generic/bitops/const_hweight.h"
diff --git a/scripts/include/asm-generic/bitops/find.h b/scripts/include/asm-generic/bitops/find.h
new file mode 100644
index 0000000000..31f51547fc
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/find.h
@@ -0,0 +1,33 @@
+#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
+#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_
+
+#ifndef find_next_bit
+/**
+ * find_next_bit - find the next set bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The bitmap size in bits
+ *
+ * Returns the bit number for the next set bit
+ * If no bits are set, returns @size.
+ */
+extern unsigned long find_next_bit(const unsigned long *addr, unsigned long
+ size, unsigned long offset);
+#endif
+
+#ifndef find_first_bit
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum number of bits to search
+ *
+ * Returns the bit number of the first set bit.
+ * If no bits are set, returns @size.
+ */
+extern unsigned long find_first_bit(const unsigned long *addr,
+ unsigned long size);
+
+#endif /* find_first_bit */
+
+#endif /*_TOOLS_LINUX_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/scripts/include/asm-generic/bitops/fls.h b/scripts/include/asm-generic/bitops/fls.h
new file mode 100644
index 0000000000..dbf711a28f
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/fls.h
@@ -0,0 +1 @@
+#include <../../../../include/asm-generic/bitops/fls.h>
diff --git a/scripts/include/asm-generic/bitops/fls64.h b/scripts/include/asm-generic/bitops/fls64.h
new file mode 100644
index 0000000000..980b1f63c0
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/fls64.h
@@ -0,0 +1 @@
+#include <../../../../include/asm-generic/bitops/fls64.h>
diff --git a/scripts/include/asm-generic/bitops/hweight.h b/scripts/include/asm-generic/bitops/hweight.h
new file mode 100644
index 0000000000..290120c01a
--- /dev/null
+++ b/scripts/include/asm-generic/bitops/hweight.h
@@ -0,0 +1,7 @@
+#ifndef _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_
+#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_
+
+#include <asm-generic/bitops/arch_hweight.h>
+#include <asm-generic/bitops/const_hweight.h>
+
+#endif /* _TOOLS_LINUX_ASM_GENERIC_BITOPS_HWEIGHT_H_ */
diff --git a/scripts/include/asm/atomic.h b/scripts/include/asm/atomic.h
new file mode 100644
index 0000000000..70794f538a
--- /dev/null
+++ b/scripts/include/asm/atomic.h
@@ -0,0 +1,10 @@
+#ifndef __TOOLS_LINUX_ASM_ATOMIC_H
+#define __TOOLS_LINUX_ASM_ATOMIC_H
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "../../arch/x86/include/asm/atomic.h"
+#else
+#include <asm-generic/atomic-gcc.h>
+#endif
+
+#endif /* __TOOLS_LINUX_ASM_ATOMIC_H */
diff --git a/scripts/include/asm/barrier.h b/scripts/include/asm/barrier.h
new file mode 100644
index 0000000000..ac66ac5946
--- /dev/null
+++ b/scripts/include/asm/barrier.h
@@ -0,0 +1,27 @@
+#if defined(__i386__) || defined(__x86_64__)
+#include "../../arch/x86/include/asm/barrier.h"
+#elif defined(__arm__)
+#include "../../arch/arm/include/asm/barrier.h"
+#elif defined(__aarch64__)
+#include "../../arch/arm64/include/asm/barrier.h"
+#elif defined(__powerpc__)
+#include "../../arch/powerpc/include/asm/barrier.h"
+#elif defined(__s390__)
+#include "../../arch/s390/include/asm/barrier.h"
+#elif defined(__sh__)
+#include "../../arch/sh/include/asm/barrier.h"
+#elif defined(__sparc__)
+#include "../../arch/sparc/include/asm/barrier.h"
+#elif defined(__tile__)
+#include "../../arch/tile/include/asm/barrier.h"
+#elif defined(__alpha__)
+#include "../../arch/alpha/include/asm/barrier.h"
+#elif defined(__mips__)
+#include "../../arch/mips/include/asm/barrier.h"
+#elif defined(__ia64__)
+#include "../../arch/ia64/include/asm/barrier.h"
+#elif defined(__xtensa__)
+#include "../../arch/xtensa/include/asm/barrier.h"
+#else
+#include <asm-generic/barrier.h>
+#endif
diff --git a/scripts/include/asm/bug.h b/scripts/include/asm/bug.h
new file mode 100644
index 0000000000..9e5f484696
--- /dev/null
+++ b/scripts/include/asm/bug.h
@@ -0,0 +1,25 @@
+#ifndef _TOOLS_ASM_BUG_H
+#define _TOOLS_ASM_BUG_H
+
+#include <linux/compiler.h>
+
+#define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0)
+
+#define WARN(condition, format...) ({ \
+ int __ret_warn_on = !!(condition); \
+ if (unlikely(__ret_warn_on)) \
+ __WARN_printf(format); \
+ unlikely(__ret_warn_on); \
+})
+
+#define WARN_ONCE(condition, format...) ({ \
+ static int __warned; \
+ int __ret_warn_once = !!(condition); \
+ \
+ if (unlikely(__ret_warn_once)) \
+ if (WARN(!__warned, format)) \
+ __warned = 1; \
+ unlikely(__ret_warn_once); \
+})
+
+#endif /* _TOOLS_ASM_BUG_H */
diff --git a/scripts/include/linux/atomic.h b/scripts/include/linux/atomic.h
new file mode 100644
index 0000000000..4e3d3d18eb
--- /dev/null
+++ b/scripts/include/linux/atomic.h
@@ -0,0 +1,6 @@
+#ifndef __TOOLS_LINUX_ATOMIC_H
+#define __TOOLS_LINUX_ATOMIC_H
+
+#include <asm/atomic.h>
+
+#endif /* __TOOLS_LINUX_ATOMIC_H */
diff --git a/scripts/include/linux/bitmap.h b/scripts/include/linux/bitmap.h
new file mode 100644
index 0000000000..28f5493da4
--- /dev/null
+++ b/scripts/include/linux/bitmap.h
@@ -0,0 +1,68 @@
+#ifndef _PERF_BITOPS_H
+#define _PERF_BITOPS_H
+
+#include <string.h>
+#include <linux/bitops.h>
+
+#define DECLARE_BITMAP(name,bits) \
+ unsigned long name[BITS_TO_LONGS(bits)]
+
+int __bitmap_weight(const unsigned long *bitmap, int bits);
+void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, int bits);
+
+#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
+
+#define BITMAP_LAST_WORD_MASK(nbits) \
+( \
+ ((nbits) % BITS_PER_LONG) ? \
+ (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \
+)
+
+#define small_const_nbits(nbits) \
+ (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)
+
+static inline void bitmap_zero(unsigned long *dst, int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = 0UL;
+ else {
+ int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
+ memset(dst, 0, len);
+ }
+}
+
+static inline int bitmap_weight(const unsigned long *src, int nbits)
+{
+ if (small_const_nbits(nbits))
+ return hweight_long(*src & BITMAP_LAST_WORD_MASK(nbits));
+ return __bitmap_weight(src, nbits);
+}
+
+static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, int nbits)
+{
+ if (small_const_nbits(nbits))
+ *dst = *src1 | *src2;
+ else
+ __bitmap_or(dst, src1, src2, nbits);
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+static inline int test_and_set_bit(int nr, unsigned long *addr)
+{
+ unsigned long mask = BIT_MASK(nr);
+ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+ unsigned long old;
+
+ old = *p;
+ *p = old | mask;
+
+ return (old & mask) != 0;
+}
+
+#endif /* _PERF_BITOPS_H */
diff --git a/scripts/include/linux/bitops.h b/scripts/include/linux/bitops.h
new file mode 100644
index 0000000000..5ad9ee1dd7
--- /dev/null
+++ b/scripts/include/linux/bitops.h
@@ -0,0 +1,58 @@
+#ifndef _TOOLS_LINUX_BITOPS_H_
+#define _TOOLS_LINUX_BITOPS_H_
+
+#include <asm/types.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+
+#ifndef __WORDSIZE
+#define __WORDSIZE (__SIZEOF_LONG__ * 8)
+#endif
+
+#define BITS_PER_LONG __WORDSIZE
+
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+#define BITS_PER_BYTE 8
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
+#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
+#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE)
+
+extern unsigned int __sw_hweight8(unsigned int w);
+extern unsigned int __sw_hweight16(unsigned int w);
+extern unsigned int __sw_hweight32(unsigned int w);
+extern unsigned long __sw_hweight64(__u64 w);
+
+/*
+ * Include this here because some architectures need generic_ffs/fls in
+ * scope
+ *
+ * XXX: this needs to be asm/bitops.h, when we get to per arch optimizations
+ */
+#include <asm-generic/bitops.h>
+
+#define for_each_set_bit(bit, addr, size) \
+ for ((bit) = find_first_bit((addr), (size)); \
+ (bit) < (size); \
+ (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+/* same as for_each_set_bit() but use bit as value to start with */
+#define for_each_set_bit_from(bit, addr, size) \
+ for ((bit) = find_next_bit((addr), (size), (bit)); \
+ (bit) < (size); \
+ (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+static inline unsigned long hweight_long(unsigned long w)
+{
+ return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
+}
+
+static inline unsigned fls_long(unsigned long l)
+{
+ if (sizeof(l) == 4)
+ return fls(l);
+ return fls64(l);
+}
+
+#endif
diff --git a/scripts/include/linux/compiler.h b/scripts/include/linux/compiler.h
new file mode 100644
index 0000000000..fa7208a32d
--- /dev/null
+++ b/scripts/include/linux/compiler.h
@@ -0,0 +1,118 @@
+#ifndef _TOOLS_LINUX_COMPILER_H_
+#define _TOOLS_LINUX_COMPILER_H_
+
+/* Optimization barrier */
+/* The "volatile" is due to gcc bugs */
+#define barrier() __asm__ __volatile__("": : :"memory")
+
+#ifndef __always_inline
+# define __always_inline inline __attribute__((always_inline))
+#endif
+
+#define __user
+
+#ifndef __attribute_const__
+# define __attribute_const__
+#endif
+
+#ifndef __maybe_unused
+# define __maybe_unused __attribute__((unused))
+#endif
+
+#ifndef __packed
+# define __packed __attribute__((__packed__))
+#endif
+
+#ifndef __force
+# define __force
+#endif
+
+#ifndef __weak
+# define __weak __attribute__((weak))
+#endif
+
+#ifndef likely
+# define likely(x) __builtin_expect(!!(x), 1)
+#endif
+
+#ifndef unlikely
+# define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+
+#include <linux/types.h>
+
+/*
+ * Following functions are taken from kernel sources and
+ * break aliasing rules in their original form.
+ *
+ * While kernel is compiled with -fno-strict-aliasing,
+ * perf uses -Wstrict-aliasing=3 which makes build fail
+ * under gcc 4.4.
+ *
+ * Using extra __may_alias__ type to allow aliasing
+ * in this case.
+ */
+typedef __u8 __attribute__((__may_alias__)) __u8_alias_t;
+typedef __u16 __attribute__((__may_alias__)) __u16_alias_t;
+typedef __u32 __attribute__((__may_alias__)) __u32_alias_t;
+typedef __u64 __attribute__((__may_alias__)) __u64_alias_t;
+
+static __always_inline void __read_once_size(const volatile void *p, void *res, int size)
+{
+ switch (size) {
+ case 1: *(__u8_alias_t *) res = *(volatile __u8_alias_t *) p; break;
+ case 2: *(__u16_alias_t *) res = *(volatile __u16_alias_t *) p; break;
+ case 4: *(__u32_alias_t *) res = *(volatile __u32_alias_t *) p; break;
+ case 8: *(__u64_alias_t *) res = *(volatile __u64_alias_t *) p; break;
+ default:
+ barrier();
+ __builtin_memcpy((void *)res, (const void *)p, size);
+ barrier();
+ }
+}
+
+static __always_inline void __write_once_size(volatile void *p, void *res, int size)
+{
+ switch (size) {
+ case 1: *(volatile __u8_alias_t *) p = *(__u8_alias_t *) res; break;
+ case 2: *(volatile __u16_alias_t *) p = *(__u16_alias_t *) res; break;
+ case 4: *(volatile __u32_alias_t *) p = *(__u32_alias_t *) res; break;
+ case 8: *(volatile __u64_alias_t *) p = *(__u64_alias_t *) res; break;
+ default:
+ barrier();
+ __builtin_memcpy((void *)p, (const void *)res, size);
+ barrier();
+ }
+}
+
+/*
+ * Prevent the compiler from merging or refetching reads or writes. The
+ * compiler is also forbidden from reordering successive instances of
+ * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the
+ * compiler is aware of some particular ordering. One way to make the
+ * compiler aware of ordering is to put the two invocations of READ_ONCE,
+ * WRITE_ONCE or ACCESS_ONCE() in different C statements.
+ *
+ * In contrast to ACCESS_ONCE these two macros will also work on aggregate
+ * data types like structs or unions. If the size of the accessed data
+ * type exceeds the word size of the machine (e.g., 32 bits or 64 bits)
+ * READ_ONCE() and WRITE_ONCE() will fall back to memcpy and print a
+ * compile-time warning.
+ *
+ * Their two major use cases are: (1) Mediating communication between
+ * process-level code and irq/NMI handlers, all running on the same CPU,
+ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
+ * mutilate accesses that either do not require ordering or that interact
+ * with an explicit memory barrier or atomic instruction that provides the
+ * required ordering.
+ */
+
+#define READ_ONCE(x) \
+ ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
+
+#define WRITE_ONCE(x, val) \
+ ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
+
+#endif /* _TOOLS_LINUX_COMPILER_H */
diff --git a/scripts/include/linux/err.h b/scripts/include/linux/err.h
new file mode 100644
index 0000000000..bdc3dd8131
--- /dev/null
+++ b/scripts/include/linux/err.h
@@ -0,0 +1,49 @@
+#ifndef __TOOLS_LINUX_ERR_H
+#define __TOOLS_LINUX_ERR_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+#include <asm/errno.h>
+
+/*
+ * Original kernel header comment:
+ *
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a normal
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ *
+ * Userspace note:
+ * The same principle works for userspace, because 'error' pointers
+ * fall down to the unused hole far from user space, as described
+ * in Documentation/x86/x86_64/mm.txt for x86_64 arch:
+ *
+ * 0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm hole caused by [48:63] sign extension
+ * ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole
+ *
+ * It should be the same case for other architectures, because
+ * this code is used in generic kernel code.
+ */
+#define MAX_ERRNO 4095
+
+#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
+
+static inline void * __must_check ERR_PTR(long error_)
+{
+ return (void *) error_;
+}
+
+static inline long __must_check PTR_ERR(__force const void *ptr)
+{
+ return (long) ptr;
+}
+
+static inline bool __must_check IS_ERR(__force const void *ptr)
+{
+ return IS_ERR_VALUE((unsigned long)ptr);
+}
+
+#endif /* _LINUX_ERR_H */
diff --git a/scripts/include/linux/export.h b/scripts/include/linux/export.h
new file mode 100644
index 0000000000..d07e586b9b
--- /dev/null
+++ b/scripts/include/linux/export.h
@@ -0,0 +1,10 @@
+#ifndef _TOOLS_LINUX_EXPORT_H_
+#define _TOOLS_LINUX_EXPORT_H_
+
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+#define EXPORT_SYMBOL_GPL_FUTURE(sym)
+#define EXPORT_UNUSED_SYMBOL(sym)
+#define EXPORT_UNUSED_SYMBOL_GPL(sym)
+
+#endif
diff --git a/scripts/include/linux/kernel.h b/scripts/include/linux/kernel.h
new file mode 100644
index 0000000000..5d94e984f1
--- /dev/null
+++ b/scripts/include/linux/kernel.h
@@ -0,0 +1,109 @@
+#ifndef __TOOLS_LINUX_KERNEL_H
+#define __TOOLS_LINUX_KERNEL_H
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
+#define PERF_ALIGN(x, a) __PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
+#define __PERF_ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
+
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+
+#ifndef container_of
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *)0)->member) * __mptr = (ptr); \
+ (type *)((char *)__mptr - offsetof(type, member)); })
+#endif
+
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
+#ifndef max
+#define max(x, y) ({ \
+ typeof(x) _max1 = (x); \
+ typeof(y) _max2 = (y); \
+ (void) (&_max1 == &_max2); \
+ _max1 > _max2 ? _max1 : _max2; })
+#endif
+
+#ifndef min
+#define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+#endif
+
+#ifndef roundup
+#define roundup(x, y) ( \
+{ \
+ const typeof(y) __y = y; \
+ (((x) + (__y - 1)) / __y) * __y; \
+} \
+)
+#endif
+
+#ifndef BUG_ON
+#ifdef NDEBUG
+#define BUG_ON(cond) do { if (cond) {} } while (0)
+#else
+#define BUG_ON(cond) assert(!(cond))
+#endif
+#endif
+
+/*
+ * Both need more care to handle endianness
+ * (Don't use bitmap_copy_le() for now)
+ */
+#define cpu_to_le64(x) (x)
+#define cpu_to_le32(x) (x)
+
+static inline int
+vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+ int i;
+ ssize_t ssize = size;
+
+ i = vsnprintf(buf, size, fmt, args);
+
+ return (i >= ssize) ? (ssize - 1) : i;
+}
+
+static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
+{
+ va_list args;
+ ssize_t ssize = size;
+ int i;
+
+ va_start(args, fmt);
+ i = vsnprintf(buf, size, fmt, args);
+ va_end(args);
+
+ return (i >= ssize) ? (ssize - 1) : i;
+}
+
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
+#endif
diff --git a/scripts/include/linux/list.h b/scripts/include/linux/list.h
new file mode 100644
index 0000000000..1da423820a
--- /dev/null
+++ b/scripts/include/linux/list.h
@@ -0,0 +1,771 @@
+#ifndef __TOOLS_LINUX_LIST_H
+#define __TOOLS_LINUX_LIST_H
+
+#include <linux/types.h>
+#include <linux/poison.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+#ifndef CONFIG_DEBUG_LIST
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+#else
+extern void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next);
+#endif
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ WRITE_ONCE(prev->next, next);
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+#ifndef CONFIG_DEBUG_LIST
+static inline void __list_del_entry(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+}
+
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+#else
+extern void __list_del_entry(struct list_head *entry);
+extern void list_del(struct list_head *entry);
+#endif
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del_entry(entry);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del_entry(list);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del_entry(list);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+ return (next == head) && (next == head->prev);
+}
+
+/**
+ * list_rotate_left - rotate the list to the left
+ * @head: the head of the list
+ */
+static inline void list_rotate_left(struct list_head *head)
+{
+ struct list_head *first;
+
+ if (!list_empty(head)) {
+ first = head->next;
+ list_move_tail(first, head);
+ }
+}
+
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+ return !list_empty(head) && (head->next == head->prev);
+}
+
+static inline void __list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ struct list_head *new_first = entry->next;
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry;
+ entry->next = list;
+ head->next = new_first;
+ new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ * and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ *
+ */
+static inline void list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ if (list_empty(head))
+ return;
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
+ return;
+ if (entry == head)
+ INIT_LIST_HEAD(list);
+ else
+ __list_cut_position(list, head, entry);
+}
+
+static inline void __list_splice(const struct list_head *list,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+
+ first->prev = prev;
+ prev->next = first;
+
+ last->next = next;
+ next->prev = last;
+}
+
+/**
+ * list_splice - join two lists, this is designed for stacks
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(const struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head->prev, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head, head->next);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head->prev, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_last_entry - get the last element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+/**
+ * list_first_entry_or_null - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
+ *
+ * Note that if the list is empty, it returns NULL.
+ */
+#define list_first_entry_or_null(ptr, type, member) \
+ (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
+/**
+ * list_next_entry - get the next element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * list_prev_entry - get the prev element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_prev_entry(pos, member) \
+ list_entry((pos)->member.prev, typeof(*(pos)), member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; \
+ pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_last_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_prev_entry(pos, member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_head within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_next_entry(pos, member); \
+ &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_prev_entry(pos, member); \
+ &pos->member != (head); \
+ pos = list_prev_entry(pos, member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_first_entry(head, typeof(*pos), member), \
+ n = list_next_entry(pos, member); \
+ &pos->member != (head); \
+ pos = n, n = list_next_entry(n, member))
+
+/**
+ * list_for_each_entry_safe_continue - continue list iteration safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_next_entry(pos, member), \
+ n = list_next_entry(pos, member); \
+ &pos->member != (head); \
+ pos = n, n = list_next_entry(n, member))
+
+/**
+ * list_for_each_entry_safe_from - iterate over list from current point safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_next_entry(pos, member); \
+ &pos->member != (head); \
+ pos = n, n = list_next_entry(n, member))
+
+/**
+ * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_last_entry(head, typeof(*pos), member), \
+ n = list_prev_entry(pos, member); \
+ &pos->member != (head); \
+ pos = n, n = list_prev_entry(n, member))
+
+/**
+ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos: the loop cursor used in the list_for_each_entry_safe loop
+ * @n: temporary storage used in list_for_each_entry_safe
+ * @member: the name of the list_head within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_safe_reset_next(pos, n, member) \
+ n = list_next_entry(pos, member)
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+static inline void INIT_HLIST_NODE(struct hlist_node *h)
+{
+ h->next = NULL;
+ h->pprev = NULL;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+
+ WRITE_ONCE(*pprev, next);
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = LIST_POISON1;
+ n->pprev = LIST_POISON2;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+ if (!hlist_unhashed(n)) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static inline void hlist_add_behind(struct hlist_node *n,
+ struct hlist_node *prev)
+{
+ n->next = prev->next;
+ prev->next = n;
+ n->pprev = &prev->next;
+
+ if (n->next)
+ n->next->pprev = &n->next;
+}
+
+/* after that we'll appear to be on some hlist and hlist_del will work */
+static inline void hlist_add_fake(struct hlist_node *n)
+{
+ n->pprev = &n->next;
+}
+
+static inline bool hlist_fake(struct hlist_node *h)
+{
+ return h->pprev == &h->next;
+}
+
+/*
+ * Move a list from one list head to another. Fixup the pprev
+ * reference of the first entry if it exists.
+ */
+static inline void hlist_move_list(struct hlist_head *old,
+ struct hlist_head *new)
+{
+ new->first = old->first;
+ if (new->first)
+ new->first->pprev = &new->first;
+ old->first = NULL;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos ; pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
+
+#define hlist_entry_safe(ptr, type, member) \
+ ({ typeof(ptr) ____ptr = (ptr); \
+ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+ })
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(pos, head, member) \
+ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
+ pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @pos: the type * to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(pos, member) \
+ for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
+ pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @pos: the type * to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(pos, member) \
+ for (; pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
+ pos && ({ n = pos->member.next; 1; }); \
+ pos = hlist_entry_safe(n, typeof(*pos), member))
+
+/**
+ * list_del_range - deletes range of entries from list.
+ * @begin: first element in the range to delete from the list.
+ * @end: last element in the range to delete from the list.
+ * Note: list_empty on the range of entries does not return true after this,
+ * the entries is in an undefined state.
+ */
+static inline void list_del_range(struct list_head *begin,
+ struct list_head *end)
+{
+ begin->prev->next = end->next;
+ end->next->prev = begin->prev;
+}
+
+/**
+ * list_for_each_from - iterate over a list from one of its nodes
+ * @pos: the &struct list_head to use as a loop cursor, from where to start
+ * @head: the head for your list.
+ */
+#define list_for_each_from(pos, head) \
+ for (; pos != (head); pos = pos->next)
+
+#endif /* __TOOLS_LINUX_LIST_H */
diff --git a/scripts/include/linux/log2.h b/scripts/include/linux/log2.h
new file mode 100644
index 0000000000..41446668cc
--- /dev/null
+++ b/scripts/include/linux/log2.h
@@ -0,0 +1,185 @@
+/* Integer base 2 logarithm calculation
+ *
+ * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * 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.
+ */
+
+#ifndef _TOOLS_LINUX_LOG2_H
+#define _TOOLS_LINUX_LOG2_H
+
+/*
+ * deal with unrepresentable constant logarithms
+ */
+extern __attribute__((const, noreturn))
+int ____ilog2_NaN(void);
+
+/*
+ * non-constant log of base 2 calculators
+ * - the arch may override these in asm/bitops.h if they can be implemented
+ * more efficiently than using fls() and fls64()
+ * - the arch is not required to handle n==0 if implementing the fallback
+ */
+static inline __attribute__((const))
+int __ilog2_u32(u32 n)
+{
+ return fls(n) - 1;
+}
+
+static inline __attribute__((const))
+int __ilog2_u64(u64 n)
+{
+ return fls64(n) - 1;
+}
+
+/*
+ * Determine whether some value is a power of two, where zero is
+ * *not* considered a power of two.
+ */
+
+static inline __attribute__((const))
+bool is_power_of_2(unsigned long n)
+{
+ return (n != 0 && ((n & (n - 1)) == 0));
+}
+
+/*
+ * round up to nearest power of two
+ */
+static inline __attribute__((const))
+unsigned long __roundup_pow_of_two(unsigned long n)
+{
+ return 1UL << fls_long(n - 1);
+}
+
+/*
+ * round down to nearest power of two
+ */
+static inline __attribute__((const))
+unsigned long __rounddown_pow_of_two(unsigned long n)
+{
+ return 1UL << (fls_long(n) - 1);
+}
+
+/**
+ * ilog2 - log of base 2 of 32-bit or a 64-bit unsigned value
+ * @n - parameter
+ *
+ * constant-capable log of base 2 calculation
+ * - this can be used to initialise global variables from constant data, hence
+ * the massive ternary operator construction
+ *
+ * selects the appropriately-sized optimised version depending on sizeof(n)
+ */
+#define ilog2(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ (n) < 1 ? ____ilog2_NaN() : \
+ (n) & (1ULL << 63) ? 63 : \
+ (n) & (1ULL << 62) ? 62 : \
+ (n) & (1ULL << 61) ? 61 : \
+ (n) & (1ULL << 60) ? 60 : \
+ (n) & (1ULL << 59) ? 59 : \
+ (n) & (1ULL << 58) ? 58 : \
+ (n) & (1ULL << 57) ? 57 : \
+ (n) & (1ULL << 56) ? 56 : \
+ (n) & (1ULL << 55) ? 55 : \
+ (n) & (1ULL << 54) ? 54 : \
+ (n) & (1ULL << 53) ? 53 : \
+ (n) & (1ULL << 52) ? 52 : \
+ (n) & (1ULL << 51) ? 51 : \
+ (n) & (1ULL << 50) ? 50 : \
+ (n) & (1ULL << 49) ? 49 : \
+ (n) & (1ULL << 48) ? 48 : \
+ (n) & (1ULL << 47) ? 47 : \
+ (n) & (1ULL << 46) ? 46 : \
+ (n) & (1ULL << 45) ? 45 : \
+ (n) & (1ULL << 44) ? 44 : \
+ (n) & (1ULL << 43) ? 43 : \
+ (n) & (1ULL << 42) ? 42 : \
+ (n) & (1ULL << 41) ? 41 : \
+ (n) & (1ULL << 40) ? 40 : \
+ (n) & (1ULL << 39) ? 39 : \
+ (n) & (1ULL << 38) ? 38 : \
+ (n) & (1ULL << 37) ? 37 : \
+ (n) & (1ULL << 36) ? 36 : \
+ (n) & (1ULL << 35) ? 35 : \
+ (n) & (1ULL << 34) ? 34 : \
+ (n) & (1ULL << 33) ? 33 : \
+ (n) & (1ULL << 32) ? 32 : \
+ (n) & (1ULL << 31) ? 31 : \
+ (n) & (1ULL << 30) ? 30 : \
+ (n) & (1ULL << 29) ? 29 : \
+ (n) & (1ULL << 28) ? 28 : \
+ (n) & (1ULL << 27) ? 27 : \
+ (n) & (1ULL << 26) ? 26 : \
+ (n) & (1ULL << 25) ? 25 : \
+ (n) & (1ULL << 24) ? 24 : \
+ (n) & (1ULL << 23) ? 23 : \
+ (n) & (1ULL << 22) ? 22 : \
+ (n) & (1ULL << 21) ? 21 : \
+ (n) & (1ULL << 20) ? 20 : \
+ (n) & (1ULL << 19) ? 19 : \
+ (n) & (1ULL << 18) ? 18 : \
+ (n) & (1ULL << 17) ? 17 : \
+ (n) & (1ULL << 16) ? 16 : \
+ (n) & (1ULL << 15) ? 15 : \
+ (n) & (1ULL << 14) ? 14 : \
+ (n) & (1ULL << 13) ? 13 : \
+ (n) & (1ULL << 12) ? 12 : \
+ (n) & (1ULL << 11) ? 11 : \
+ (n) & (1ULL << 10) ? 10 : \
+ (n) & (1ULL << 9) ? 9 : \
+ (n) & (1ULL << 8) ? 8 : \
+ (n) & (1ULL << 7) ? 7 : \
+ (n) & (1ULL << 6) ? 6 : \
+ (n) & (1ULL << 5) ? 5 : \
+ (n) & (1ULL << 4) ? 4 : \
+ (n) & (1ULL << 3) ? 3 : \
+ (n) & (1ULL << 2) ? 2 : \
+ (n) & (1ULL << 1) ? 1 : \
+ (n) & (1ULL << 0) ? 0 : \
+ ____ilog2_NaN() \
+ ) : \
+ (sizeof(n) <= 4) ? \
+ __ilog2_u32(n) : \
+ __ilog2_u64(n) \
+ )
+
+/**
+ * roundup_pow_of_two - round the given value up to nearest power of two
+ * @n - parameter
+ *
+ * round the given value up to the nearest power of two
+ * - the result is undefined when n == 0
+ * - this can be used to initialise global variables from constant data
+ */
+#define roundup_pow_of_two(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ (n == 1) ? 1 : \
+ (1UL << (ilog2((n) - 1) + 1)) \
+ ) : \
+ __roundup_pow_of_two(n) \
+ )
+
+/**
+ * rounddown_pow_of_two - round the given value down to nearest power of two
+ * @n - parameter
+ *
+ * round the given value down to the nearest power of two
+ * - the result is undefined when n == 0
+ * - this can be used to initialise global variables from constant data
+ */
+#define rounddown_pow_of_two(n) \
+( \
+ __builtin_constant_p(n) ? ( \
+ (1UL << ilog2(n))) : \
+ __rounddown_pow_of_two(n) \
+ )
+
+#endif /* _TOOLS_LINUX_LOG2_H */
diff --git a/scripts/include/linux/poison.h b/scripts/include/linux/poison.h
new file mode 100644
index 0000000000..0c27bdf142
--- /dev/null
+++ b/scripts/include/linux/poison.h
@@ -0,0 +1 @@
+#include "../../../include/linux/poison.h"
diff --git a/scripts/include/linux/string.h b/scripts/include/linux/string.h
new file mode 100644
index 0000000000..e26223f1f2
--- /dev/null
+++ b/scripts/include/linux/string.h
@@ -0,0 +1,15 @@
+#ifndef _TOOLS_LINUX_STRING_H_
+#define _TOOLS_LINUX_STRING_H_
+
+
+#include <linux/types.h> /* for size_t */
+
+void *memdup(const void *src, size_t len);
+
+int strtobool(const char *s, bool *res);
+
+#ifndef __UCLIBC__
+extern size_t strlcpy(char *dest, const char *src, size_t size);
+#endif
+
+#endif /* _LINUX_STRING_H_ */
diff --git a/scripts/include/linux/types.h b/scripts/include/linux/types.h
new file mode 100644
index 0000000000..8ebf6278b2
--- /dev/null
+++ b/scripts/include/linux/types.h
@@ -0,0 +1,83 @@
+#ifndef _TOOLS_LINUX_TYPES_H_
+#define _TOOLS_LINUX_TYPES_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */
+#include <asm/types.h>
+
+struct page;
+struct kmem_cache;
+
+typedef enum {
+ GFP_KERNEL,
+ GFP_ATOMIC,
+ __GFP_HIGHMEM,
+ __GFP_HIGH
+} gfp_t;
+
+/*
+ * We define u64 as uint64_t for every architecture
+ * so that we can print it with "%"PRIx64 without getting warnings.
+ *
+ * typedef __u64 u64;
+ * typedef __s64 s64;
+ */
+typedef uint64_t u64;
+typedef int64_t s64;
+
+typedef __u32 u32;
+typedef __s32 s32;
+
+typedef __u16 u16;
+typedef __s16 s16;
+
+typedef __u8 u8;
+typedef __s8 s8;
+
+#ifdef __CHECKER__
+#define __bitwise__ __attribute__((bitwise))
+#else
+#define __bitwise__
+#endif
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __bitwise__
+#else
+#define __bitwise
+#endif
+
+#define __force
+#define __user
+#define __must_check
+#define __cold
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+typedef struct {
+ int counter;
+} atomic_t;
+
+#ifndef __aligned_u64
+# define __aligned_u64 __u64 __attribute__((aligned(8)))
+#endif
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#endif /* _TOOLS_LINUX_TYPES_H_ */
diff --git a/scripts/include/tools/be_byteshift.h b/scripts/include/tools/be_byteshift.h
new file mode 100644
index 0000000000..84c17d8365
--- /dev/null
+++ b/scripts/include/tools/be_byteshift.h
@@ -0,0 +1,70 @@
+#ifndef _TOOLS_BE_BYTESHIFT_H
+#define _TOOLS_BE_BYTESHIFT_H
+
+#include <stdint.h>
+
+static inline uint16_t __get_unaligned_be16(const uint8_t *p)
+{
+ return p[0] << 8 | p[1];
+}
+
+static inline uint32_t __get_unaligned_be32(const uint8_t *p)
+{
+ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+}
+
+static inline uint64_t __get_unaligned_be64(const uint8_t *p)
+{
+ return (uint64_t)__get_unaligned_be32(p) << 32 |
+ __get_unaligned_be32(p + 4);
+}
+
+static inline void __put_unaligned_be16(uint16_t val, uint8_t *p)
+{
+ *p++ = val >> 8;
+ *p++ = val;
+}
+
+static inline void __put_unaligned_be32(uint32_t val, uint8_t *p)
+{
+ __put_unaligned_be16(val >> 16, p);
+ __put_unaligned_be16(val, p + 2);
+}
+
+static inline void __put_unaligned_be64(uint64_t val, uint8_t *p)
+{
+ __put_unaligned_be32(val >> 32, p);
+ __put_unaligned_be32(val, p + 4);
+}
+
+static inline uint16_t get_unaligned_be16(const void *p)
+{
+ return __get_unaligned_be16((const uint8_t *)p);
+}
+
+static inline uint32_t get_unaligned_be32(const void *p)
+{
+ return __get_unaligned_be32((const uint8_t *)p);
+}
+
+static inline uint64_t get_unaligned_be64(const void *p)
+{
+ return __get_unaligned_be64((const uint8_t *)p);
+}
+
+static inline void put_unaligned_be16(uint16_t val, void *p)
+{
+ __put_unaligned_be16(val, p);
+}
+
+static inline void put_unaligned_be32(uint32_t val, void *p)
+{
+ __put_unaligned_be32(val, p);
+}
+
+static inline void put_unaligned_be64(uint64_t val, void *p)
+{
+ __put_unaligned_be64(val, p);
+}
+
+#endif /* _TOOLS_BE_BYTESHIFT_H */
diff --git a/scripts/include/tools/endian.h b/scripts/include/tools/endian.h
new file mode 100644
index 0000000000..8001194008
--- /dev/null
+++ b/scripts/include/tools/endian.h
@@ -0,0 +1,56 @@
+#ifndef _TOOLS_ENDIAN_H
+#define _TOOLS_ENDIAN_H
+
+#include <byteswap.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+
+#ifndef htole16
+#define htole16(x) (x)
+#endif
+#ifndef htole32
+#define htole32(x) (x)
+#endif
+#ifndef htole64
+#define htole64(x) (x)
+#endif
+
+#ifndef le16toh
+#define le16toh(x) (x)
+#endif
+
+#ifndef le32toh
+#define le32toh(x) (x)
+#endif
+
+#ifndef le64toh
+#define le64toh(x) (x)
+#endif
+
+#else /* __BYTE_ORDER */
+
+#ifndef htole16
+#define htole16(x) __bswap_16(x)
+#endif
+#ifndef htole32
+#define htole32(x) __bswap_32(x)
+#endif
+#ifndef htole64
+#define htole64(x) __bswap_64(x)
+#endif
+
+#ifndef le16toh
+#define le16toh(x) __bswap_16(x)
+#endif
+
+#ifndef le32toh
+#define le32toh(x) __bswap_32(x)
+#endif
+
+#ifndef le64toh
+#define le64toh(x) __bswap_64(x)
+#endif
+
+#endif
+
+#endif /* _TOOLS_ENDIAN_H */
diff --git a/scripts/include/tools/le_byteshift.h b/scripts/include/tools/le_byteshift.h
new file mode 100644
index 0000000000..8fe9f2488e
--- /dev/null
+++ b/scripts/include/tools/le_byteshift.h
@@ -0,0 +1,70 @@
+#ifndef _TOOLS_LE_BYTESHIFT_H
+#define _TOOLS_LE_BYTESHIFT_H
+
+#include <stdint.h>
+
+static inline uint16_t __get_unaligned_le16(const uint8_t *p)
+{
+ return p[0] | p[1] << 8;
+}
+
+static inline uint32_t __get_unaligned_le32(const uint8_t *p)
+{
+ return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
+}
+
+static inline uint64_t __get_unaligned_le64(const uint8_t *p)
+{
+ return (uint64_t)__get_unaligned_le32(p + 4) << 32 |
+ __get_unaligned_le32(p);
+}
+
+static inline void __put_unaligned_le16(uint16_t val, uint8_t *p)
+{
+ *p++ = val;
+ *p++ = val >> 8;
+}
+
+static inline void __put_unaligned_le32(uint32_t val, uint8_t *p)
+{
+ __put_unaligned_le16(val >> 16, p + 2);
+ __put_unaligned_le16(val, p);
+}
+
+static inline void __put_unaligned_le64(uint64_t val, uint8_t *p)
+{
+ __put_unaligned_le32(val >> 32, p + 4);
+ __put_unaligned_le32(val, p);
+}
+
+static inline uint16_t get_unaligned_le16(const void *p)
+{
+ return __get_unaligned_le16((const uint8_t *)p);
+}
+
+static inline uint32_t get_unaligned_le32(const void *p)
+{
+ return __get_unaligned_le32((const uint8_t *)p);
+}
+
+static inline uint64_t get_unaligned_le64(const void *p)
+{
+ return __get_unaligned_le64((const uint8_t *)p);
+}
+
+static inline void put_unaligned_le16(uint16_t val, void *p)
+{
+ __put_unaligned_le16(val, p);
+}
+
+static inline void put_unaligned_le32(uint32_t val, void *p)
+{
+ __put_unaligned_le32(val, p);
+}
+
+static inline void put_unaligned_le64(uint64_t val, void *p)
+{
+ __put_unaligned_le64(val, p);
+}
+
+#endif /* _TOOLS_LE_BYTESHIFT_H */
diff --git a/scripts/mxsimage.c b/scripts/mxsimage.c
index 0a5f6a05ef..2b1a5f38b3 100644
--- a/scripts/mxsimage.c
+++ b/scripts/mxsimage.c
@@ -16,12 +16,10 @@
#include <getopt.h>
#include <stdint.h>
#include <arpa/inet.h>
+#include <linux/kernel.h>
#define SB_BLOCK_SIZE 16
-#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
static char *prepfile;
static char *bootloaderfile;