]> spindle.queued.net Git - xodist/blob - mkext3.sh
mkext3: don't allow a build that lacks a kernel image to succeed
[xodist] / mkext3.sh
1 #!/bin/bash -e
2 #
3 # Copyright © 2008-2009  Andres Salomon <dilinger@collabora.co.uk>
4 #
5 # This file is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 IMG_NAME=""
20 ROOT_DIR=""
21
22 . ./functions.sh
23
24 CONFIG_TYPE=generic
25
26 # @img - fs image to attach loop device to
27 # @offset - if the image is partitioned, the offset to attach at
28 #
29 # sets $LOOP_DEV with the path of the newly attached loop device
30 attach_loop()
31 {
32         img="$1"
33         offset="$2"
34
35         LOOP_DEV=$(losetup -f)
36
37         if [ "$offset" != "" ]; then
38                 losetup -o "$offset" "$LOOP_DEV" "$img"
39         else
40                 losetup "$LOOP_DEV" "$img"
41         fi
42 }
43
44 # @dev - the loop device to detach
45 detach_loop()
46 {
47         losetup -d "$1"
48 }
49
50 # @img - image name to create
51 create_bootable_img()
52 {
53         img="$1"
54
55         # get the total size by summing all the partition sizes (listed in fstab comments)
56         partition_sizes=`grep '^LABEL=' configs/${CONFIG_TYPE}/fstab-ext3 | \
57                         sed 's/.*#[[:space:]]\+\([0-9]\+\)$/\1/' | xargs echo | tr ' ' +`
58         size=$(($partition_sizes))
59
60         # there's some partition overhead; pad the image so that parted doesn't whine
61         overhead=`echo | awk "{ printf(\"%d\n\", 0.014 * $size); }"`
62         size=$((size + overhead))
63
64         # first, create a sparse image
65         minus_size=$(($size * 6 / 100))
66         size=$(($size - $minus_size))
67         dd if=/dev/zero of=$img bs=1M count=1 seek=$(($size - 1))
68
69         # fill in the partition table
70         parted -s "$img" "mklabel msdos"
71         prior=0
72         grep '^LABEL=' configs/${CONFIG_TYPE}/fstab-ext3 | \
73                         sed 's/.*#[[:space:]]\+\([0-9]\+\)$/\1/' | while read s; do
74                 end=$((prior + s))
75                 parted -s "$img" "mkpart primary ext2 $prior $end"
76                 prior=$end
77         done
78         parted -s "$img" "set 1 boot on"
79 }
80
81 # @img - image name
82 # @mntpt - path to mounted root directory
83 grub_install()
84 {
85         img="$1"
86         mntpt="$2"
87
88         mkdir -p ${mntpt}/boot/grub
89         cp /usr/lib/grub/i386-pc/stage[12] ${mntpt}/boot/grub
90         cp /usr/lib/grub/i386-pc/e2fs_stage1_5 ${mntpt}/boot/grub
91
92         cat >${mntpt}/boot/grub/menu.lst<<EOF
93 default 0
94 timeout 5
95 color cyan/blue white/blue
96 EOF
97         label=`sed -ne 's/^LABEL=\(.\+\)[[:space:]]\+\/[[:space:]]\+.*/\1/p' configs/${CONFIG_TYPE}/fstab-ext3`
98         prefix=
99         grep -q ' ${mntpt}/boot ' /proc/mounts && prefix=/boot
100         for kern in ${mntpt}/boot/vmlinuz-*; do
101                 v=$(basename $kern | sed 's/vmlinuz-//')
102                 if [ "${v}" = '*' ]; then
103                         echo "*** Error: no kernel images found in /boot!" 1>&2
104                         exit 1
105                 fi
106                 cat >>${mntpt}/boot/grub/menu.lst<<EOF
107
108 title           Debian GNU/Linux, kernel ${v}
109 root            (hd0,0)
110 kernel          ${prefix}/vmlinuz-${v} root=LABEL=${label} ro
111 initrd          ${prefix}/initrd.img-${v}
112 boot
113 EOF
114         done
115
116         # grub-install is pretty broken, so we do this manually
117         geom=`parted -s "$img" "unit chs" "print" | sed -ne 's/geometry: \([0-9]\+\),\([0-9]\+\),\([0-9]\+\)/:\1 \2 \3:/p' | cut -d: -f2`
118         grub --device-map=/dev/null <<EOF
119 device (hd0) $img
120 geometry (hd0) $geom
121 root (hd0,0)
122 setup (hd0)
123 EOF
124
125 }
126
127 # @img - image to create a filesystem on
128 # @root_dir - root directory to populate the fs with
129 mk_ext3_fs()
130 {
131         img="$1"
132         root_dir="$2"
133
134         # create root mount point
135         mount_point_root=$(mktemp)
136         rm -f $mount_point_root
137         mkdir $mount_point_root
138
139         i=1
140         sed -ne 's/^LABEL=//p' configs/${CONFIG_TYPE}/fstab-ext3 | \
141                         while read name mntpt fstype extra; do
142                 partition_start=$(parted -m -s "$img" "unit B" "print" | grep "^$i" | cut -d: -f2 | cut -dB -f1)
143                 partition_size=$(parted -m -s "$img" "unit B" "print" | grep "^$i" | cut -d: -f4 | cut -dB -f1)
144                 bs=1024
145         
146                 # create the filesystems/swap
147                 attach_loop "$img" "$partition_start"
148                 if [ "$fstype" = "ext3" ]; then
149                         mke2fs -q -b $bs -L "$name" -m0 -j "$LOOP_DEV" $((partition_size / bs))
150                         tune2fs -c0 -i0 "$LOOP_DEV"     # XXX: this is from OLPC days; do we still want this?
151                 elif [ "$fstype" = "ext2" ]; then
152                         mke2fs -q -b $bs -L "$name" -m0 "$LOOP_DEV" $((partition_size / bs))
153                         tune2fs -c0 -i0 "$LOOP_DEV"
154                 elif [ "$fstype" = "swap" ]; then
155                         mkswap -L "$name" "$LOOP_DEV" $((partition_size / bs))
156                 fi
157                 detach_loop "$LOOP_DEV"
158
159                 # mount the root partition if it's found
160                 if [ "$mntpt" = "/" ]; then
161                         mount "$img" "${mount_point_root}" -o loop,offset=$partition_start -t $fstype
162                 fi
163
164                 i=$((i + 1))
165         done
166
167         # mount the rest of the partitions (working around /boot coming before /)
168         sed -ne 's/^LABEL=//p' configs/${CONFIG_TYPE}/fstab-ext3 | \
169                         while read name mntpt fstype extra; do
170
171                 # / is already mounted
172                 if [ "$mntpt" = "/" ]; then
173                         continue
174                 fi
175
176                 # if $mntpt doesn't start with '/', don't mount it
177                 if [ "${mntpt##/}" = "$mntpt" ]; then
178                         continue
179                 fi
180
181                 # parted 1.8 added --machine for easier parsing; however,
182                 # debian still has 1.7 in unstable.
183                 partition_start=$(parted -s "$img" "unit B" "print" | sed -ne "s/^ $i[[:space:]]\+//p" | cut -dB -f1)
184         
185                 [ -d "${mount_point_root}${mntpt}" ] || mkdir -p "${mount_point_root}${mntpt}"
186                 mount "$img" "${mount_point_root}${mntpt}" -o loop,offset=$partition_start -t $fstype
187         done
188         
189         # populate the filesystem
190         cp -ra "$root_dir"/* "$mount_point_root" || true
191         grub_install "$img" "$mount_point_root"
192
193         # umount the filesystem
194         sed -ne 's/^LABEL=//p' configs/${CONFIG_TYPE}/fstab-ext3 | \
195                         while read name mntpt fstype extra; do
196
197                 # don't unmount / yet
198                 if [ "$mntpt" = "/" ]; then
199                         continue
200                 fi
201
202                 # if $mntpt doesn't start with '/', it's not mounted
203                 if [ "${mntpt##/}" = "$mntpt" ]; then
204                         continue
205                 fi
206
207                 umount "${mount_point_root}${mntpt}"
208         done
209
210         umount "${mount_point_root}"
211         rmdir "${mount_point_root}" 
212 }
213
214 usage()
215 {
216         echo "" 1>&2
217         echo "Usage: $0 [<options>] <root directory> <img>" 1>&2
218         echo "" 1>&2
219         echo "Options:" 1>&2
220         echo "  --config-type <config>    directory name in configs/ to use" 1>&2
221         echo "  --help                    display this help screen" 1>&2
222         echo "" 1>&2
223         exit 1
224 }
225
226 while test $# != 0
227 do
228         case $1 in
229         --config-type)
230                 CONFIG_TYPE=$2
231                 [ -d ./configs/${CONFIG_TYPE} ] || {
232                         echo "Error: can't find directory './configs/${CONFIG_TYPE}/'!" 1>&2
233                         exit 2
234                 }
235                 shift
236                 ;;
237         --help|-h)
238                 usage
239                 ;;
240         *)
241                 ROOT_DIR="$1"
242                 shift
243                 if [ "$#" = "1" ]; then
244                         IMG_NAME="$1"
245                 fi
246                 ;;
247         esac
248         shift
249 done
250
251 if [ "$ROOT_DIR" = "" ]; then
252         echo "" 1>&2
253         echo "*** No root directory specified!" 1>&2
254         usage
255 fi
256 if [ "$IMG_NAME" = "" ]; then
257         echo "" 1>&2
258         echo "*** No image name specified!" 1>&2
259         usage
260 fi
261 if [ ! -d "$ROOT_DIR" ]; then
262         echo "" 1>&2
263         echo "*** Unable to find root directory!" 1>&2
264         usage
265 fi
266
267 check_for_cmds losetup parted mke2fs tune2fs grub || exit 1
268
269 # create image's /etc/fstab
270 if [ ! -f ./configs/${CONFIG_TYPE}/fstab-ext3 ]; then
271         echo "*** Unable to find fstab-ext3!" 1>&2
272         exit 1
273 fi
274 sed 's/[[:space:]]#.*//' ./configs/${CONFIG_TYPE}/fstab-ext3 > ${ROOT_DIR}/etc/fstab
275
276 # TODO: this needs to go into an OFW package; here it's a hack
277 # create image's /boot/olpc.fth
278 if [ -f ./configs/${CONFIG_TYPE}/olpc.fth-ext3 ]; then
279         cp ./configs/${CONFIG_TYPE}/olpc.fth-ext3 ${ROOT_DIR}/boot/olpc.fth
280 fi
281
282 create_bootable_img ${IMG_NAME}
283 mk_ext3_fs ${IMG_NAME} ${ROOT_DIR}
284
285 #mount ${IMG_NAME}.ext3 $MOUNT_POINT -o loop,offset=$OS_PART1_BEGIN -t ext3
286 #cp -r "$ROOT_DIR"/* $MOUNT_POINT
287 #umount $MOUNT_POINT