#!/bin/sh
#
ME="Bootsector Linux loader 1.3 (C) 2023 By Alphons van der Heijden"
#
# Making bootable disk file and an additional .vmdk file for booting in vmware
#
# For the .vmdk file see https://kb.vmware.com/s/article/1026266
# (this is handled in this script)
# HEADS=64, SECTORS=32 ; disksize < 1GB
# HEADS=128, SECTORS=32 ; disksize > 1GB && disksize < 2GB
# HEADS=255, SECTORS=63 ; disksize > 2GB
#
# Experimental disk decoding
# for example: ./build.sh disk /tmp
# creates kernel and initrd.gz in /tmp
# 2014- Dr Gareth Owen (www.ghowen.me). All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# INITRD can have multiple gz files, for example INITRD=rootfs.gz,modules.gz
WORK=/mnt/sdb1
KERNEL=$WORK/vmlinuz64
INITRD=$WORK/vmtux64.gz
#rootfs64.gz,$WORK/modules64.gz
CMDLINE="'loglevel=3 nozswap'"
OUTPUT=/tmp/vmtux
#
echo
echo $ME
echo
# some usefull constants
BOOT="bsect.asm"
TMPINITRD=/tmp/initrd.gz
SECTORSIZE=512
if [ "$#" -gt 0 ]; then
if [ "$#" != 2 ]; then
echo "Usage: $0 "
echo
exit 1
fi
INPUT=$1
DIR=$2
if [ ! -d $DIR ]; then
echo "Directory does not exist"
exit 1
fi
if [ ! -f $INPUT ]; then
echo "Input file $INPUT not found"
echo
exit 1
fi
TOTAL=$(stat -c %s $INPUT)
TOTALSECTORS=$(($TOTAL / $SECTORSIZE))
echo "Decoding $INPUT to directory $DIR processing..."
HEXADDRESS=$(hexdump $INPUT | grep '8b1f 0008 0000' | sed 's/ .*//' | tr '[a-z]' '[A-Z]')
if [[ $HEXADDRESS == "" ]]; then
echo "No initrd.gz found"
exit 1
fi
echo
ADDRESS=$(echo "obase=10; ibase=16; $HEXADDRESS" | bc)
SECTOR=$(($ADDRESS / SECTORSIZE))
echo "writing: $DIR/kernel"
dd if=$INPUT count=$(($SECTOR - 1)) skip=1 2>/dev/null > $DIR/kernel
echo "writing: $DIR/initrd.gz"
dd if=$INPUT count=$(($TOTALSECTORS - $SECTOR)) skip=$SECTOR 2>/dev/null | gunzip | gzip > $DIR/initrd.gz
echo
exit 0
fi
if [ ! -f $KERNEL ]; then
echo "Error: $KERNEL not found"
exit 1
fi
# preprocessing INITRD for multiple entries
echo -n > $TMPINITRD
for gz in ${INITRD//,/ }
do
if [ -f $gz ]; then
cat $gz >> $TMPINITRD
else
echo "Error: $gz not found"
echo
exit 1
fi
done
# size of kernel + ramdisk
K_SZ=$(stat -c %s $KERNEL)
R_SZ=$(stat -c %s $TMPINITRD)
# Padding to make it up to a sector
# Always use padding even when exact on sector boundary
K_PAD=$(($SECTORSIZE - $K_SZ % $SECTORSIZE))
R_PAD=$(($SECTORSIZE - $R_SZ % $SECTORSIZE))
nasm -o $OUTPUT -D initRdSizeDef=$R_SZ -D cmdLineDef="$CMDLINE" $BOOT
cat $KERNEL >> $OUTPUT
dd if=/dev/zero bs=1 count=$K_PAD status=none >> $OUTPUT
cat $TMPINITRD >> $OUTPUT
dd if=/dev/zero bs=1 count=$R_PAD status=none >> $OUTPUT
rm -f $TMPINITRD
TOTAL=$(stat -c %s $OUTPUT)
if [ $TOTAL -gt 2000000000 ]; then
SECTORS=63
HEADS=255
else
SECTORS=32
if [ $TOTAL -gt 1000000000 ]; then
HEADS=128
else
HEADS=64
fi
fi
TOTALSECTORS=$(($TOTAL / $SECTORSIZE))
CYLINDERS=$(($TOTALSECTORS / ($HEADS * $SECTORS)))
OUTPUTNAME=$(echo $OUTPUT | sed 's/.*\///' )
cat > $OUTPUT.vmdk <