3 # Copyright © 2010, 2011, 2012
4 # Thorsten Glaser <tg@mirbsd.org>
5 # Copyright © 2010-2024
6 # Waldemar Brodkorb <wbx@openadk.org>
8 # Provided that these terms and disclaimer and all copyright notices
9 # are retained or reproduced in an accompanying document, permission
10 # is granted to deal in this work without restriction, including un‐
11 # limited rights to use, publicly perform, distribute, sell, modify,
12 # merge, give away, or sublicence.
14 # This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
15 # the utmost extent permitted by applicable law, neither express nor
16 # implied; without malicious intent or gross negligence. In no event
17 # may a licensor, author or contributor be held liable for indirect,
18 # direct, other damage, loss, or other issues arising in any way out
19 # of dealing in the work, even if advised of the possibility of such
20 # damage or existence of a defect, except proven that it results out
21 # of said person’s immediate fault when using the work as intended.
23 # Alternatively, this work may be distributed under the Terms of the
24 # General Public License, any version as published by the Free Soft‐
27 # Create a hard disc image, bootable using GNU GRUB2, with an ext2fs
28 # root partition and an OpenADK cfgfs partition.
31 HOST
=$
(gcc
-dumpmachine)
35 (*:$ADK_TOPDIR/host_
$HOST/usr
/bin
:*) ;;
36 (*) export PATH
=$PATH:$ADK_TOPDIR/host_
$HOST/usr
/bin
;;
39 test -n "$KSH_VERSION" ||
exec mksh
"$me" "$@"
40 if test -z "$KSH_VERSION"; then
41 echo >&2 Fatal error
: could not run myself with mksh
!
45 ### run with mksh from here onwards ###
49 ADK_TOPDIR
=$
(realpath .
)
54 Syntax: $me [-c cfgfssize] [+g] [-i imagesize] [-p panictime]
55 [-s serialspeed] [-t] [-T imagetype] [+U] target.ima source.tgz
57 -c: minimum 0, maximum 5, default 1 (MiB)
58 -g: enable installing GNU GRUB 2
59 -i: total image, default 512 (MiB; max. approx. 2 TiB)
60 -p: default 10 (seconds; 0 disables; max. 300)
61 -s: default 115200 (bps, others: 9600 19200 38400 57600)
62 -t: enable serial console (+t disables it, default)
63 -T: image type (default raw, others: vdi)
76 while getopts "c:ghi:p:s:tT:" ch
; do
78 (c
) if (( (cfgfs
= OPTARG
) < 0 || cfgfs
> 5 )); then
79 print
-u2 "$me: -c $OPTARG out of bounds"
84 (i
) if (( (tgtmib
= OPTARG
) < 7 || tgtmib
> 2097150 )); then
85 print
-u2 "$me: -i $OPTARG out of bounds"
88 (p
) if (( (panicreboot
= OPTARG
) < 0 || panicreboot
> 300 )); then
89 print
-u2 "$me: -p $OPTARG out of bounds"
92 (s
) if [[ $OPTARG != @
(96|
192|
384|
576|
1152)00 ]]; then
93 print
-u2 "$me: serial speed $OPTARG invalid"
99 (T
) if [[ $OPTARG != @
(raw|vdi
) ]]; then
100 print
-u2 "$me: image type $OPTARG invalid"
107 shift $
((OPTIND
- 1))
109 (( $# == 2 )) || usage
1
113 [[ $tgttype = vdi
]] && tools
="$tools VBoxManage"
114 for tool
in $tools; do
115 print
-n Checking
if $tool is installed...
116 if whence
-p $tool >/dev
/null
; then
124 if bc --help >/dev
/null
2>&1; then
125 # GNU bc shows a “welcome message” which irritates scripts
132 [[ $tgt = /* ]] || tgt
=$PWD/$tgt
135 if [[ ! -f $src ]]; then
136 print
-u2 "'$src' is not a file, exiting"
139 if ! T
=$
(mktemp
-d /tmp
/openadk.XXXXXXXXXX
); then
140 print
-u2 Error creating temporary directory.
143 print
"Installing $src on $tgt."
148 if stat
-qs .
>/dev
/null
2>&1; then
149 statcmd
='stat -f %z' # BSD stat (or so we assume)
151 statcmd
='stat -c %s' # GNU stat
154 if (( usegrub
)); then
155 tar -xOJf "$src" boot
/grub
/core.img
>"$T/core.img"
156 integer coreimgsz
=$
($statcmd "$T/core.img")
157 if (( coreimgsz
< 1024 )); then
158 print
-u2 core.img is probably too small
: $coreimgsz
162 if (( coreimgsz
> 65024 )); then
163 print
-u2 core.img is larger than
64K-512
: $coreimgsz
171 (( coreendsec
= (coreimgsz
+ 511) / 512 ))
173 corepatchofs
=$
((0x414))
174 # partition offset: at least coreendsec+1 but aligned on a multiple of secs
175 (( partofs
= ((coreendsec
/ secs
) + 1) * secs
))
176 # calculate size of ext2fs in KiB as image size minus cfgfs minus firsttrack
177 ((# partfssz = ((cyls - cfgfs) * 64 * 32 - partofs) / 2 ))
179 if (( usegrub
)); then
180 print Preparing MBR and GRUB2...
182 print Preparing partition table...
184 dd if=/dev
/zero of
="$T/firsttrack" count
=$partofs 2>/dev
/null
185 echo $corestartsec $coreendsec | mksh
"$ADK_TOPDIR/scripts/bootgrub.mksh" \
186 -A -g $
((cyls
- cfgfs
)):$heads:$secs -M 1:0x83 -O $partofs | \
187 dd of
="$T/firsttrack" conv
=notrunc
2>/dev
/null
188 if (( usegrub
)); then
189 dd if="$T/core.img" of
="$T/firsttrack" conv
=notrunc \
190 seek
=$corestartsec 2>/dev
/null
191 # set partition where it can find /boot/grub
192 print
-n '\0\0\0\0' | \
193 dd of
="$T/firsttrack" conv
=notrunc bs
=1 seek
=$corepatchofs \
197 # create cfgfs partition (mostly taken from bootgrub.mksh)
199 typeset
-Uui8 thecode
201 set -A g_code
$cyls $heads $secs
202 (( pssz
= cfgfs
* g_code
[1] * g_code
[2] ))
203 (( pofs
= (cyls
- cfgfs
) * g_code
[1] * g_code
[2] ))
204 set -A o_code
# g_code equivalent for partition offset
205 (( o_code
[2] = pofs
% g_code
[2] + 1 ))
206 (( o_code
[1] = pofs
/ g_code
[2] ))
207 (( o_code
[0] = o_code
[1] / g_code
[1] + 1 ))
208 (( o_code
[1] = o_code
[1] % g_code
[1] + 1 ))
209 # boot flag; C/H/S offset
210 thecode
[mbrpno
++]=0x00
211 (( thecode
[mbrpno
++] = o_code
[1] - 1 ))
212 (( cylno
= o_code
[0] > 1024 ?
1023 : o_code
[0] - 1 ))
213 (( thecode
[mbrpno
++] = o_code
[2] |
((cylno
& 0x0300) >> 2) ))
214 (( thecode
[mbrpno
++] = cylno
& 0x00FF ))
215 # partition type; C/H/S end
216 (( thecode
[mbrpno
++] = 0x88 ))
217 (( thecode
[mbrpno
++] = g_code
[1] - 1 ))
218 (( cylno
= g_code
[0] > 1024 ?
1023 : g_code
[0] - 1 ))
219 (( thecode
[mbrpno
++] = g_code
[2] |
((cylno
& 0x0300) >> 2) ))
220 (( thecode
[mbrpno
++] = cylno
& 0x00FF ))
221 # partition offset, size (LBA)
222 (( thecode
[mbrpno
++] = pofs
& 0xFF ))
223 (( thecode
[mbrpno
++] = (pofs
>> 8) & 0xFF ))
224 (( thecode
[mbrpno
++] = (pofs
>> 16) & 0xFF ))
225 (( thecode
[mbrpno
++] = (pofs
>> 24) & 0xFF ))
226 (( thecode
[mbrpno
++] = pssz
& 0xFF ))
227 (( thecode
[mbrpno
++] = (pssz
>> 8) & 0xFF ))
228 (( thecode
[mbrpno
++] = (pssz
>> 16) & 0xFF ))
229 (( thecode
[mbrpno
++] = (pssz
>> 24) & 0xFF ))
230 # write partition table entry
233 while (( curptr
< 16 )); do
234 ostr
=$ostr\\0${thecode[curptr++]#8#}
237 dd of
="$T/firsttrack" conv
=notrunc bs
=1 seek
=$
((0x1CE)) 2>/dev
/null
239 print Extracting installation archive...
241 gunzip
-dc "$src" |
(cd "$T/src"; tar -xpf -)
244 [[ -c /dev
/arandom
]] && rnddev
=/dev
/arandom
245 dd if=$rnddev bs
=16 count
=1 >>etc
/.rnd
2>/dev
/null
246 print Fixing up permissions...
248 [[ -f usr
/bin
/sudo
]] && chmod 4755 usr
/bin
/sudo
250 if (( usegrub
)); then
251 print Configuring GRUB2 bootloader...
256 if (( serial
)); then
257 print serial
--unit=0 --speed=$speed
258 print terminal_output serial
259 print terminal_input serial
260 consargs
="console=ttyS0,$speed console=tty0"
262 print terminal_output console
263 print terminal_input console
264 consargs
="console=tty0"
267 print
'menuentry "GNU/Linux (OpenADK)" {'
268 linuxargs
="root=/dev/sda1 $consargs"
269 (( panicreboot
)) && linuxargs
="$linuxargs panic=$panicreboot"
270 print
"\tlinux /boot/kernel $linuxargs"
272 ) >boot
/grub
/grub.cfg
275 print
"Creating ext2fs filesystem image..."
278 genext2fs
-U -N 65536 -b $
((partfssz
)) -d src fsimg || f
=1
280 # use bc(1): this may be over the shell’s 32-bit arithmetics
281 wantsz
=$
($bc <<<"$((partfssz))*1024")
282 gotsz
=$
($statcmd fsimg
)
283 if [[ $wantsz != "$gotsz" ]]; then
284 print
-u2 "Error: want $wantsz bytes, got $gotsz bytes!"
289 print
-u2 "Error creating ext2fs filesystem image"
294 # delete source tree, to save disc space
297 if [[ $tgttype = raw
]]; then
302 print
"Putting together raw output image $tgttmp..."
303 dd if=/dev
/zero bs
=1048576 count
=$cfgfs 2>/dev
/null | \
304 cat firsttrack fsimg
- >"$tgttmp"
305 # use bc(1): this may be over the shell’s 32-bit arithmetics
306 wantsz
=$
($bc <<<"$tgtmib*1048576")
307 gotsz
=$
($statcmd "$tgttmp")
308 if [[ $wantsz != "$gotsz" ]]; then
309 print
-u2 "Error: want $wantsz bytes, got $gotsz bytes!"
319 print
"Converting raw image to VDI..."
320 VBoxManage convertdd dst.ima dst.vdi
322 print
"Moving VDI image to $tgt.vdi..."
323 mv -f dst.vdi
"$tgt".vdi
327 print Finishing up...