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@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 $@