A convenient POSIX shell script to pad images by prepending or appending
constant data to prepare them for flashrom digestion.
Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
---
Preparing images for iPXE was a pain without this (I had to build it many
times for debugging), and it is probably useful for other use cases too.
The only thing missing is a mode that repeats the file every 2^N bytes
where 2^N is the nearest larger power of two to the length of the image
to be padded, e.g. if you want to write a 256 kB chip in a 3Com NIC that
does only support up to 128 kB/is one address line short.
And maybe a SI-prefix parser... but first flashrom should get one ;)
util/pad_image.sh | 222 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 222 insertions(+)
create mode 100755 util/pad_image.sh
diff --git a/util/pad_image.sh b/util/pad_image.sh
new file mode 100755
index 0000000..30813f4
--- /dev/null
+++ b/util/pad_image.sh
@@ -0,0 +1,222 @@
+#!/bin/sh
+#
+# This file is part of the flashrom project.
+#
+# Copyright (C) 2013 Stefan Tauner
+#
+# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+assert_cmds_avail () {
+ while [ $# -gt 0 ];
+ do
+ command -v $1 >/dev/null 2>&1 || {
+ echo "$1 is required."
+ exit 1
+ }
+ shift
+ done
+}
+
+assert_cmds_avail "cat" "cp" "dd" "mv" "printf" "tr" "wc"
+
+show_help() {
+ echo "Usage:
+ $0 [-a|-p] [-h] [-f] -i <infile> [-o <outfile>] -s <size> [-v <val>]
+
+ Copies infile into outfile and fills up the remaining space to size with val.
+Options
+ -h or --help
+ this message
+ -a or --append
+ append the padding (default)
+ -p or --prepend
+ prepend the padding
+ -f or --force
+ force to overwrite existing output file
+ -i or --infile <infile>
+ the input file
+ -o or --outfile <outfile>
+ the output file (\"<infile>-padded\" on default)
+ -s or --size <size>
+ the wanted size of the output file in bytes
+ -v or --value <value>
+ the value in common hexadecimal format to be used for padding (0xFF on default)
+"
+}
+
+check_action() {
+ if [ -n "$action" ]; then
+ echo "Error: Multiple actions given.">&2
+ exit 1
+ fi
+}
+
+check_arg() {
+ if [ -z "$2" ]; then
+ echo "Error: $1 requires an argument.">&2
+ exit 1
+ fi
+}
+
+
+prepend () {
+ { tr '\0' $(printf "\\\\%o" "$val") < /dev/zero | dd bs=1 count=$padsize of="$outfile".tmp && \
+ cat "$infile" >> "$outfile".tmp && \
+ mv -f "$outfile".tmp "$outfile" ; } >/dev/null 2>&1 || \
+ return 1
+}
+
+append () {
+ { cp "$infile" "$outfile".tmp && tr '\0' $(printf "\\\\%o" "$val") < /dev/zero | \
+ dd bs=1 count=$padsize of="$outfile".tmp conv=notrunc seek=$filesize && \
+ mv -f "$outfile".tmp "$outfile" ; } >/dev/null 2>&1 || \
+ return 1;
+}
+
+main () {
+ local action=
+ local outfile=
+ local infile=
+ local size=
+ local val=
+ local force=
+
+ # The is the main loop
+ while [ $# -gt 0 ];
+ do
+ case ${1} in
+ -h|--help)
+ action=show_help;
+ shift;;
+ -a|--append)
+ check_action $1
+ action=append
+ shift;;
+ -p|--prepend)
+ check_action $1
+ action=prepend
+ shift;;
+ -f|--force)
+ force=1
+ shift;;
+ -i|--infile)
+ if [ -z "$infile" ] ; then
+ check_arg $1 $2
+ infile=$2
+ else
+ echo "Error: More than one input file given.">&2;
+ exit 1
+ fi
+ shift 2;;
+ -o|--outfile)
+ if [ -z "$outfile" ] ; then
+ check_arg $1 $2
+ outfile=$2
+ else
+ echo "Error: More than one output file given.">&2;
+ exit 1
+ fi
+ shift 2;;
+ -v|--value)
+ if [ -z "$val" ] ; then
+ check_arg $1 $2
+ val=$2
+ else
+ echo "Error: More than one value given.">&2;
+ exit 1
+ fi
+ shift 2;;
+ -s|--size)
+ if [ -z "$size" ] ; then
+ check_arg $1 $2
+ size=$2
+ case $size in
+ ''|[!0-9]*) echo "Error: Could not parse size $size.">&2; exit 1;;
+ *) ;;
+ esac
+ else
+ echo "Error: More than one size given.">&2;
+ exit 1
+ fi
+ shift 2;;
+ -*)
+ show_help;
+ echo "Error: Invalid option: ${1}">&2
+ exit 1;;
+ *)
+ echo "Error: Overabundant parameter: \"${1}\"">&2
+ shift;;
+ esac;
+ done
+
+ if [ -z "$infile" ] ; then
+ show_help
+ echo "Error: No input file specified">&2
+ exit 1
+ fi
+
+ if [ ! -e "$infile" -o ! -r "$infile" -o ! -w "$infile" ]; then
+ echo "Error: ${infile} is not accessible">&2
+ exit 1
+ fi
+
+ if [ -z "$outfile" ] ; then
+ outfile="${infile}-padded"
+ fi
+
+ if [ -z "$force" -a -e "$outfile" ]; then
+ echo "Error: ${outfile} exists already.">&2
+ exit 1
+ fi
+
+ if [ -z "$size" ] ; then
+ show_help
+ echo "Error: No target size specified.">&2
+ exit 1
+ fi
+
+ filesize=$(wc -c < "$infile") || exit 1
+ if [ $size -le $filesize ]; then
+ echo "File is already as large as or even larger than requested.">&2
+ exit 1
+ fi
+
+ # default action is to append
+ if [ -z "$action" ] ; then
+ action=append
+ fi
+
+ # default value is all ones
+ if [ -z "$val" ] ; then
+ val="0xff"
+ fi
+ case $val in
+ ''|[!a-fA-F0-9]*) echo "Could not parse value $val.">&2; exit 1;;
+ *) ;;
+ esac
+
+ padsize=$(($size-$filesize))
+ printf "Copy data from file \"%s\" to \"%s\" and pad it from %d B to %d B by %sing 0x%x %d times... " \
+ $infile $outfile $filesize $size $action $val $padsize
+ if $action ; then
+ echo "done."
+ else
+ echo "failed."
+ return 1
+ fi
+}
+
+main $@
--
Kind regards, Stefan Tauner