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