1#!/bin/sh
2#
3# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
4#
5# SPDX-License-Identifier: BSD-2-Clause
6#
7
8# Build a qemu-bootable harddisk image.
9#
10# Usage:
11# An optional kernel command line argument is provided with -a.
12# The kernel image is provided with -k.
13# The output harddisk image is specified with -o.
14# Userland images are provided after that (usually only one).
15#
16# Authors:
17# Benjamin Kalman, 2009
18# Michael von Tessin, 2010
19
20# Support build system debugging directive passed from above.
21if [ 0${V} -ge 3 ]; then
22    set -x
23fi
24
25# Find syslinux
26SYSLINUX=`which syslinux`
27if [ -z "${SYSLINUX}" ]; then
28    echo "syslinux not found." >&2
29    exit 1
30fi
31SYSLINUXDIR=`echo $SYSLINUX | sed 's:/bin/:/share/:'`
32[ -d "$SYSLINUXDIR"  ] || SYSLINUXDIR="`echo $SYSLINUXDIR | sed 's:/share/:/lib/:'`"
33
34[ -d "$SYSLINUXDIR" ] || {
35       echo >&2 "Cannot find syslinux data directory!"
36       exit 1
37}
38
39if [ -f "$SYSLINUXDIR"/mbr.bin ]
40then
41    SYSLINUX_MODULES="$SYSLINUXDIR"
42    MBR="$SYSLINUXDIR"/mbr.bin
43elif [ -d "$SYSLINUXDIR"/modules ]
44then
45    SYSLINUX_MODULES="$SYSLINUXDIR"/modules/bios/
46    MBR="$SYSLINUXDIR"/mbr/mbr.bin
47fi
48
49[ -f "$MBR" ] || {
50    echo >&2 "Can't find mbr.bin.  Is syslinux installed?"
51    exit 1
52}
53
54trap "rm -f mtoolsrc syslinux.cfg mbr.bin" 0
55
56# Parse options
57while getopts "k:o:a:" flag ; do
58    case "$flag" in
59        k) KERNEL="$OPTARG" ;;
60        o) OUTIMG="$OPTARG" ;;
61        a) CMDLINE="$OPTARG" ;;
62    esac
63done
64shift $(($OPTIND-1))
65UIMGS=$@
66
67if [ ! -f "$KERNEL" -o -z "$OUTIMG" -o -z "$UIMGS" ] ; then
68    echo "Usage: $0 [-a kernel_cmdline] -k kernel_image -o output_image userland_images ..."
69    exit 1
70fi
71
72for UIMG in $UIMGS ; do
73    if [ ! -f "$UIMG" ] ; then
74        echo "Error: Userland image '$UIMG' not found!"
75        exit 1
76    fi
77done
78
79MODULES="$SYSLINUX_MODULES/mboot.c32"
80[ -f $SYSLINUX_MODULES/libcom32.c32 ] && MODULES="$MODULES $SYSLINUX_MODULES/libcom32.c32"
81# Calculate image size and number of cylinders
82
83IMGSIZE=`stat -c '%s' $UIMGS $KERNEL $MODULES | awk ' { sum += $1 } END { print sum }'`
84
85echo "final image size will be $IMGSIZE"
86
87HEADS=16
88SECTORS=63
89BLKSPERCYL=`expr $HEADS \* $SECTORS`
90CYLINDERS=`expr 2 + $IMGSIZE / 512 / $BLKSPERCYL`
91
92# Create a blank image
93dd if=/dev/zero of="$OUTIMG" count=1 seek=`expr $CYLINDERS \* $BLKSPERCYL - 1` bs=512 2>/dev/null
94
95# Set up mtools
96echo "drive c: file=\"$OUTIMG\" partition=1" > mtoolsrc
97export MTOOLSRC=mtoolsrc
98
99# Get mbr.bin and blow up/cut down to 512 bytes (required by mtools)
100cat "$MBR" /dev/zero 2>/dev/null | head -c 512 > mbr.bin
101
102# Create filesystem
103which mpartition >/dev/null 2>&1
104if [ $? -ne 0 ]; then
105    echo "mpartition not found. Is mtools installed?" >&2
106    exit 1
107fi
108mpartition -I -B mbr.bin c:
109mpartition -c -t $CYLINDERS -h $HEADS -s $SECTORS c:
110mpartition -a c:
111mformat c:
112syslinux --offset `expr $SECTORS \* 512` $OUTIMG
113
114# Write syslinux config file
115UIMGS_CFG=""
116for UIMG in $UIMGS
117do
118    UIMGS_CFG="$UIMGS_CFG --- `basename $UIMG`"
119done
120
121cat > syslinux.cfg <<EOF
122serial 0 115200
123default mylabel
124
125label mylabel
126  kernel mboot.c32
127  append `basename $KERNEL` $CMDLINE $UIMGS_CFG
128EOF
129
130# Install kernel and apps to the image
131for file in $KERNEL $UIMGS $MODULES syslinux.cfg
132do
133    mcopy "$file" c: || {
134        echo "Error: mcopy $file failed!" >&2
135        exit 1
136    }
137done
138
139# And we're done
140echo "Image '$OUTIMG' successfully created"
141