diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/Makefile | 4 | ||||
| -rw-r--r-- | tools/aisimage.c | 1 | ||||
| -rw-r--r-- | tools/buildman/control.py | 9 | ||||
| -rw-r--r-- | tools/fit_image.c | 98 | ||||
| -rw-r--r-- | tools/image-host.c | 208 | ||||
| -rw-r--r-- | tools/mkimage.h | 2 | ||||
| -rw-r--r-- | tools/patman/gitutil.py | 21 | ||||
| -rwxr-xr-x | tools/patman/patman.py | 2 | ||||
| -rw-r--r-- | tools/patman/series.py | 4 | 
9 files changed, 300 insertions, 49 deletions
| diff --git a/tools/Makefile b/tools/Makefile index 93f4a8454..4630f03dc 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -78,6 +78,7 @@ BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)  # Source files which exist outside the tools directory  EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o  EXT_OBJ_FILES-y += common/image.o +EXT_OBJ_FILES-$(CONFIG_FIT) += common/image-fit.o  EXT_OBJ_FILES-y += lib/crc32.o  EXT_OBJ_FILES-y += lib/md5.o  EXT_OBJ_FILES-y += lib/sha1.o @@ -95,6 +96,7 @@ NOPED_OBJ_FILES-y += aisimage.o  NOPED_OBJ_FILES-y += kwbimage.o  NOPED_OBJ_FILES-y += pblimage.o  NOPED_OBJ_FILES-y += imximage.o +NOPED_OBJ_FILES-y += image-host.o  NOPED_OBJ_FILES-y += omapimage.o  NOPED_OBJ_FILES-y += mkenvimage.o  NOPED_OBJ_FILES-y += mkimage.o @@ -202,7 +204,9 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \  			$(obj)crc32.o \  			$(obj)default_image.o \  			$(obj)fit_image.o \ +			$(obj)image-fit.o \  			$(obj)image.o \ +			$(obj)image-host.o \  			$(obj)imximage.o \  			$(obj)kwbimage.o \  			$(obj)pblimage.o \ diff --git a/tools/aisimage.c b/tools/aisimage.c index c645708da..659df8c0e 100644 --- a/tools/aisimage.c +++ b/tools/aisimage.c @@ -32,7 +32,6 @@  #define WORD_ALIGN0	4  #define WORD_ALIGN(len) (((len)+WORD_ALIGN0-1) & ~(WORD_ALIGN0-1))  #define MAX_CMD_BUFFER	4096 -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  static uint32_t ais_img_size; diff --git a/tools/buildman/control.py b/tools/buildman/control.py index 8d7b9b547..4319ce77d 100644 --- a/tools/buildman/control.py +++ b/tools/buildman/control.py @@ -111,6 +111,10 @@ def DoBuildman(options, args):              print col.Color(col.RED, str)              sys.exit(1)          count = gitutil.CountCommitsInBranch(options.git_dir, options.branch) +        if count is None: +            str = "Branch '%s' not found or has no upstream" % options.branch +            print col.Color(col.RED, str) +            sys.exit(1)          count += 1   # Build upstream commit also      if not count: @@ -137,6 +141,11 @@ def DoBuildman(options, args):      upstream_commit = gitutil.GetUpstream(options.git_dir, options.branch)      series = patchstream.GetMetaDataForList(upstream_commit, options.git_dir,              1) +    # Conflicting tags are not a problem for buildman, since it does not use +    # them. For example, Series-version is not useful for buildman. On the +    # other hand conflicting tags will cause an error. So allow later tags +    # to overwrite earlier ones. +    series.allow_overwrite = True      series = patchstream.GetMetaDataForList(range_expr, options.git_dir, None,              series) diff --git a/tools/fit_image.c b/tools/fit_image.c index 76bbba125..cc123dd37 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -47,6 +47,48 @@ static int fit_check_image_types (uint8_t type)  		return EXIT_FAILURE;  } +int mmap_fdt(struct mkimage_params *params, const char *fname, void **blobp, +		struct stat *sbuf) +{ +	void *ptr; +	int fd; + +	/* Load FIT blob into memory (we need to write hashes/signatures) */ +	fd = open(fname, O_RDWR | O_BINARY); + +	if (fd < 0) { +		fprintf(stderr, "%s: Can't open %s: %s\n", +			params->cmdname, fname, strerror(errno)); +		unlink(fname); +		return -1; +	} + +	if (fstat(fd, sbuf) < 0) { +		fprintf(stderr, "%s: Can't stat %s: %s\n", +			params->cmdname, fname, strerror(errno)); +		unlink(fname); +		return -1; +	} + +	ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); +	if (ptr == MAP_FAILED) { +		fprintf(stderr, "%s: Can't read %s: %s\n", +			params->cmdname, fname, strerror(errno)); +		unlink(fname); +		return -1; +	} + +	/* check if ptr has a valid blob */ +	if (fdt_check_header(ptr)) { +		fprintf(stderr, "%s: Invalid FIT blob\n", params->cmdname); +		unlink(fname); +		return -1; +	} + +	*blobp = ptr; +	return fd; +} +  /**   * fit_handle_file - main FIT file processing function   * @@ -65,7 +107,7 @@ static int fit_handle_file (struct mkimage_params *params)  	char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];  	int tfd;  	struct stat sbuf; -	unsigned char *ptr; +	void *ptr;  	/* Flattened Image Tree (FIT) format  handling */  	debug ("FIT format handling\n"); @@ -87,57 +129,25 @@ static int fit_handle_file (struct mkimage_params *params)  	if (system (cmd) == -1) {  		fprintf (stderr, "%s: system(%s) failed: %s\n",  				params->cmdname, cmd, strerror(errno)); -		unlink (tmpfile); -		return (EXIT_FAILURE); -	} - -	/* load FIT blob into memory */ -	tfd = open (tmpfile, O_RDWR|O_BINARY); - -	if (tfd < 0) { -		fprintf (stderr, "%s: Can't open %s: %s\n", -				params->cmdname, tmpfile, strerror(errno)); -		unlink (tmpfile); -		return (EXIT_FAILURE); -	} - -	if (fstat (tfd, &sbuf) < 0) { -		fprintf (stderr, "%s: Can't stat %s: %s\n", -				params->cmdname, tmpfile, strerror(errno)); -		unlink (tmpfile); -		return (EXIT_FAILURE); -	} - -	ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, -				tfd, 0); -	if (ptr == MAP_FAILED) { -		fprintf (stderr, "%s: Can't read %s: %s\n", -				params->cmdname, tmpfile, strerror(errno)); -		unlink (tmpfile); -		return (EXIT_FAILURE); +		goto err_system;  	} -	/* check if ptr has a valid blob */ -	if (fdt_check_header (ptr)) { -		fprintf (stderr, "%s: Invalid FIT blob\n", params->cmdname); -		unlink (tmpfile); -		return (EXIT_FAILURE); -	} +	tfd = mmap_fdt(params, tmpfile, &ptr, &sbuf); +	if (tfd < 0) +		goto err_mmap;  	/* set hashes for images in the blob */ -	if (fit_set_hashes (ptr)) { +	if (fit_add_verification_data(ptr)) {  		fprintf (stderr, "%s Can't add hashes to FIT blob",  				params->cmdname); -		unlink (tmpfile); -		return (EXIT_FAILURE); +		goto err_add_hashes;  	}  	/* add a timestamp at offset 0 i.e., root  */  	if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {  		fprintf (stderr, "%s: Can't add image timestamp\n",  				params->cmdname); -		unlink (tmpfile); -		return (EXIT_FAILURE); +		goto err_add_timestamp;  	}  	debug ("Added timestamp successfully\n"); @@ -153,6 +163,14 @@ static int fit_handle_file (struct mkimage_params *params)  		return (EXIT_FAILURE);  	}  	return (EXIT_SUCCESS); + +err_add_timestamp: +err_add_hashes: +	munmap(ptr, sbuf.st_size); +err_mmap: +err_system: +	unlink(tmpfile); +	return -1;  }  static int fit_check_params (struct mkimage_params *params) diff --git a/tools/image-host.c b/tools/image-host.c new file mode 100644 index 000000000..d944d0ff4 --- /dev/null +++ b/tools/image-host.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2013, Google Inc. + * + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include <bootstage.h> +#include <image.h> +#include <sha1.h> +#include <time.h> +#include <u-boot/crc.h> +#include <u-boot/md5.h> + +/** + * fit_set_hash_value - set hash value in requested has node + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @value: hash value to be set + * @value_len: hash value length + * + * fit_set_hash_value() attempts to set hash value in a node at offset + * given and returns operation status to the caller. + * + * returns + *     0, on success + *     -1, on failure + */ +static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, +				int value_len) +{ +	int ret; + +	ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len); +	if (ret) { +		printf("Can't set hash '%s' property for '%s' node(%s)\n", +		       FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), +		       fdt_strerror(ret)); +		return -1; +	} + +	return 0; +} + +/** + * fit_image_process_hash - Process a single subnode of the images/ node + * + * Check each subnode and process accordingly. For hash nodes we generate + * a hash of the supplised data and store it in the node. + * + * @fit:	pointer to the FIT format image header + * @image_name:	name of image being processes (used to display errors) + * @noffset:	subnode offset + * @data:	data to process + * @size:	size of data in bytes + * @return 0 if ok, -1 on error + */ +static int fit_image_process_hash(void *fit, const char *image_name, +		int noffset, const void *data, size_t size) +{ +	uint8_t value[FIT_MAX_HASH_LEN]; +	const char *node_name; +	int value_len; +	char *algo; + +	node_name = fit_get_name(fit, noffset, NULL); + +	if (fit_image_hash_get_algo(fit, noffset, &algo)) { +		printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", +		       node_name, image_name); +		return -1; +	} + +	if (calculate_hash(data, size, algo, value, &value_len)) { +		printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", +		       algo, node_name, image_name); +		return -1; +	} + +	if (fit_set_hash_value(fit, noffset, value, value_len)) { +		printf("Can't set hash value for '%s' hash node in '%s' image node\n", +		       node_name, image_name); +		return -1; +	} + +	return 0; +} + +/** + * fit_image_add_verification_data() - calculate/set hash data for image node + * + * This adds hash values for a component image node. + * + * All existing hash subnodes are checked, if algorithm property is set to + * one of the supported hash algorithms, hash value is computed and + * corresponding hash node property is set, for example: + * + * Input component image node structure: + * + * o image@1 (at image_noffset) + *   | - data = [binary data] + *   o hash@1 + *     |- algo = "sha1" + * + * Output component image node structure: + * + * o image@1 (at image_noffset) + *   | - data = [binary data] + *   o hash@1 + *     |- algo = "sha1" + *     |- value = sha1(data) + * + * For signature details, please see doc/uImage.FIT/signature.txt + * + * @fit:	Pointer to the FIT format image header + * @image_noffset: Requested component image node + * @return: 0 on success, <0 on failure + */ +int fit_image_add_verification_data(void *fit, int image_noffset) +{ +	const char *image_name; +	const void *data; +	size_t size; +	int noffset; + +	/* Get image data and data length */ +	if (fit_image_get_data(fit, image_noffset, &data, &size)) { +		printf("Can't get image data/size\n"); +		return -1; +	} + +	image_name = fit_get_name(fit, image_noffset, NULL); + +	/* Process all hash subnodes of the component image node */ +	for (noffset = fdt_first_subnode(fit, image_noffset); +	     noffset >= 0; +	     noffset = fdt_next_subnode(fit, noffset)) { +		const char *node_name; +		int ret = 0; + +		/* +		 * Check subnode name, must be equal to "hash" or "signature". +		 * Multiple hash nodes require unique unit node +		 * names, e.g. hash@1, hash@2, signature@1, etc. +		 */ +		node_name = fit_get_name(fit, noffset, NULL); +		if (!strncmp(node_name, FIT_HASH_NODENAME, +			     strlen(FIT_HASH_NODENAME))) { +			ret = fit_image_process_hash(fit, image_name, noffset, +						data, size); +		} +		if (ret) +			return -1; +	} + +	return 0; +} + +int fit_add_verification_data(void *fit) +{ +	int images_noffset; +	int noffset; +	int ret; + +	/* Find images parent node offset */ +	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH); +	if (images_noffset < 0) { +		printf("Can't find images parent node '%s' (%s)\n", +		       FIT_IMAGES_PATH, fdt_strerror(images_noffset)); +		return images_noffset; +	} + +	/* Process its subnodes, print out component images details */ +	for (noffset = fdt_first_subnode(fit, images_noffset); +	     noffset >= 0; +	     noffset = fdt_next_subnode(fit, noffset)) { +		/* +		 * Direct child node of the images parent node, +		 * i.e. component image node. +		 */ +		ret = fit_image_add_verification_data(fit, noffset); +		if (ret) +			return ret; +	} + +	return 0; +} diff --git a/tools/mkimage.h b/tools/mkimage.h index ea45f5c83..e07a6157e 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -42,6 +42,8 @@  #define debug(fmt,args...)  #endif /* MKIMAGE_DEBUG */ +#define ARRAY_SIZE(x)		(sizeof(x) / sizeof((x)[0])) +  #define MKIMAGE_TMPFILE_SUFFIX		".tmp"  #define MKIMAGE_MAX_TMPFILE_LEN		256  #define MKIMAGE_DEFAULT_DTC_OPTIONS	"-I dts -O dtb -p 500" diff --git a/tools/patman/gitutil.py b/tools/patman/gitutil.py index e31da1548..b7f673955 100644 --- a/tools/patman/gitutil.py +++ b/tools/patman/gitutil.py @@ -56,10 +56,14 @@ def GetUpstream(git_dir, branch):      Returns:          Name of upstream branch (e.g. 'upstream/master') or None if none      """ -    remote = command.OutputOneLine('git', '--git-dir', git_dir, 'config', -            'branch.%s.remote' % branch) -    merge = command.OutputOneLine('git', '--git-dir', git_dir, 'config', -            'branch.%s.merge' % branch) +    try: +        remote = command.OutputOneLine('git', '--git-dir', git_dir, 'config', +                                       'branch.%s.remote' % branch) +        merge = command.OutputOneLine('git', '--git-dir', git_dir, 'config', +                                      'branch.%s.merge' % branch) +    except: +        return None +      if remote == '.':          return merge      elif remote and merge: @@ -78,9 +82,11 @@ def GetRangeInBranch(git_dir, branch, include_upstream=False):          branch: Name of branch      Return:          Expression in the form 'upstream..branch' which can be used to -        access the commits. +        access the commits. If the branch does not exist, returns None.      """      upstream = GetUpstream(git_dir, branch) +    if not upstream: +        return None      return '%s%s..%s' % (upstream, '~' if include_upstream else '', branch)  def CountCommitsInBranch(git_dir, branch, include_upstream=False): @@ -90,9 +96,12 @@ def CountCommitsInBranch(git_dir, branch, include_upstream=False):          git_dir: Directory containing git repo          branch: Name of branch      Return: -        Number of patches that exist on top of the branch +        Number of patches that exist on top of the branch, or None if the +        branch does not exist.      """      range_expr = GetRangeInBranch(git_dir, branch, include_upstream) +    if not range_expr: +        return None      pipe = [['git', '--git-dir', git_dir, 'log', '--oneline', '--no-decorate',               range_expr],              ['wc', '-l']] diff --git a/tools/patman/patman.py b/tools/patman/patman.py index a8061a937..7a317c5c2 100755 --- a/tools/patman/patman.py +++ b/tools/patman/patman.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python  #  # Copyright (c) 2011 The Chromium OS Authors.  # diff --git a/tools/patman/series.py b/tools/patman/series.py index 783b3dd13..85ed31688 100644 --- a/tools/patman/series.py +++ b/tools/patman/series.py @@ -40,6 +40,7 @@ class Series(dict):          notes: List of lines in the notes          changes: (dict) List of changes for each version, The key is              the integer version number +        allow_overwrite: Allow tags to overwrite an existing tag      """      def __init__(self):          self.cc = [] @@ -49,6 +50,7 @@ class Series(dict):          self.cover = None          self.notes = []          self.changes = {} +        self.allow_overwrite = False          # Written in MakeCcFile()          #  key: name of patch file @@ -72,7 +74,7 @@ class Series(dict):          """          # If we already have it, then add to our list          name = name.replace('-', '_') -        if name in self: +        if name in self and not self.allow_overwrite:              values = value.split(',')              values = [str.strip() for str in values]              if type(self[name]) != type([]): |