]> spindle.queued.net Git - xodist/blob - mkext3.sh
initial installer support (no, it doesn't do anything interesting yet)
[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         installer_added=0
98         label=`sed -ne 's/^LABEL=\(.\+\)[[:space:]]\+\/[[:space:]]\+.*/\1/p' configs/${CONFIG_TYPE}/fstab-ext3`
99         prefix=
100         grep -q ' ${mntpt}/boot ' /proc/mounts && prefix=/boot
101         for kern in ${mntpt}/boot/vmlinuz-*; do
102                 v=$(basename $kern | sed 's/vmlinuz-//')
103                 if [ "${v}" = '*' ]; then
104                         echo "*** Error: no kernel images found in /boot!" 1>&2
105                         exit 1
106                 fi
107                 cat >>${mntpt}/boot/grub/menu.lst<<EOF
108
109 title           Debian GNU/Linux, kernel ${v}
110 root            (hd0,0)
111 kernel          ${prefix}/vmlinuz-${v} root=LABEL=${label} ro
112 initrd          ${prefix}/initrd.img-${v}
113 boot
114 EOF
115                 if [ "$installer_added" = "0" ]; then
116                         installer_added=1
117                         cat >>${mntpt}/boot/grub/menu.lst<<EOF
118
119 title           Debian GNU/Linux Installer
120 root            (hd0,0)
121 kernel          ${prefix}/vmlinuz-${v} root=LABEL=${label} ro installer
122 initrd          ${prefix}/initrd.img-${v}
123 boot
124 EOF
125                 fi
126
127         done
128
129         # grub-install is pretty broken, so we do this manually
130         geom=`parted -s "$img" "unit chs" "print" | sed -ne 's/geometry: \([0-9]\+\),\([0-9]\+\),\([0-9]\+\)/:\1 \2 \3:/p' | cut -d: -f2`
131         grub --device-map=/dev/null <<EOF
132 device (hd0) $img
133 geometry (hd0) $geom
134 root (hd0,0)
135 setup (hd0)
136 EOF
137
138 }
139
140 # @img - image to create a filesystem on
141 # @root_dir - root directory to populate the fs with
142 mk_ext3_fs()
143 {
144         img="$1"
145         root_dir="$2"
146
147         # create root mount point
148         mount_point_root=$(mktemp)
149         rm -f $mount_point_root
150         mkdir $mount_point_root
151
152         i=1
153         sed -ne 's/^LABEL=//p' configs/${CONFIG_TYPE}/fstab-ext3 | \
154                         while read name mntpt fstype extra; do
155                 partition_start=$(parted -m -s "$img" "unit B" "print" | grep "^$i" | cut -d: -f2 | cut -dB -f1)
156                 partition_size=$(parted -m -s "$img" "unit B" "print" | grep "^$i" | cut -d: -f4 | cut -dB -f1)
157                 bs=1024
158         
159                 # create the filesystems/swap
160                 attach_loop "$img" "$partition_start"
161                 if [ "$fstype" = "ext3" ]; then
162                         mke2fs -q -b $bs -L "$name" -m0 -j "$LOOP_DEV" $((partition_size / bs))
163                         tune2fs -c0 -i0 "$LOOP_DEV"     # XXX: this is from OLPC days; do we still want this?
164                 elif [ "$fstype" = "ext2" ]; then
165                         mke2fs -q -b $bs -L "$name" -m0 "$LOOP_DEV" $((partition_size / bs))
166                         tune2fs -c0 -i0 "$LOOP_DEV"
167                 elif [ "$fstype" = "swap" ]; then
168                         mkswap -L "$name" "$LOOP_DEV" $((partition_size / bs))
169                 fi
170                 detach_loop "$LOOP_DEV"
171
172                 # mount the root partition if it's found
173                 if [ "$mntpt" = "/" ]; then
174                         mount "$img" "${mount_point_root}" -o loop,offset=$partition_start -t $fstype
175                 fi
176
177                 i=$((i + 1))
178         done
179
180         # mount the rest of the partitions (working around /boot coming before /)
181         sed -ne 's/^LABEL=//p' configs/${CONFIG_TYPE}/fstab-ext3 | \
182                         while read name mntpt fstype extra; do
183
184                 # / is already mounted
185                 if [ "$mntpt" = "/" ]; then
186                         continue
187                 fi
188
189                 # if $mntpt doesn't start with '/', don't mount it
190                 if [ "${mntpt##/}" = "$mntpt" ]; then
191                         continue
192                 fi
193
194                 # parted 1.8 added --machine for easier parsing; however,
195                 # debian still has 1.7 in unstable.
196                 partition_start=$(parted -s "$img" "unit B" "print" | sed -ne "s/^ $i[[:space:]]\+//p" | cut -dB -f1)
197         
198                 [ -d "${mount_point_root}${mntpt}" ] || mkdir -p "${mount_point_root}${mntpt}"
199                 mount "$img" "${mount_point_root}${mntpt}" -o loop,offset=$partition_start -t $fstype
200         done
201         
202         # populate the filesystem
203         cp -ra "$root_dir"/* "$mount_point_root" || true
204         grub_install "$img" "$mount_point_root"
205
206         # umount the filesystem
207         sed -ne 's/^LABEL=//p' configs/${CONFIG_TYPE}/fstab-ext3 | \
208                         while read name mntpt fstype extra; do
209
210                 # don't unmount / yet
211                 if [ "$mntpt" = "/" ]; then
212                         continue
213                 fi
214
215                 # if $mntpt doesn't start with '/', it's not mounted
216                 if [ "${mntpt##/}" = "$mntpt" ]; then
217                         continue
218                 fi
219
220                 umount "${mount_point_root}${mntpt}"
221         done
222
223         umount "${mount_point_root}"
224         rmdir "${mount_point_root}" 
225 }
226
227 usage()
228 {
229         echo "" 1>&2
230         echo "Usage: $0 [<options>] <root directory> <img>" 1>&2
231         echo "" 1>&2
232         echo "Options:" 1>&2
233         echo "  --config-type <config>    directory name in configs/ to use" 1>&2
234         echo "  --help                    display this help screen" 1>&2
235         echo "" 1>&2
236         exit 1
237 }
238
239 while test $# != 0
240 do
241         case $1 in
242         --config-type)
243                 CONFIG_TYPE=$2
244                 [ -d ./configs/${CONFIG_TYPE} ] || {
245                         echo "Error: can't find directory './configs/${CONFIG_TYPE}/'!" 1>&2
246                         exit 2
247                 }
248                 shift
249                 ;;
250         --help|-h)
251                 usage
252                 ;;
253         *)
254                 ROOT_DIR="$1"
255                 shift
256                 if [ "$#" = "1" ]; then
257                         IMG_NAME="$1"
258                 fi
259                 ;;
260         esac
261         shift
262 done
263
264 if [ "$ROOT_DIR" = "" ]; then
265         echo "" 1>&2
266         echo "*** No root directory specified!" 1>&2
267         usage
268 fi
269 if [ "$IMG_NAME" = "" ]; then
270         echo "" 1>&2
271         echo "*** No image name specified!" 1>&2
272         usage
273 fi
274 if [ ! -d "$ROOT_DIR" ]; then
275         echo "" 1>&2
276         echo "*** Unable to find root directory!" 1>&2
277         usage
278 fi
279
280 check_for_cmds losetup parted mke2fs tune2fs grub || exit 1
281
282 # create image's /etc/fstab
283 if [ ! -f ./configs/${CONFIG_TYPE}/fstab-ext3 ]; then
284         echo "*** Unable to find fstab-ext3!" 1>&2
285         exit 1
286 fi
287 sed 's/[[:space:]]#.*//' ./configs/${CONFIG_TYPE}/fstab-ext3 > ${ROOT_DIR}/etc/fstab
288
289 # TODO: this needs to go into an OFW package; here it's a hack
290 # create image's /boot/olpc.fth
291 if [ -f ./configs/${CONFIG_TYPE}/olpc.fth-ext3 ]; then
292         cp ./configs/${CONFIG_TYPE}/olpc.fth-ext3 ${ROOT_DIR}/boot/olpc.fth
293 fi
294
295 create_bootable_img ${IMG_NAME}
296 mk_ext3_fs ${IMG_NAME} ${ROOT_DIR}
297
298 #mount ${IMG_NAME}.ext3 $MOUNT_POINT -o loop,offset=$OS_PART1_BEGIN -t ext3
299 #cp -r "$ROOT_DIR"/* $MOUNT_POINT
300 #umount $MOUNT_POINT