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