The cirros image was rebuilt against the 3.13.0-83 kernel, drivers e1000e, igbvf...
[packages/trusty/cirros-testvm.git] / cirros-testvm / src-cirros / bin / part2disk
1 #!/bin/sh
2 #    part2disk - wrap a partition image in a disk image
3 #
4 #    Copyright (C) 2010 Canonical Ltd.
5 #
6 #    Authors: Scott Moser <smoser@canonical.com>
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, version 3 of the License.
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU General Public License for more details.
16 #
17 #    You should have received a copy of the GNU General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 DEF_SECTOR_SIZE=512
21 DEBUG=0
22 base_d=$(dirname $(readlink -f "${0}"))
23 PATH="${PATH}:${base_d}"
24 error() { echo "$@" 1>&2; }
25 debug() {
26         [ "${DEBUG}" -ge "${1:-0}" ] && shift || return 0;
27         error "$@";
28 }
29 fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
30 getsize() {
31         local fname="$1" kname="" size=""
32         if [ -b "${fname}" ]; then
33                 kname=$(readlink -f "${fname}") &&
34                         size=$(awk '$4 == kn { print $3 * 1024 }' \
35                                 "kn=${kname##*/}" /proc/partitions) &&
36                         [ -n "${size}" ] || {
37                                 error "failed to read size of ${fname} from /proc/partitions";
38                                 return 1;
39                         }
40         else
41                 size=$(stat --format "%s" "${fname}") || {
42                         error "failed to get size of ${fname}"
43                         return 1;
44                 }
45         fi
46         _RET="$size"
47 }
48
49 Usage() {
50         cat <<EOF
51 Usage: ${0##*/} [options] partition-image disk-image
52
53    create disk image 'disk-image' with 'partition-image' in a partition
54    inside it.
55
56    options:
57       -G | --grub       install grub to disk image mbr
58          | --grub1      install grub1 to disk image mbr
59       -s | --size  S    create the disk image of size 'S'.
60                         default is large enough to fit partition-image
61       -v | --verbose    increase verbosity
62 EOF
63 }
64 bad_Usage() { Usage 1>&2; fail "$@"; }
65 human2bytes() {
66    # converts size suitable for input to resize2fs to bytes
67    # s:512 byte sectors, K:kilobytes, M:megabytes, G:gigabytes
68    # none: block size of the image
69    local input=${1} defunit=${2:-1024}
70    local unit count;
71    case "$input" in
72       *s) count=${input%s}; unit=512;;
73       *K) count=${input%K}; unit=1024;;
74       *M) count=${input%M}; unit=$((1024*1024));;
75       *G) count=${input%G}; unit=$((1024*1024*1024));;
76       *)  count=${input}  ; unit=${2:-1024};;
77    esac
78    _RET=$((${count}*${unit}))
79 }
80
81 short_opts="b:c:Ghs:v"
82 long_opts="grub1,grub,help,size:,verbose"
83 getopt_out=$(getopt --name "${0##*/}" \
84         --options "${short_opts}" --long "${long_opts}" -- "$@") &&
85         eval set -- "${getopt_out}" ||
86         bad_Usage
87
88 ssize=${DEF_SECTOR_SIZE}
89 size_in=""
90 grub_ptnum=1
91 grub=0
92 grub1=0
93 while [ $# -ne 0 ]; do
94         cur=${1}; next=${2};
95         case "$cur" in
96                 -G|--grub) grub=1;;
97                 -G|--grub1) grub1=1;;
98                 -h|--help) Usage; exit 0;;
99                 -s|--size) size_in=$2; shift;;
100                 -v|--verbose) DEBUG=$((${DEBUG}+1));;
101                 --) shift; break;;
102         esac
103         shift;
104 done
105
106 [ $# -eq 2 ] || bad_Usage "must supply partition image and output file"
107
108 pimg=${1}
109 dimg=${2}
110
111 { [ ${grub} -eq 0 ] || phelper=$(command -v part2disk-grubhelper); } ||
112         fail "no part2disk-grubhelper in PATH"
113 [ $grub1 -eq 0 ] || command -v grub >/dev/null || fail "no 'grub' in path";
114
115 [ -f "${pimg}" -o -b "${pimg}" ] || fail "${pimg}: not a file or block device"
116
117 getsize "$pimg" ||
118         fail "failed to get size of $pimg"
119 pimg_s="$_RET"
120
121 # end_pad_sectors: room for secondary gpt
122 end_pad_sectors=33
123 end_pad=$(($end_pad_sectors*$ssize))
124 front_pad=$((1024*1024))
125 front_pad_sectors=$(($front_pad/$ssize))
126 padding=$(($front_pad+$end_pad))
127 pt_sector_pad=$(($ssize-(${pimg_s}%$ssize)))
128 if [ $pt_sector_pad -eq $ssize ]; then
129         pt_sector_pad=0
130 fi
131 pt_size=$(($pimg_s+$pt_sector_pad))
132 pt_sectors=$(($pt_size/$ssize))
133 tot_size=$(($front_pad+$pt_size+$end_pad))
134 tot_size_sectors=$(($tot_size/$ssize))
135
136 if [ -n "${size_in}" ]; then
137         human2bytes "${size_in}" 1 || fail "failed to convert ${size_in} to bytes"
138         size=${_RET}
139 else
140         # no size specified, get enough to fit part_img, 1M header and 1M end.
141         size=$((${pimg_s}+$padding+$pt_sector_pad))
142 fi
143
144 if [ -e "$dimg" ]; then
145         getsize "$dimg" ||
146                 fail "failed to get size of $dimg"
147         dimg_s="$_RET"
148 else
149         dimg_s="$size"
150 fi
151
152 if [ "${dimg_s}" -lt "$size" ]; then
153         fail "size of $dimg ($dimg_s) not large enough to fit $size"
154 fi
155
156 debug 1 "input is ${pimg_s} bytes ($pt_sectors sectors of $ssize)."
157 debug 1 "target is ${tot_size} bytes ($tot_size_sectors sectors)."
158 debug 1 "padding $front_pad_sectors sectors at front," \
159         "$end_pad_sectors sectors at end."
160
161 debug 2 "zeroing first $front_pad_sectors sectors $dimg"
162 dd if=/dev/zero of="${dimg}" bs=$ssize "count=${front_pad_sectors}" \
163         2>/dev/null ||
164     fail "failed to write to ${dimg}"
165
166 # copy partition image. this writes $pimg bytes even if that is
167 # not divivisble by $ssize
168 debug 2 "copying ${pimg} to partition in ${dimg}"
169 dd if="$pimg" of="$dimg" seek=${front_pad_sectors} bs=$ssize conv=notrunc \
170         2>/dev/null ||
171         fail "failed to write ${pimg} into ${dimg}"
172
173 # zero any unwritten portion of the final sector
174 leftover=$(($ssize-(${pimg_s}%$ssize)))
175 if [ $pt_sector_pad -ne 0 ]; then
176         debug 2 "finishing final sector with $pt_sector_pad bytes of zeros"
177         dd if=/dev/zero of="$dimg" bs=1 seek=$((${pimg_s}+${front_pad})) \
178                 conv=notrunc count=$pt_sector_pad 2>/dev/null ||
179         fail "failed to finish final sector of $pimg"
180 fi
181
182 # we've now written front pad + round-sectors. now write end_pad
183 debug 2 "writing final $end_pad_sectors sectors"
184 dd if=/dev/zero "of=$dimg" bs=$ssize \
185         seek=$((($size/$ssize)-${end_pad_sectors})) count=${end_pad_sectors} \
186         conv=notrunc 2>/dev/null ||
187         fail "failed to write final 1M to $pimg"
188
189 sfdisk_in="${front_pad_sectors},$pt_sectors,L,*"
190 debug 2 "writing partition table to ${dimg} ($sfdisk_in)"
191 sfdisk_out=$(echo "$sfdisk_in" | sfdisk --force --unit=S "${dimg}" 2>&1)
192
193 [ $? -eq 0 ] || {
194         error "${sfdisk_out}";
195         fail "failed to create partition table";
196 }
197
198 if [ ${grub} -ne 0 ]; then
199         debug 2 "invoking part2disk-grubhelper ${dimg}"
200         sudo "${phelper}" "${dimg}" ||
201                 fail "part2disk-grubhelper ${dimg} failed"
202 fi
203
204 if [ $grub1 -ne 0 ]; then
205         debug 2 "installing grub"
206         grub --no-floppy --batch <<EOF
207 device (hd0) $dimg
208 root (hd0,0)
209 setup (hd0)
210 quit
211 EOF
212 fi
213
214 error "wrote to ${dimg}"
215 # vi: ts=4 noexpandtab