]> spindle.queued.net Git - xodist/blob - mkimg.sh
initial import
[xodist] / mkimg.sh
1 #!/bin/sh -e
2 #
3 # Copyright © 2008  Andres Salomon <dilinger@queued.net>
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
20
21 IMG_NAME="DebOLPC"
22 ROOT_SIZE="512"
23 IMG_LABEL="DebOLPC"
24 ROOT_DIR=""
25 CRCIMG="./crcimg.pl"
26
27
28 PREREQ_CMDS="losetup dd parted mke2fs tune2fs grub"
29
30 check_for_cmds()
31 {
32         err=0
33         for cmd in $PREREQ_CMDS; do
34                 which $cmd >/dev/null || {
35                         echo "Missing required command '$cmd'!" 1>&2
36                         err=1
37                 }
38         done
39         if [ "$err" = 1 ]; then
40                 exit 1
41         fi
42 }
43
44 # @img - fs image to attach loop device to
45 # @offset - if the image is partitioned, the offset to attach at
46 #
47 # sets $LOOP_DEV with the path of the newly attached loop device
48 attach_loop()
49 {
50         img="$1"
51         offset="$2"
52
53         LOOP_DEV=$(losetup -f)
54
55         if [ "$offset" != "" ]; then
56                 losetup -o "$offset" "$LOOP_DEV" "$img"
57         else
58                 losetup "$LOOP_DEV" "$img"
59         fi
60 }
61
62 # @dev - the loop device to detach
63 detach_loop()
64 {
65         losetup -d "$1"
66 }
67
68 # @img - fs image to mount
69 # @type - fs type to mount
70 # @offset - if the image is partitioned, the offset to mount at
71 #
72 # sets $MOUNT_POINT with the path of the newly created (and mounted) dir
73 mk_mount()
74 {
75         img="$1"
76         type="$2"
77         offset="$3"
78
79         if [ "$offset" != "" ]; then
80                 offset=",offset=$offset"
81         fi
82
83         MOUNT_POINT=$(mktemp)
84         rm -f $MOUNT_POINT
85         mkdir $MOUNT_POINT
86
87         mount "$img" "$MOUNT_POINT" -o loop$offset -t "$type"
88 }
89
90 # @mntpt - directory to umount and delete
91 rm_mount()
92 {
93         umount "$1"
94         rmdir "$1"
95 }
96
97 # @img - image name to create
98 # @size - image size
99 mk_bootable_img()
100 {
101         img="$1"
102         size="$2"
103
104         # first, create a sparse image
105         minus_size=$(($size * 6 / 100))
106         size=$(($size - $minus_size))
107         dd if=/dev/zero of=$img bs=1M count=1 seek=$(($size - 1))
108
109         # fill in the partition table
110         parted -s "$img" "mklabel msdos"
111         parted -s "$img" "mkpart primary ext2 0 -1"
112         parted -s "$img" "set 1 boot on"
113 }
114
115 # @mntpt - path to mounted root directory
116 # @fstype - the root filesystem type (in a form that 'mount' understands)
117 mk_fstab()
118 {
119         mntpt="$1"
120         fstype="$2"
121
122         cat >${mntpt}/etc/fstab<<EOF
123 LABEL=OLPCRoot  /               $fstype defaults,noatime        1 1
124 devpts          /dev/pts        devpts  gid=5,mode=620          0 0
125 tmpfs           /dev/shm        tmpfs   defaults,size=15%       0 0
126 proc            /proc           proc    defaults                0 0
127 sysfs           /sys            sysfs   defaults                0 0
128 EOF
129
130 }
131
132 # @img - image name
133 # @mntpt - path to mounted root directory
134 grub_install()
135 {
136         img="$1"
137         mntpt="$2"
138
139         mkdir -p ${mntpt}/boot/grub
140         cp /usr/lib/grub/i386-pc/stage[12] ${mntpt}/boot/grub
141         cp /usr/lib/grub/i386-pc/e2fs_stage1_5 ${mntpt}/boot/grub
142
143         cat >${mntpt}/boot/grub/menu.lst<<EOF
144 default 0
145 timeout 5
146 color cyan/blue white/blue
147
148 title           $IMG_LABEL
149 root            (hd0,0)
150 kernel          /bzImage root=LABEL=${IMG_LABEL} rootfstype=ext3 ro
151 boot
152 EOF
153
154         # grub-install is pretty broken, so we do this manually
155         geom=`parted -s "$img" "unit chs" "print" | sed -ne 's/geometry: \([0-9]\+\),\([0-9]\+\),\([0-9]\+\)/:\1 \2 \3:/p' | cut -d: -f2`
156         grub --device-map=/dev/null <<EOF
157 device (hd0) $img
158 geometry (hd0) $geom
159 root (hd0,0)
160 setup (hd0)
161 EOF
162
163 }
164
165 # @img - image to create a filesystem on
166 # @label - fs label
167 # @root_dir - root directory to populate the fs with
168 mk_ext3_fs()
169 {
170         img="$1"
171         label="$2"
172         root_dir="$3"
173
174         # parted 1.8 added --machine for easier parsing; however,
175         # debian still has 1.7 in unstable.
176         partition_start=$(parted -s "$img" "unit B" "print" | sed -ne 's/^ 1[[:space:]]\+//p' | cut -dB -f1)
177
178         # create the filesystem
179         attach_loop "$img" "$partition_start"
180         mke2fs -q -L "$label" -m0 -j "$LOOP_DEV"
181         tune2fs -c0 -i0 "$LOOP_DEV"
182         detach_loop "$LOOP_DEV"
183
184         # populate the filesystem
185         mk_mount "$img" "ext3" "$partition_start"
186         cp -ra "$root_dir"/* "$MOUNT_POINT" || true
187         mk_fstab "$MOUNT_POINT" "ext3"
188         grub_install "$img" "$MOUNT_POINT"
189         rm_mount "$MOUNT_POINT"
190 }
191
192 create_jffs2_img()
193 {
194         mkfs.jffs2 -n -e128KiB -r "$1" -o "${IMG_NAME}.pre"
195         sumtool -n -p -e 128KiB -i "${IMG_NAME}.pre" -o "${IMG_NAME}.jffs2"
196         rm -f "${IMG_NAME}.pre"
197         $CRCIMG < ${IMG_NAME}.jffs2 > ${IMG_NAME}.jffs2.crc
198 }
199
200
201 usage()
202 {
203         echo "" 1>&2
204         echo "Usage: $0 [<options>] <root directory>" 1>&2
205         echo "" 1>&2
206         echo "Options:" 1>&2
207         echo "  -l <label>    Image label" 1>&2
208         echo "  -o <img>      Image (base) filename" 1>&2
209         echo "  -s <size>     Root filesystem size (in MB)" 1>&2
210         echo "" 1>&2
211         exit 1
212 }
213
214 check_for_cmds
215
216 while test $# != 0
217 do
218         case $1 in
219         -l)
220                 IMG_LABEL=$2
221                 shift
222                 ;;
223         -o)
224                 IMG_NAME=$2
225                 shift
226                 ;;
227         -s)
228                 ROOT_SIZE=$2
229                 shift
230                 ;;
231         *)
232                 if [ "$#" != "1" ]; then
233                         echo "Unknown option $1" 1>&2
234                         usage
235                 else
236                         ROOT_DIR="$1"
237                 fi
238                 ;;
239         esac
240         shift
241 done
242
243 if [ "$(id -u)" != "0" ]; then
244         echo "" 1>&2
245         echo "*** Error: must be run as root!" 1>&2
246         echo "" 1>&2
247         exit 2
248 fi
249
250 if [ "$ROOT_DIR" = "" ]; then
251         echo "" 1>&2
252         echo "*** No root directory specified!" 1>&2
253         usage
254 fi
255 if [ ! -d "$ROOT_DIR" ]; then
256         echo "" 1>&2
257         echo "*** Unable to find root directory!" 1>&2
258         usage
259 fi
260
261 mk_bootable_img "${IMG_NAME}.ext3.img" "$ROOT_SIZE"
262 mk_ext3_fs "${IMG_NAME}.ext3.img" "$IMG_LABEL" "$ROOT_DIR"
263
264 #mount ${IMG_NAME}.ext3 $MOUNT_POINT -o loop,offset=$OS_PART1_BEGIN -t ext3
265 #cp -r "$ROOT_DIR"/* $MOUNT_POINT
266 #create_jffs2_img $MOUNT_POINT
267 #umount $MOUNT_POINT