summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/.gitignore1
-rw-r--r--tools/Makefile14
-rw-r--r--tools/buildman/README4
-rw-r--r--tools/default_image.c21
-rw-r--r--tools/fdtgrep.c1234
-rw-r--r--tools/imagetool.h1
-rw-r--r--tools/kwbimage.c13
-rw-r--r--tools/mkimage.c77
-rw-r--r--tools/mpc86x_clk.c202
-rw-r--r--tools/patman/README11
-rw-r--r--tools/patman/__init__.py3
-rwxr-xr-xtools/patman/patman.py25
-rw-r--r--tools/patman/setup.py13
13 files changed, 1384 insertions, 235 deletions
diff --git a/tools/.gitignore b/tools/.gitignore
index 9bc9fecf7b..eb1a27e36d 100644
--- a/tools/.gitignore
+++ b/tools/.gitignore
@@ -11,7 +11,6 @@
/mkenvimage
/mkimage
/mkexynosspl
-/mpc86x_clk
/mxsboot
/mksunxiboot
/ncb
diff --git a/tools/Makefile b/tools/Makefile
index 8ff9c2e108..f673258bad 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -58,7 +58,8 @@ hostprogs-$(CONFIG_FIT_SIGNATURE) += fit_info fit_check_sign
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o
# Flattened device tree objects
LIBFDT_OBJS := $(addprefix lib/libfdt/, \
- fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o)
+ fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o \
+ fdt_region.o)
RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
rsa-sign.o rsa-verify.o rsa-checksum.o \
rsa-mod-exp.o)
@@ -116,8 +117,8 @@ ifdef CONFIG_FIT_SIGNATURE
HOST_EXTRACFLAGS += -DCONFIG_FIT_SIGNATURE
endif
-ifdef CONFIG_SYS_SPI_U_BOOT_OFFS
-HOSTCFLAGS_kwbimage.o += -DCONFIG_SYS_SPI_U_BOOT_OFFS=$(CONFIG_SYS_SPI_U_BOOT_OFFS)
+ifdef CONFIG_SYS_U_BOOT_OFFS
+HOSTCFLAGS_kwbimage.o += -DCONFIG_SYS_U_BOOT_OFFS=$(CONFIG_SYS_U_BOOT_OFFS)
endif
# MXSImage needs LibSSL
@@ -155,6 +156,9 @@ hostprogs-$(CONFIG_ARMADA_XP) += kwboot
hostprogs-y += proftool
hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela
+hostprogs-y += fdtgrep
+fdtgrep-objs += $(LIBFDT_OBJS) fdtgrep.o
+
# We build some files with extra pedantic flags to try to minimize things
# that won't build on some weird host compiler -- though there are lots of
# exceptions for files that aren't complaint.
@@ -163,10 +167,6 @@ HOSTCFLAGS_md5.o := -pedantic
HOSTCFLAGS_sha1.o := -pedantic
HOSTCFLAGS_sha256.o := -pedantic
-# Don't build by default
-#hostprogs-$(CONFIG_PPC) += mpc86x_clk
-#HOSTCFLAGS_mpc86x_clk.o := -pedantic
-
quiet_cmd_wrap = WRAP $@
cmd_wrap = echo "\#include <../$(patsubst $(obj)/%,%,$@)>" >$@
diff --git a/tools/buildman/README b/tools/buildman/README
index 8ecdd8f854..10c7135b5f 100644
--- a/tools/buildman/README
+++ b/tools/buildman/README
@@ -318,7 +318,7 @@ settings file to find them.
To make this easier, buildman can automatically download and install
toolchains from kernel.org. First list the available architectures:
-$ ./tools/buildman/buildman sandbox --fetch-arch list
+$ ./tools/buildman/buildman --fetch-arch list
Checking: https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/4.6.3/
Checking: https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/4.6.2/
Checking: https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/4.5.1/
@@ -329,7 +329,7 @@ sparc sparc64 tilegx x86_64 xtensa
Then pick one and download it:
-$ ./tools/buildman/buildman sandbox --fetch-arch or32
+$ ./tools/buildman/buildman --fetch-arch or32
Checking: https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/4.6.3/
Checking: https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/4.6.2/
Checking: https://www.kernel.org/pub/tools/crosstool/files/bin/x86_64/4.5.1/
diff --git a/tools/default_image.c b/tools/default_image.c
index cf5c0d4393..18940af5b5 100644
--- a/tools/default_image.c
+++ b/tools/default_image.c
@@ -88,6 +88,9 @@ static void image_set_header(void *ptr, struct stat *sbuf, int ifd,
struct image_tool_params *params)
{
uint32_t checksum;
+ char *source_date_epoch;
+ struct tm *time_universal;
+ time_t time;
image_header_t * hdr = (image_header_t *)ptr;
@@ -96,9 +99,25 @@ static void image_set_header(void *ptr, struct stat *sbuf, int ifd,
sizeof(image_header_t)),
sbuf->st_size - sizeof(image_header_t));
+ source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+ if (source_date_epoch != NULL) {
+ time = (time_t) strtol(source_date_epoch, NULL, 10);
+
+ time_universal = gmtime(&time);
+ if (time_universal == NULL) {
+ fprintf(stderr, "%s: SOURCE_DATE_EPOCH is not valid\n",
+ __func__);
+ time = 0;
+ } else {
+ time = mktime(time_universal);
+ }
+ } else {
+ time = sbuf->st_mtime;
+ }
+
/* Build new header */
image_set_magic(hdr, IH_MAGIC);
- image_set_time(hdr, sbuf->st_mtime);
+ image_set_time(hdr, time);
image_set_size(hdr, sbuf->st_size - sizeof(image_header_t));
image_set_load(hdr, params->addr);
image_set_ep(hdr, params->ep);
diff --git a/tools/fdtgrep.c b/tools/fdtgrep.c
new file mode 100644
index 0000000000..caaf6006a5
--- /dev/null
+++ b/tools/fdtgrep.c
@@ -0,0 +1,1234 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * Perform a grep of an FDT either displaying the source subset or producing
+ * a new .dtb subset which can be used as required.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <../include/libfdt.h>
+#include <libfdt_internal.h>
+
+/* Define DEBUG to get some debugging output on stderr */
+#ifdef DEBUG
+#define debug(a, b...) fprintf(stderr, a, ## b)
+#else
+#define debug(a, b...)
+#endif
+
+/* A linked list of values we are grepping for */
+struct value_node {
+ int type; /* Types this value matches (FDT_IS... mask) */
+ int include; /* 1 to include matches, 0 to exclude */
+ const char *string; /* String to match */
+ struct value_node *next; /* Pointer to next node, or NULL */
+};
+
+/* Output formats we support */
+enum output_t {
+ OUT_DTS, /* Device tree source */
+ OUT_DTB, /* Valid device tree binary */
+ OUT_BIN, /* Fragment of .dtb, for hashing */
+};
+
+/* Holds information which controls our output and options */
+struct display_info {
+ enum output_t output; /* Output format */
+ int add_aliases; /* Add aliases node to output */
+ int all; /* Display all properties/nodes */
+ int colour; /* Display output in ANSI colour */
+ int region_list; /* Output a region list */
+ int flags; /* Flags (FDT_REG_...) */
+ int list_strings; /* List strings in string table */
+ int show_offset; /* Show offset */
+ int show_addr; /* Show address */
+ int header; /* Output an FDT header */
+ int diff; /* Show +/- diff markers */
+ int include_root; /* Include the root node and all properties */
+ int remove_strings; /* Remove unused strings */
+ int show_dts_version; /* Put '/dts-v1/;' on the first line */
+ int types_inc; /* Mask of types that we include (FDT_IS...) */
+ int types_exc; /* Mask of types that we exclude (FDT_IS...) */
+ int invert; /* Invert polarity of match */
+ struct value_node *value_head; /* List of values to match */
+ const char *output_fname; /* Output filename */
+ FILE *fout; /* File to write dts/dtb output */
+};
+
+static void report_error(const char *where, int err)
+{
+ fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+}
+
+/* Supported ANSI colours */
+enum {
+ COL_BLACK,
+ COL_RED,
+ COL_GREEN,
+ COL_YELLOW,
+ COL_BLUE,
+ COL_MAGENTA,
+ COL_CYAN,
+ COL_WHITE,
+
+ COL_NONE = -1,
+};
+
+/**
+ * print_ansi_colour() - Print out the ANSI sequence for a colour
+ *
+ * @fout: Output file
+ * @col: Colour to output (COL_...), or COL_NONE to reset colour
+ */
+static void print_ansi_colour(FILE *fout, int col)
+{
+ if (col == COL_NONE)
+ fprintf(fout, "\033[0m");
+ else
+ fprintf(fout, "\033[1;%dm", col + 30);
+}
+
+
+/**
+ * value_add() - Add a new value to our list of things to grep for
+ *
+ * @disp: Display structure, holding info about our options
+ * @headp: Pointer to header pointer of list
+ * @type: Type of this value (FDT_IS_...)
+ * @include: 1 if we want to include matches, 0 to exclude
+ * @str: String value to match
+ */
+static int value_add(struct display_info *disp, struct value_node **headp,
+ int type, int include, const char *str)
+{
+ struct value_node *node;
+
+ /*
+ * Keep track of which types we are excluding/including. We don't
+ * allow both including and excluding things, because it doesn't make
+ * sense. 'Including' means that everything not mentioned is
+ * excluded. 'Excluding' means that everything not mentioned is
+ * included. So using the two together would be meaningless.
+ */
+ if (include)
+ disp->types_inc |= type;
+ else
+ disp->types_exc |= type;
+ if (disp->types_inc & disp->types_exc & type) {
+ fprintf(stderr,
+ "Cannot use both include and exclude for '%s'\n", str);
+ return -1;
+ }
+
+ str = strdup(str);
+ node = malloc(sizeof(*node));
+ if (!str || !node) {
+ fprintf(stderr, "Out of memory\n");
+ return -1;
+ }
+ node->next = *headp;
+ node->type = type;
+ node->include = include;
+ node->string = str;
+ *headp = node;
+
+ return 0;
+}
+
+static bool util_is_printable_string(const void *data, int len)
+{
+ const char *s = data;
+ const char *ss, *se;
+
+ /* zero length is not */
+ if (len == 0)
+ return 0;
+
+ /* must terminate with zero */
+ if (s[len - 1] != '\0')
+ return 0;
+
+ se = s + len;
+
+ while (s < se) {
+ ss = s;
+ while (s < se && *s && isprint((unsigned char)*s))
+ s++;
+
+ /* not zero, or not done yet */
+ if (*s != '\0' || s == ss)
+ return 0;
+
+ s++;
+ }
+
+ return 1;
+}
+
+static void utilfdt_print_data(const char *data, int len)
+{
+ int i;
+ const char *p = data;
+ const char *s;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ if (util_is_printable_string(data, len)) {
+ printf(" = ");
+
+ s = data;
+ do {
+ printf("\"%s\"", s);
+ s += strlen(s) + 1;
+ if (s < data + len)
+ printf(", ");
+ } while (s < data + len);
+
+ } else if ((len % 4) == 0) {
+ const uint32_t *cell = (const uint32_t *)data;
+
+ printf(" = <");
+ for (i = 0, len /= 4; i < len; i++)
+ printf("0x%08x%s", fdt32_to_cpu(cell[i]),
+ i < (len - 1) ? " " : "");
+ printf(">");
+ } else {
+ printf(" = [");
+ for (i = 0; i < len; i++)
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
+ printf("]");
+ }
+}
+
+/**
+ * display_fdt_by_regions() - Display regions of an FDT source
+ *
+ * This dumps an FDT as source, but only certain regions of it. This is the
+ * final stage of the grep - we have a list of regions we want to display,
+ * and this function displays them.
+ *
+ * @disp: Display structure, holding info about our options
+ * @blob: FDT blob to display
+ * @region: List of regions to display
+ * @count: Number of regions
+ */
+static int display_fdt_by_regions(struct display_info *disp, const void *blob,
+ struct fdt_region region[], int count)
+{
+ struct fdt_region *reg = region, *reg_end = region + count;
+ uint32_t off_mem_rsvmap = fdt_off_mem_rsvmap(blob);
+ int base = fdt_off_dt_struct(blob);
+ int version = fdt_version(blob);
+ int offset, nextoffset;
+ int tag, depth, shift;
+ FILE *f = disp->fout;
+ uint64_t addr, size;
+ int in_region;
+ int file_ofs;
+ int i;
+
+ if (disp->show_dts_version)
+ fprintf(f, "/dts-v1/;\n");
+
+ if (disp->header) {
+ fprintf(f, "// magic:\t\t0x%x\n", fdt_magic(blob));
+ fprintf(f, "// totalsize:\t\t0x%x (%d)\n", fdt_totalsize(blob),
+ fdt_totalsize(blob));
+ fprintf(f, "// off_dt_struct:\t0x%x\n",
+ fdt_off_dt_struct(blob));
+ fprintf(f, "// off_dt_strings:\t0x%x\n",
+ fdt_off_dt_strings(blob));
+ fprintf(f, "// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
+ fprintf(f, "// version:\t\t%d\n", version);
+ fprintf(f, "// last_comp_version:\t%d\n",
+ fdt_last_comp_version(blob));
+ if (version >= 2) {
+ fprintf(f, "// boot_cpuid_phys:\t0x%x\n",
+ fdt_boot_cpuid_phys(blob));
+ }
+ if (version >= 3) {
+ fprintf(f, "// size_dt_strings:\t0x%x\n",
+ fdt_size_dt_strings(blob));
+ }
+ if (version >= 17) {
+ fprintf(f, "// size_dt_struct:\t0x%x\n",
+ fdt_size_dt_struct(blob));
+ }
+ fprintf(f, "\n");
+ }
+
+ if (disp->flags & FDT_REG_ADD_MEM_RSVMAP) {
+ const struct fdt_reserve_entry *p_rsvmap;
+
+ p_rsvmap = (const struct fdt_reserve_entry *)
+ ((const char *)blob + off_mem_rsvmap);
+ for (i = 0; ; i++) {
+ addr = fdt64_to_cpu(p_rsvmap[i].address);
+ size = fdt64_to_cpu(p_rsvmap[i].size);
+ if (addr == 0 && size == 0)
+ break;
+
+ fprintf(f, "/memreserve/ %llx %llx;\n",
+ (unsigned long long)addr,
+ (unsigned long long)size);
+ }
+ }
+
+ depth = 0;
+ nextoffset = 0;
+ shift = 4; /* 4 spaces per indent */
+ do {
+ const struct fdt_property *prop;
+ const char *name;
+ int show;
+ int len;
+
+ offset = nextoffset;
+
+ /*
+ * Work out the file offset of this offset, and decide
+ * whether it is in the region list or not
+ */
+ file_ofs = base + offset;
+ if (reg < reg_end && file_ofs >= reg->offset + reg->size)
+ reg++;
+ in_region = reg < reg_end && file_ofs >= reg->offset &&
+ file_ofs < reg->offset + reg->size;
+ tag = fdt_next_tag(blob, offset, &nextoffset);
+
+ if (tag == FDT_END)
+ break;
+ show = in_region || disp->all;
+ if (show && disp->diff)
+ fprintf(f, "%c", in_region ? '+' : '-');
+
+ if (!show) {
+ /* Do this here to avoid 'if (show)' in every 'case' */
+ if (tag == FDT_BEGIN_NODE)
+ depth++;
+ else if (tag == FDT_END_NODE)
+ depth--;
+ continue;
+ }
+ if (tag != FDT_END) {
+ if (disp->show_addr)
+ fprintf(f, "%4x: ", file_ofs);
+ if (disp->show_offset)
+ fprintf(f, "%4x: ", file_ofs - base);
+ }
+
+ /* Green means included, red means excluded */
+ if (disp->colour)
+ print_ansi_colour(f, in_region ? COL_GREEN : COL_RED);
+
+ switch (tag) {
+ case FDT_PROP:
+ prop = fdt_get_property_by_offset(blob, offset, NULL);
+ name = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
+ fprintf(f, "%*s%s", depth * shift, "", name);
+ utilfdt_print_data(prop->data,
+ fdt32_to_cpu(prop->len));
+ fprintf(f, ";");
+ break;
+
+ case FDT_NOP:
+ fprintf(f, "%*s// [NOP]", depth * shift, "");
+ break;
+
+ case FDT_BEGIN_NODE:
+ name = fdt_get_name(blob, offset, &len);
+ fprintf(f, "%*s%s {", depth++ * shift, "",
+ *name ? name : "/");
+ break;
+
+ case FDT_END_NODE:
+ fprintf(f, "%*s};", --depth * shift, "");
+ break;
+ }
+
+ /* Reset colour back to normal before end of line */
+ if (disp->colour)
+ print_ansi_colour(f, COL_NONE);
+ fprintf(f, "\n");
+ } while (1);
+
+ /* Print a list of strings if requested */
+ if (disp->list_strings) {
+ const char *str;
+ int str_base = fdt_off_dt_strings(blob);
+
+ for (offset = 0; offset < fdt_size_dt_strings(blob);
+ offset += strlen(str) + 1) {
+ str = fdt_string(blob, offset);
+ int len = strlen(str) + 1;
+ int show;
+
+ /* Only print strings that are in the region */
+ file_ofs = str_base + offset;
+ in_region = reg < reg_end &&
+ file_ofs >= reg->offset &&
+ file_ofs + len < reg->offset +
+ reg->size;
+ show = in_region || disp->all;
+ if (show && disp->diff)
+ printf("%c", in_region ? '+' : '-');
+ if (disp->show_addr)
+ printf("%4x: ", file_ofs);
+ if (disp->show_offset)
+ printf("%4x: ", offset);
+ printf("%s\n", str);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * dump_fdt_regions() - Dump regions of an FDT as binary data
+ *
+ * This dumps an FDT as binary, but only certain regions of it. This is the
+ * final stage of the grep - we have a list of regions we want to dump,
+ * and this function dumps them.
+ *
+ * The output of this function may or may not be a valid FDT. To ensure it
+ * is, these disp->flags must be set:
+ *
+ * FDT_REG_SUPERNODES: ensures that subnodes are preceeded by their
+ * parents. Without this option, fragments of subnode data may be
+ * output without the supernodes above them. This is useful for
+ * hashing but cannot produce a valid FDT.
+ * FDT_REG_ADD_STRING_TAB: Adds a string table to the end of the FDT.
+ * Without this none of the properties will have names
+ * FDT_REG_ADD_MEM_RSVMAP: Adds a mem_rsvmap table - an FDT is invalid
+ * without this.
+ *
+ * @disp: Display structure, holding info about our options
+ * @blob: FDT blob to display
+ * @region: List of regions to display
+ * @count: Number of regions
+ * @out: Output destination
+ */
+static int dump_fdt_regions(struct display_info *disp, const void *blob,
+ struct fdt_region region[], int count, char *out)
+{
+ struct fdt_header *fdt;
+ int size, struct_start;
+ int ptr;
+ int i;
+
+ /* Set up a basic header (even if we don't actually write it) */
+ fdt = (struct fdt_header *)out;
+ memset(fdt, '\0', sizeof(*fdt));
+ fdt_set_magic(fdt, FDT_MAGIC);
+ struct_start = FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry));
+ fdt_set_off_mem_rsvmap(fdt, struct_start);
+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+
+ /*
+ * Calculate the total size of the regions we are writing out. The
+ * first will be the mem_rsvmap if the FDT_REG_ADD_MEM_RSVMAP flag
+ * is set. The last will be the string table if FDT_REG_ADD_STRING_TAB
+ * is set.
+ */
+ for (i = size = 0; i < count; i++)
+ size += region[i].size;
+
+ /* Bring in the mem_rsvmap section from the old file if requested */
+ if (count > 0 && (disp->flags & FDT_REG_ADD_MEM_RSVMAP)) {
+ struct_start += region[0].size;
+ size -= region[0].size;
+ }
+ fdt_set_off_dt_struct(fdt, struct_start);
+
+ /* Update the header to have the correct offsets/sizes */
+ if (count >= 2 && (disp->flags & FDT_REG_ADD_STRING_TAB)) {
+ int str_size;
+
+ str_size = region[count - 1].size;
+ fdt_set_size_dt_struct(fdt, size - str_size);
+ fdt_set_off_dt_strings(fdt, struct_start + size - str_size);
+ fdt_set_size_dt_strings(fdt, str_size);
+ fdt_set_totalsize(fdt, struct_start + size);
+ }
+
+ /* Write the header if required */
+ ptr = 0;
+ if (disp->header) {
+ ptr = sizeof(*fdt);
+ while (ptr < fdt_off_mem_rsvmap(fdt))
+ out[ptr++] = '\0';
+ }
+
+ /* Output all the nodes including any mem_rsvmap/string table */
+ for (i = 0; i < count; i++) {
+ struct fdt_region *reg = &region[i];
+
+ memcpy(out + ptr, (const char *)blob + reg->offset, reg->size);
+ ptr += reg->size;
+ }
+
+ return ptr;
+}
+
+/**
+ * show_region_list() - Print out a list of regions
+ *
+ * The list includes the region offset (absolute offset from start of FDT
+ * blob in bytes) and size
+ *
+ * @reg: List of regions to print
+ * @count: Number of regions
+ */
+static void show_region_list(struct fdt_region *reg, int count)
+{
+ int i;
+
+ printf("Regions: %d\n", count);
+ for (i = 0; i < count; i++, reg++) {
+ printf("%d: %-10x %-10x\n", i, reg->offset,
+ reg->offset + reg->size);
+ }
+}
+
+static int check_type_include(void *priv, int type, const char *data, int size)
+{
+ struct display_info *disp = priv;
+ struct value_node *val;
+ int match, none_match = FDT_IS_ANY;
+
+ /* If none of our conditions mention this type, we know nothing */
+ debug("type=%x, data=%s\n", type, data ? data : "(null)");
+ if (!((disp->types_inc | disp->types_exc) & type)) {
+ debug(" - not in any condition\n");
+ return -1;
+ }
+
+ /*
+ * Go through the list of conditions. For inclusive conditions, we
+ * return 1 at the first match. For exclusive conditions, we must
+ * check that there are no matches.
+ */
+ for (val = disp->value_head; val; val = val->next) {
+ if (!(type & val->type))
+ continue;
+ match = fdt_stringlist_contains(data, size, val->string);
+ debug(" - val->type=%x, str='%s', match=%d\n",
+ val->type, val->string, match);
+ if (match && val->include) {
+ debug(" - match inc %s\n", val->string);
+ return 1;
+ }
+ if (match)
+ none_match &= ~val->type;
+ }
+
+ /*
+ * If this is an exclusive condition, and nothing matches, then we
+ * should return 1.
+ */
+ if ((type & disp->types_exc) && (none_match & type)) {
+ debug(" - match exc\n");
+ /*
+ * Allow FDT_IS_COMPAT to make the final decision in the
+ * case where there is no specific type
+ */
+ if (type == FDT_IS_NODE && disp->types_exc == FDT_ANY_GLOBAL) {
+ debug(" - supressed exc node\n");
+ return -1;
+ }
+ return 1;
+ }
+
+ /*
+ * Allow FDT_IS_COMPAT to make the final decision in the
+ * case where there is no specific type (inclusive)
+ */
+ if (type == FDT_IS_NODE && disp->types_inc == FDT_ANY_GLOBAL)
+ return -1;
+
+ debug(" - no match, types_inc=%x, types_exc=%x, none_match=%x\n",
+ disp->types_inc, disp->types_exc, none_match);
+
+ return 0;
+}
+
+/**
+ * h_include() - Include handler function for fdt_find_regions()
+ *
+ * This function decides whether to include or exclude a node, property or
+ * compatible string. The function is defined by fdt_find_regions().
+ *
+ * The algorithm is documented in the code - disp->invert is 0 for normal
+ * operation, and 1 to invert the sense of all matches.
+ *
+ * See
+ */
+static int h_include(void *priv, const void *fdt, int offset, int type,
+ const char *data, int size)
+{
+ struct display_info *disp = priv;
+ int inc, len;
+
+ inc = check_type_include(priv, type, data, size);
+ if (disp->include_root && type == FDT_IS_PROP && offset == 0 && inc)
+ return 1;
+
+ /*
+ * If the node name does not tell us anything, check the
+ * compatible string
+ */
+ if (inc == -1 && type == FDT_IS_NODE) {
+ debug(" - checking compatible2\n");
+ data = fdt_getprop(fdt, offset, "compatible", &len);
+ inc = check_type_include(priv, FDT_IS_COMPAT, data, len);
+ }
+
+ /* If we still have no idea, check for properties in the node */
+ if (inc != 1 && type == FDT_IS_NODE &&
+ (disp->types_inc & FDT_NODE_HAS_PROP)) {
+ debug(" - checking node '%s'\n",
+ fdt_get_name(fdt, offset, NULL));
+ for (offset = fdt_first_property_offset(fdt, offset);
+ offset > 0 && inc != 1;
+ offset = fdt_next_property_offset(fdt, offset)) {
+ const struct fdt_property *prop;
+ const char *str;
+
+ prop = fdt_get_property_by_offset(fdt, offset, NULL);
+ if (!prop)
+ continue;
+ str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ inc = check_type_include(priv, FDT_NODE_HAS_PROP, str,
+ strlen(str));
+ }
+ if (inc == -1)
+ inc = 0;
+ }
+
+ switch (inc) {
+ case 1:
+ inc = !disp->invert;
+ break;
+ case 0:
+ inc = disp->invert;
+ break;
+ }
+ debug(" - returning %d\n", inc);
+
+ return inc;
+}
+
+static int h_cmp_region(const void *v1, const void *v2)
+{
+ const struct fdt_region *region1 = v1, *region2 = v2;
+
+ return region1->offset - region2->offset;
+}
+
+static int fdtgrep_find_regions(const void *fdt,
+ int (*include_func)(void *priv, const void *fdt, int offset,
+ int type, const char *data, int size),
+ struct display_info *disp, struct fdt_region *region,
+ int max_regions, char *path, int path_len, int flags)
+{
+ struct fdt_region_state state;
+ int count;
+ int ret;
+
+ count = 0;
+ ret = fdt_first_region(fdt, include_func, disp,
+ &region[count++], path, path_len,
+ disp->flags, &state);
+ while (ret == 0) {
+ ret = fdt_next_region(fdt, include_func, disp,
+ count < max_regions ? &region[count] : NULL,
+ path, path_len, disp->flags, &state);
+ if (!ret)
+ count++;
+ }
+
+ /* Find all the aliases and add those regions back in */
+ if (disp->add_aliases && count < max_regions) {
+ int new_count;
+
+ new_count = fdt_add_alias_regions(fdt, region, count,
+ max_regions, &state);
+ if (new_count > max_regions) {
+ region = malloc(new_count * sizeof(struct fdt_region));
+ if (!region) {
+ fprintf(stderr,
+ "Out of memory for %d regions\n",
+ count);
+ return -1;
+ }
+ memcpy(region, state.region,
+ count * sizeof(struct fdt_region));
+ free(state.region);
+ new_count = fdt_add_alias_regions(fdt, region, count,
+ max_regions, &state);
+ }
+
+ /*
+ * The alias regions will now be at the end of the list. Sort
+ * the regions by offset to get things into the right order
+ */
+ qsort(region, new_count, sizeof(struct fdt_region),
+ h_cmp_region);
+ count = new_count;
+ }
+
+ if (ret != -FDT_ERR_NOTFOUND)
+ return ret;
+
+ return count;
+}
+
+int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
+{
+ int fd = 0; /* assume stdin */
+ char *buf = NULL;
+ off_t bufsize = 1024, offset = 0;
+ int ret = 0;
+
+ *buffp = NULL;
+ if (strcmp(filename, "-") != 0) {
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return errno;
+ }
+
+ /* Loop until we have read everything */
+ buf = malloc(bufsize);
+ if (!buf)
+ return -ENOMEM;
+ do {
+ /* Expand the buffer to hold the next chunk */
+ if (offset == bufsize) {
+ bufsize *= 2;
+ buf = realloc(buf, bufsize);
+ if (!buf)
+ return -ENOMEM;
+ }
+
+ ret = read(fd, &buf[offset], bufsize - offset);
+ if (ret < 0) {
+ ret = errno;
+ break;
+ }
+ offset += ret;
+ } while (ret != 0);
+
+ /* Clean up, including closing stdin; return errno on error */
+ close(fd);
+ if (ret)
+ free(buf);
+ else
+ *buffp = buf;
+ *len = bufsize;
+ return ret;
+}
+
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+ off_t len;
+ return utilfdt_read_err_len(filename, buffp, &len);
+}
+
+char *utilfdt_read_len(const char *filename, off_t *len)
+{
+ char *buff;
+ int ret = utilfdt_read_err_len(filename, &buff, len);
+
+ if (ret) {
+ fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
+ strerror(ret));
+ return NULL;
+ }
+ /* Successful read */
+ return buff;
+}
+
+char *utilfdt_read(const char *filename)
+{
+ off_t len;
+ return utilfdt_read_len(filename, &len);
+}
+
+/**
+ * Run the main fdtgrep operation, given a filename and valid arguments
+ *
+ * @param disp Display information / options
+ * @param filename Filename of blob file
+ * @param return 0 if ok, -ve on error
+ */
+static int do_fdtgrep(struct display_info *disp, const char *filename)
+{
+ struct fdt_region *region;
+ int max_regions;
+ int count = 100;
+ char path[1024];
+ char *blob;
+ int i, ret;
+
+ blob = utilfdt_read(filename);
+ if (!blob)
+ return -1;
+ ret = fdt_check_header(blob);
+ if (ret) {
+ fprintf(stderr, "Error: %s\n", fdt_strerror(ret));
+ return ret;
+ }
+
+ /* Allow old files, but they are untested */
+ if (fdt_version(blob) < 17 && disp->value_head) {
+ fprintf(stderr,
+ "Warning: fdtgrep does not fully support version %d files\n",
+ fdt_version(blob));
+ }
+
+ /*
+ * We do two passes, since we don't know how many regions we need.
+ * The first pass will count the regions, but if it is too many,
+ * we do another pass to actually record them.
+ */
+ for (i = 0; i < 2; i++) {
+ region = malloc(count * sizeof(struct fdt_region));
+ if (!region) {
+ fprintf(stderr, "Out of memory for %d regions\n",
+ count);
+ return -1;
+ }
+ max_regions = count;
+ count = fdtgrep_find_regions(blob,
+ h_include, disp,
+ region, max_regions, path, sizeof(path),
+ disp->flags);
+ if (count < 0) {
+ report_error("fdt_find_regions", count);
+ return -1;
+ }
+ if (count <= max_regions)
+ break;
+ free(region);
+ }
+
+ /* Optionally print a list of regions */
+ if (disp->region_list)
+ show_region_list(region, count);
+
+ /* Output either source .dts or binary .dtb */
+ if (disp->output == OUT_DTS) {
+ ret = display_fdt_by_regions(disp, blob, region, count);
+ } else {
+ void *fdt;
+ /* Allow reserved memory section to expand slightly */
+ int size = fdt_totalsize(blob) + 16;
+
+ fdt = malloc(size);
+ if (!fdt) {
+ fprintf(stderr, "Out_of_memory\n");
+ ret = -1;
+ goto err;
+ }
+ size = dump_fdt_regions(disp, blob, region, count, fdt);
+ if (disp->remove_strings) {
+ void *out;
+
+ out = malloc(size);
+ if (!out) {
+ fprintf(stderr, "Out_of_memory\n");
+ ret = -1;
+ goto err;
+ }
+ ret = fdt_remove_unused_strings(fdt, out);
+ if (ret < 0) {
+ fprintf(stderr,
+ "Failed to remove unused strings: err=%d\n",
+ ret);
+ goto err;
+ }
+ free(fdt);
+ fdt = out;
+ ret = fdt_pack(fdt);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to pack: err=%d\n",
+ ret);
+ goto err;
+ }
+ size = fdt_totalsize(fdt);
+ }
+
+ if (size != fwrite(fdt, 1, size, disp->fout)) {
+ fprintf(stderr, "Write failure, %d bytes\n", size);
+ free(fdt);
+ ret = 1;
+ goto err;
+ }
+ free(fdt);
+ }
+err:
+ free(blob);
+ free(region);
+
+ return ret;
+}
+
+static const char usage_synopsis[] =
+ "fdtgrep - extract portions from device tree\n"
+ "\n"
+ "Usage:\n"
+ " fdtgrep <options> <dt file>|-\n\n"
+ "Output formats are:\n"
+ "\tdts - device tree soure text\n"
+ "\tdtb - device tree blob (sets -Hmt automatically)\n"
+ "\tbin - device tree fragment (may not be a valid .dtb)";
+
+/* Helper for usage_short_opts string constant */
+#define USAGE_COMMON_SHORT_OPTS "hV"
+
+/* Helper for aligning long_opts array */
+#define a_argument required_argument
+
+/* Helper for usage_long_opts option array */
+#define USAGE_COMMON_LONG_OPTS \
+ {"help", no_argument, NULL, 'h'}, \
+ {"version", no_argument, NULL, 'V'}, \
+ {NULL, no_argument, NULL, 0x0}
+
+/* Helper for usage_opts_help array */
+#define USAGE_COMMON_OPTS_HELP \
+ "Print this help and exit", \
+ "Print version and exit", \
+ NULL
+
+/* Helper for getopt case statements */
+#define case_USAGE_COMMON_FLAGS \
+ case 'h': usage(NULL); \
+ case 'V': util_version(); \
+ case '?': usage("unknown option");
+
+static const char usage_short_opts[] =
+ "haAc:b:C:defg:G:HIlLmn:N:o:O:p:P:rRsStTv"
+ USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"show-address", no_argument, NULL, 'a'},
+ {"colour", no_argument, NULL, 'A'},
+ {"include-node-with-prop", a_argument, NULL, 'b'},
+ {"include-compat", a_argument, NULL, 'c'},
+ {"exclude-compat", a_argument, NULL, 'C'},
+ {"diff", no_argument, NULL, 'd'},
+ {"enter-node", no_argument, NULL, 'e'},
+ {"show-offset", no_argument, NULL, 'f'},
+ {"include-match", a_argument, NULL, 'g'},
+ {"exclude-match", a_argument, NULL, 'G'},
+ {"show-header", no_argument, NULL, 'H'},
+ {"show-version", no_argument, NULL, 'I'},
+ {"list-regions", no_argument, NULL, 'l'},
+ {"list-strings", no_argument, NULL, 'L'},
+ {"include-mem", no_argument, NULL, 'm'},
+ {"include-node", a_argument, NULL, 'n'},
+ {"exclude-node", a_argument, NULL, 'N'},
+ {"include-prop", a_argument, NULL, 'p'},
+ {"exclude-prop", a_argument, NULL, 'P'},
+ {"remove-strings", no_argument, NULL, 'r'},
+ {"include-root", no_argument, NULL, 'R'},
+ {"show-subnodes", no_argument, NULL, 's'},
+ {"skip-supernodes", no_argument, NULL, 'S'},
+ {"show-stringtab", no_argument, NULL, 't'},
+ {"show-aliases", no_argument, NULL, 'T'},
+ {"out", a_argument, NULL, 'o'},
+ {"out-format", a_argument, NULL, 'O'},
+ {"invert-match", no_argument, NULL, 'v'},
+ USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+ "Display address",
+ "Show all nodes/tags, colour those that match",
+ "Include contains containing property",
+ "Compatible nodes to include in grep",
+ "Compatible nodes to exclude in grep",
+ "Diff: Mark matching nodes with +, others with -",
+ "Enter direct subnode names of matching nodes",
+ "Display offset",
+ "Node/property/compatible string to include in grep",
+ "Node/property/compatible string to exclude in grep",
+ "Output a header",
+ "Put \"/dts-v1/;\" on first line of dts output",
+ "Output a region list",
+ "List strings in string table",
+ "Include mem_rsvmap section in binary output",
+ "Node to include in grep",
+ "Node to exclude in grep",
+ "Property to include in grep",
+ "Property to exclude in grep",
+ "Remove unused strings from string table",
+ "Include root node and all properties",
+ "Show all subnodes matching nodes",
+ "Don't include supernodes of matching nodes",
+ "Include string table in binary output",
+ "Include matching aliases in output",
+ "-o <output file>",
+ "-O <output format>",
+ "Invert the sense of matching (select non-matching lines)",
+ USAGE_COMMON_OPTS_HELP
+};
+
+/**
+ * Call getopt_long() with standard options
+ *
+ * Since all util code runs getopt in the same way, provide a helper.
+ */
+#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
+ usage_long_opts, NULL)
+
+void util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts, struct option const long_opts[],
+ const char * const opts_help[])
+{
+ FILE *fp = errmsg ? stderr : stdout;
+ const char a_arg[] = "<arg>";
+ size_t a_arg_len = strlen(a_arg) + 1;
+ size_t i;
+ int optlen;
+
+ fprintf(fp,
+ "Usage: %s\n"
+ "\n"
+ "Options: -[%s]\n", synopsis, short_opts);
+
+ /* prescan the --long opt length to auto-align */
+ optlen = 0;
+ for (i = 0; long_opts[i].name; ++i) {
+ /* +1 is for space between --opt and help text */
+ int l = strlen(long_opts[i].name) + 1;
+ if (long_opts[i].has_arg == a_argument)
+ l += a_arg_len;
+ if (optlen < l)
+ optlen = l;
+ }
+
+ for (i = 0; long_opts[i].name; ++i) {
+ /* helps when adding new applets or options */
+ assert(opts_help[i] != NULL);
+
+ /* first output the short flag if it has one */
+ if (long_opts[i].val > '~')
+ fprintf(fp, " ");
+ else
+ fprintf(fp, " -%c, ", long_opts[i].val);
+
+ /* then the long flag */
+ if (long_opts[i].has_arg == no_argument) {
+ fprintf(fp, "--%-*s", optlen, long_opts[i].name);
+ } else {
+ fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
+ (int)(optlen - strlen(long_opts[i].name) -
+ a_arg_len), "");
+ }
+
+ /* finally the help text */
+ fprintf(fp, "%s\n", opts_help[i]);
+ }
+
+ if (errmsg) {
+ fprintf(fp, "\nError: %s\n", errmsg);
+ exit(EXIT_FAILURE);
+ } else {
+ exit(EXIT_SUCCESS);
+ }
+}
+
+/**
+ * Show usage and exit
+ *
+ * If you name all your usage variables with usage_xxx, then you can call this
+ * help macro rather than expanding all arguments yourself.
+ *
+ * @param errmsg If non-NULL, an error message to display
+ */
+#define usage(errmsg) \
+ util_usage(errmsg, usage_synopsis, usage_short_opts, \
+ usage_long_opts, usage_opts_help)
+
+void util_version(void)
+{
+ printf("Version: %s\n", "(U-Boot)");
+ exit(0);
+}
+
+static void scan_args(struct display_info *disp, int argc, char *argv[])
+{
+ int opt;
+
+ while ((opt = util_getopt_long()) != EOF) {
+ int type = 0;
+ int inc = 1;
+
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+ case 'a':
+ disp->show_addr = 1;
+ break;
+ case 'A':
+ disp->all = 1;
+ break;
+ case 'b':
+ type = FDT_NODE_HAS_PROP;
+ break;
+ case 'C':
+ inc = 0;
+ /* no break */
+ case 'c':
+ type = FDT_IS_COMPAT;
+ break;
+ case 'd':
+ disp->diff = 1;
+ break;
+ case 'e':
+ disp->flags |= FDT_REG_DIRECT_SUBNODES;
+ break;
+ case 'f':
+ disp->show_offset = 1;
+ break;
+ case 'G':
+ inc = 0;
+ /* no break */
+ case 'g':
+ type = FDT_ANY_GLOBAL;
+ break;
+ case 'H':
+ disp->header = 1;
+ break;
+ case 'l':
+ disp->region_list = 1;
+ break;
+ case 'L':
+ disp->list_strings = 1;
+ break;
+ case 'm':
+ disp->flags |= FDT_REG_ADD_MEM_RSVMAP;
+ break;
+ case 'N':
+ inc = 0;
+ /* no break */
+ case 'n':
+ type = FDT_IS_NODE;
+ break;
+ case 'o':
+ disp->output_fname = optarg;
+ break;
+ case 'O':
+ if (!strcmp(optarg, "dtb"))
+ disp->output = OUT_DTB;
+ else if (!strcmp(optarg, "dts"))
+ disp->output = OUT_DTS;
+ else if (!strcmp(optarg, "bin"))
+ disp->output = OUT_BIN;
+ else
+ usage("Unknown output format");
+ break;
+ case 'P':
+ inc = 0;
+ /* no break */
+ case 'p':
+ type = FDT_IS_PROP;
+ break;
+ case 'r':
+ disp->remove_strings = 1;
+ break;
+ case 'R':
+ disp->include_root = 1;
+ break;
+ case 's':
+ disp->flags |= FDT_REG_ALL_SUBNODES;
+ break;
+ case 'S':
+ disp->flags &= ~FDT_REG_SUPERNODES;
+ break;
+ case 't':
+ disp->flags |= FDT_REG_ADD_STRING_TAB;
+ break;
+ case 'T':
+ disp->add_aliases = 1;
+ break;
+ case 'v':
+ disp->invert = 1;
+ break;
+ case 'I':
+ disp->show_dts_version = 1;
+ break;
+ }
+
+ if (type && value_add(disp, &disp->value_head, type, inc,
+ optarg))
+ usage("Cannot add value");
+ }
+
+ if (disp->invert && disp->types_exc)
+ usage("-v has no meaning when used with 'exclude' conditions");
+}
+
+int main(int argc, char *argv[])
+{
+ char *filename = NULL;
+ struct display_info disp;
+ int ret;
+
+ /* set defaults */
+ memset(&disp, '\0', sizeof(disp));
+ disp.flags = FDT_REG_SUPERNODES; /* Default flags */
+
+ scan_args(&disp, argc, argv);
+
+ /* Show matched lines in colour if we can */
+ disp.colour = disp.all && isatty(0);
+
+ /* Any additional arguments can match anything, just like -g */
+ while (optind < argc - 1) {
+ if (value_add(&disp, &disp.value_head, FDT_IS_ANY, 1,
+ argv[optind++]))
+ usage("Cannot add value");
+ }
+
+ if (optind < argc)
+ filename = argv[optind++];
+ if (!filename)
+ usage("Missing filename");
+
+ /* If a valid .dtb is required, set flags to ensure we get one */
+ if (disp.output == OUT_DTB) {
+ disp.header = 1;
+ disp.flags |= FDT_REG_ADD_MEM_RSVMAP | FDT_REG_ADD_STRING_TAB;
+ }
+
+ if (disp.output_fname) {
+ disp.fout = fopen(disp.output_fname, "w");
+ if (!disp.fout)
+ usage("Cannot open output file");
+ } else {
+ disp.fout = stdout;
+ }
+
+ /* Run the grep and output the results */
+ ret = do_fdtgrep(&disp, filename);
+ if (disp.output_fname)
+ fclose(disp.fout);
+ if (ret)
+ return 1;
+
+ return 0;
+}
diff --git a/tools/imagetool.h b/tools/imagetool.h
index b7874f47cd..99bbf2f459 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -59,6 +59,7 @@ struct image_tool_params {
const char *keydest; /* Destination .dtb for public key */
const char *comment; /* Comment to add to signature node */
int require_keys; /* 1 to mark signing keys as 'required' */
+ int file_size; /* Total size of output file */
};
/*
diff --git a/tools/kwbimage.c b/tools/kwbimage.c
index 1ff17cab26..3fa90d3a75 100644
--- a/tools/kwbimage.c
+++ b/tools/kwbimage.c
@@ -115,6 +115,7 @@ struct boot_mode boot_modes[] = {
{ 0x78, "sata" },
{ 0x9C, "pex" },
{ 0x69, "uart" },
+ { 0xAE, "sdio" },
{},
};
@@ -420,15 +421,15 @@ static size_t image_headersz_v1(struct image_tool_params *params,
*hasext = 1;
}
-#if defined(CONFIG_SYS_SPI_U_BOOT_OFFS)
- if (headersz > CONFIG_SYS_SPI_U_BOOT_OFFS) {
+#if defined(CONFIG_SYS_U_BOOT_OFFS)
+ if (headersz > CONFIG_SYS_U_BOOT_OFFS) {
fprintf(stderr, "Error: Image header (incl. SPL image) too big!\n");
- fprintf(stderr, "header=0x%x CONFIG_SYS_SPI_U_BOOT_OFFS=0x%x!\n",
- (int)headersz, CONFIG_SYS_SPI_U_BOOT_OFFS);
- fprintf(stderr, "Increase CONFIG_SYS_SPI_U_BOOT_OFFS!\n");
+ fprintf(stderr, "header=0x%x CONFIG_SYS_U_BOOT_OFFS=0x%x!\n",
+ (int)headersz, CONFIG_SYS_U_BOOT_OFFS);
+ fprintf(stderr, "Increase CONFIG_SYS_U_BOOT_OFFS!\n");
return 0;
} else {
- headersz = CONFIG_SYS_SPI_U_BOOT_OFFS;
+ headersz = CONFIG_SYS_U_BOOT_OFFS;
}
#endif
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 5ccd951048..e81d455083 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -26,8 +26,48 @@ struct image_tool_params params = {
.imagename2 = "",
};
-int
-main (int argc, char **argv)
+static int h_compare_image_name(const void *vtype1, const void *vtype2)
+{
+ const int *type1 = vtype1;
+ const int *type2 = vtype2;
+ const char *name1 = genimg_get_type_short_name(*type1);
+ const char *name2 = genimg_get_type_short_name(*type2);
+
+ return strcmp(name1, name2);
+}
+
+/* Show all image types supported by mkimage */
+static void show_image_types(void)
+{
+ struct image_type_params *tparams;
+ int order[IH_TYPE_COUNT];
+ int count;
+ int type;
+ int i;
+
+ /* Sort the names in order of short name for easier reading */
+ memset(order, '\0', sizeof(order));
+ for (count = 0, type = 0; type < IH_TYPE_COUNT; type++) {
+ tparams = imagetool_get_type(type);
+ if (tparams)
+ order[count++] = type;
+ }
+ qsort(order, count, sizeof(int), h_compare_image_name);
+
+ fprintf(stderr, "\nInvalid image type. Supported image types:\n");
+ for (i = 0; i < count; i++) {
+ type = order[i];
+ tparams = imagetool_get_type(type);
+ if (tparams) {
+ fprintf(stderr, "\t%-15s %s\n",
+ genimg_get_type_short_name(type),
+ genimg_get_type_name(type));
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+int main(int argc, char **argv)
{
int ifd = -1;
struct stat sbuf;
@@ -35,6 +75,7 @@ main (int argc, char **argv)
int retval = 0;
struct image_type_params *tparams = NULL;
int pad_len = 0;
+ int dfd;
params.cmdname = *argv;
params.addr = params.ep = 0;
@@ -75,12 +116,16 @@ main (int argc, char **argv)
usage ();
goto NXTARG;
case 'T':
- if ((--argc <= 0) ||
- (params.type =
- genimg_get_type_id (*++argv)) < 0)
- usage ();
+ params.type = -1;
+ if (--argc >= 0 && argv[1]) {
+ params.type =
+ genimg_get_type_id(*++argv);
+ }
+ if (params.type < 0) {
+ show_image_types();
+ usage();
+ }
goto NXTARG;
-
case 'a':
if (--argc <= 0)
usage ();
@@ -266,6 +311,22 @@ NXTARG: ;
exit (retval);
}
+ dfd = open(params.datafile, O_RDONLY | O_BINARY);
+ if (dfd < 0) {
+ fprintf(stderr, "%s: Can't open %s: %s\n",
+ params.cmdname, params.datafile, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (fstat(dfd, &sbuf) < 0) {
+ fprintf(stderr, "%s: Can't stat %s: %s\n",
+ params.cmdname, params.datafile, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ params.file_size = sbuf.st_size + tparams->header_size;
+ close(dfd);
+
/*
* In case there an header with a variable
* length will be added, the corresponding
@@ -365,6 +426,7 @@ NXTARG: ;
params.cmdname, params.imagefile, strerror(errno));
exit (EXIT_FAILURE);
}
+ params.file_size = sbuf.st_size;
ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
if (ptr == MAP_FAILED) {
@@ -546,6 +608,7 @@ static void usage(void)
#endif
fprintf (stderr, " %s -V ==> print version information and exit\n",
params.cmdname);
+ fprintf(stderr, "Use -T to see a list of available image types\n");
exit (EXIT_FAILURE);
}
diff --git a/tools/mpc86x_clk.c b/tools/mpc86x_clk.c
deleted file mode 100644
index 9f662f73eb..0000000000
--- a/tools/mpc86x_clk.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * (C) Copyright 2003 Intracom S.A.
- * Pantelis Antoniou <panto@intracom.gr>
- *
- * This little program makes an exhaustive search for the
- * correct terms of pdf, mfi, mfn, mfd, s, dbrmo, in PLPRCR.
- * The goal is to produce a gclk2 from a xin input, while respecting
- * all the restrictions on their combination.
- *
- * Generaly you select the first row of the produced table.
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define DPREF_MIN 10000000
-#define DPREF_MAX 32000000
-
-#define DPGDCK_MAX 320000000
-#define DPGDCK_MIN 160000000
-
-#define S_MIN 0
-#define S_MAX 2
-
-#define MFI_MIN 5
-#define MFI_MAX 15
-
-#define MFN_MIN 0
-#define MFN_MAX 15
-
-#define MFD_MIN 0
-#define MFD_MAX 31
-
-#define MF_MIN 5
-#define MF_MAX 15
-
-#define PDF_MIN 0
-#define PDF_MAX 15
-
-#define GCLK2_MAX 150000000
-
-static int calculate (int xin, int target_clock,
- int ppm, int pdf, int mfi, int mfn, int mfd, int s,
- int *dprefp, int *dpgdckp, int *jdbckp,
- int *gclk2p, int *dbrmop)
-{
- unsigned int dpref, dpgdck, jdbck, gclk2, t1, t2, dbrmo;
-
- /* valid MFI? */
- if (mfi < MFI_MIN)
- return -1;
-
- /* valid num, denum? */
- if (mfn > 0 && mfn >= mfd)
- return -1;
-
- dpref = xin / (pdf + 1);
-
- /* valid dpef? */
- if (dpref < DPREF_MIN || dpref > DPREF_MAX)
- return -1;
-
- if (mfn == 0) {
- dpgdck = (2 * mfi * xin) / (pdf + 1) ;
- dbrmo = 0;
- } else {
- /* 5 <= mfi + (mfn / mfd + 1) <= 15 */
- t1 = mfd + 1;
- t2 = mfi * t1 + mfn;
- if ( MF_MIN * t1 > t2 || MF_MAX * t1 < t2)
- return -1;
-
- dpgdck = (unsigned int)(2 * (mfi * mfd + mfi + mfn) *
- (unsigned int)xin) /
- ((mfd + 1) * (pdf + 1));
-
- dbrmo = 10 * mfn < (mfd + 1);
- }
-
- /* valid dpgclk? */
- if (dpgdck < DPGDCK_MIN || dpgdck > DPGDCK_MAX)
- return -1;
-
- jdbck = dpgdck >> s;
- gclk2 = jdbck / 2;
-
- /* valid gclk2 */
- if (gclk2 > GCLK2_MAX)
- return -1;
-
- t1 = abs(gclk2 - target_clock);
-
- /* XXX max 1MHz dev. in clock */
- if (t1 > 1000000)
- return -1;
-
- /* dev within range (XXX gclk2 scaled to avoid overflow) */
- if (t1 * 1000 > (unsigned int)ppm * (gclk2 / 1000))
- return -1;
-
- *dprefp = dpref;
- *dpgdckp = dpgdck;
- *jdbckp = jdbck;
- *gclk2p = gclk2;
- *dbrmop = dbrmo;
-
- return gclk2;
-}
-
-int conf_clock(int xin, int target_clock, int ppm)
-{
- int pdf, s, mfn, mfd, mfi;
- int dpref, dpgdck, jdbck, gclk2, xout, dbrmo;
- int found = 0;
-
- /* integer multipliers */
- for (pdf = PDF_MIN; pdf <= PDF_MAX; pdf++) {
- for (mfi = MFI_MIN; mfi <= MFI_MAX; mfi++) {
- for (s = 0; s <= S_MAX; s++) {
- xout = calculate(xin, target_clock,
- ppm, pdf, mfi, 0, 0, s,
- &dpref, &dpgdck, &jdbck,
- &gclk2, &dbrmo);
- if (xout < 0)
- continue;
-
- if (found == 0) {
- printf("pdf mfi mfn mfd s dbrmo dpref dpgdck jdbck gclk2 exact?\n");
- printf("--- --- --- --- - ----- ----- ------ ----- ----- ------\n");
- }
-
- printf("%3d %3d --- --- %1d %5d %9d %9d %9d %9d%s\n",
- pdf, mfi, s, dbrmo,
- dpref, dpgdck, jdbck, gclk2,
- gclk2 == target_clock ? " YES" : "");
-
- found++;
- }
- }
- }
-
- /* fractional multipliers */
- for (pdf = PDF_MIN; pdf <= PDF_MAX; pdf++) {
- for (mfi = MFI_MIN; mfi <= MFI_MAX; mfi++) {
- for (mfn = 1; mfn <= MFN_MAX; mfn++) {
- for (mfd = 1; mfd <= MFD_MAX; mfd++) {
- for (s = 0; s <= S_MAX; s++) {
- xout = calculate(xin, target_clock,
- ppm, pdf, mfi, mfn, mfd, s,
- &dpref, &dpgdck, &jdbck,
- &gclk2, &dbrmo);
- if (xout < 0)
- continue;
-
- if (found == 0) {
- printf("pdf mfi mfn mfd s dbrmo dpref dpgdck jdbck gclk2 exact?\n");
- printf("--- --- --- --- - ----- ----- ------ ----- ----- ------\n");
- }
-
- printf("%3d %3d %3d %3d %1d %5d %9d %9d %9d %9d%s\n",
- pdf, mfi, mfn, mfd, s,
- dbrmo, dpref, dpgdck, jdbck, gclk2,
- gclk2 == target_clock ? " YES" : "");
-
- found++;
- }
- }
- }
-
- }
- }
-
- return found;
-}
-
-int main(int argc, char *argv[])
-{
- int xin, want_gclk2, found, ppm = 100;
-
- if (argc < 3) {
- fprintf(stderr, "usage: mpc86x_clk <xin> <want_gclk2> [ppm]\n");
- fprintf(stderr, " default ppm is 100\n");
- return 10;
- }
-
- xin = atoi(argv[1]);
- want_gclk2 = atoi(argv[2]);
- if (argc >= 4)
- ppm = atoi(argv[3]);
-
- found = conf_clock(xin, want_gclk2, ppm);
- if (found <= 0) {
- fprintf(stderr, "cannot produce gclk2 %d from xin %d\n",
- want_gclk2, xin);
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/tools/patman/README b/tools/patman/README
index 27ec90acc8..5bd74c4f83 100644
--- a/tools/patman/README
+++ b/tools/patman/README
@@ -135,6 +135,17 @@ Similar to the above, but skip the first commit and take the next 5. This
is useful if your top commit is for setting up testing.
+How to install it
+=================
+
+The most up to date version of patman can be found in the U-boot sources.
+However to use it on other projects it may be more convenient to install it as
+a standalone application. A distutils installer is included, this can be used
+to install patman:
+
+$ cd tools/patman && python setup.py install
+
+
How to add tags
===============
diff --git a/tools/patman/__init__.py b/tools/patman/__init__.py
new file mode 100644
index 0000000000..7cbe5fa4b0
--- /dev/null
+++ b/tools/patman/__init__.py
@@ -0,0 +1,3 @@
+__all__ = ['checkpatch', 'command', 'commit', 'cros_subprocess',
+ 'get_maintainer', 'gitutil', 'patchstream', 'project',
+ 'series', 'settings', 'terminal', 'test']
diff --git a/tools/patman/patman.py b/tools/patman/patman.py
index 6c6473e462..6fe8fe068c 100755
--- a/tools/patman/patman.py
+++ b/tools/patman/patman.py
@@ -14,14 +14,18 @@ import sys
import unittest
# Our modules
-import checkpatch
-import command
-import gitutil
-import patchstream
-import project
-import settings
-import terminal
-import test
+try:
+ from patman import checkpatch, command, gitutil, patchstream, \
+ project, settings, terminal, test
+except ImportError:
+ import checkpatch
+ import command
+ import gitutil
+ import patchstream
+ import project
+ import settings
+ import terminal
+ import test
parser = OptionParser()
@@ -70,8 +74,11 @@ specified by tags you place in the commits. Use -n to do a dry run first."""
settings.Setup(parser, options.project, '')
(options, args) = parser.parse_args()
+if __name__ != "__main__":
+ pass
+
# Run our meagre tests
-if options.test:
+elif options.test:
import doctest
sys.argv = [sys.argv[0]]
diff --git a/tools/patman/setup.py b/tools/patman/setup.py
new file mode 100644
index 0000000000..e61804f178
--- /dev/null
+++ b/tools/patman/setup.py
@@ -0,0 +1,13 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+from distutils.core import setup
+setup(name='patman',
+ version='1.0',
+ license='GPL-2.0+',
+ scripts=['patman'],
+ packages=['patman'],
+ package_dir={'patman': ''},
+ package_data={'patman': ['README']},
+ classifiers=['Environment :: Console',
+ 'Topic :: Software Development'])