From 66c32905a8e5a3e70909fe6dbcfedb4498e10f03 Mon Sep 17 00:00:00 2001 From: Thorsten Glaser Date: Sat, 20 Nov 2010 19:19:21 +0000 Subject: new GRUB2 installation script, derived from MirBSD bootblocks Signed-off-by: Thorsten Glaser --- scripts/install.sh | 408 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 302 insertions(+), 106 deletions(-) (limited to 'scripts') diff --git a/scripts/install.sh b/scripts/install.sh index e1a80d787..2665c30c5 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -1,132 +1,328 @@ #!/usr/bin/env bash -# This file is part of the OpenADK project. OpenADK is copyrighted -# material, please see the LICENCE file in the top-level directory. +#- +# Copyright © 2010 +# Waldemar Brodkorb +# Thorsten Glaser +# +# Provided that these terms and disclaimer and all copyright notices +# are retained or reproduced in an accompanying document, permission +# is granted to deal in this work without restriction, including un‐ +# limited rights to use, publicly perform, distribute, sell, modify, +# merge, give away, or sublicence. +# +# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to +# the utmost extent permitted by applicable law, neither express nor +# implied; without malicious intent or gross negligence. In no event +# may a licensor, author or contributor be held liable for indirect, +# direct, other damage, loss, or other issues arising in any way out +# of dealing in the work, even if advised of the possibility of such +# damage or existence of a defect, except proven that it results out +# of said person’s immediate fault when using the work as intended. +# +# Alternatively, this work may be distributed under the terms of the +# General Public License, any version, as published by the Free Soft- +# ware Foundation. +#- +# Prepare a USB stick or CF/SD/MMC card or hard disc for installation +# of OpenADK: +# • install a Master Boot Record containing a MirBSD PBR loading GRUB +# • write GRUB2 core.img just past the MBR +# • create a root partition with ext2fs and extract the OpenADK image +# just built there +# • create a cfgfs partition TOPDIR=$(pwd) +me=$0 -if [ $(id -u) -ne 0 ];then - printf "Installation is only possible as root\n" - exit 1 +case :$PATH: in +(*:$TOPDIR/bin/tools:*) ;; +(*) export PATH=$PATH:$TOPDIR/bin/tools ;; +esac + +test -n "$KSH_VERSION" || if ! which mksh >/dev/null 2>&1; then + make package=mksh fetch || exit 1 + df=$(cd package/mksh; TOPDIR="$TOPDIR" gmake show=DISTFILES) + mkdir -p build_mksh + gzip -dc dl/"$df" | (cd build_mksh; cpio -mid) + cd build_mksh/mksh + bash Build.sh -r || exit 1 + cp mksh "$TOPDIR"/bin/tools/ + cd "$TOPDIR" + rm -rf build_mksh fi -printf "Checking if mke2fs is installed" -mke2fs=$(which mke2fs) +test -n "$KSH_VERSION" || exec mksh "$me" "$@" +if test -z "$KSH_VERSION"; then + echo >&2 Fatal error: could not run myself with mksh! + exit 255 +fi -if [ ! -z $mke2fs -a -x $mke2fs ];then - printf "...okay\n" -else - printf "...failed\n" +### run with mksh from here onwards ### + +me=${me##*/} + +if (( USER_ID )); then + print -u2 Installation is only possible as root! exit 1 fi +TOPDIR=$(realpath .) +ostype=$(uname -s) + cfgfs=1 quiet=0 -console=0 serial=0 -while getopts "nq" option -do - case $option in - q) - quiet=1 - ;; - n) - cfgfs=0 - ;; - *) - printf "Option not recognized\n" +speed=115200 + +function usage { +cat >&2 < 5 )); then + print -u2 "$me: -c $OPTARG out of bounds" + exit 1 + fi ;; + (h) usage 0 ;; + (q) quiet=1 ;; + (+q) quiet=0 ;; + (s) if [[ $OPTARG != @(96|192|384|576|1152)00 ]]; then + print -u2 "$me: serial speed $OPTARG invalid" exit 1 - ;; - esac + fi + speed=$OPTARG ;; + (t) serial=1 ;; + (+t) serial=0 ;; + (*) usage 1 ;; + } done -shift $(($OPTIND - 1)) +shift $((OPTIND - 1)) +(( $# == 2 )) || usage 1 -if [ -z $1 ];then - printf "Please give your compact flash or USB device as first parameter\n" +f=0 +tools='mke2fs tune2fs' +case $ostype { +(DragonFly|*BSD*) + ;; +(Darwin) + tools="$tools fuse-ext2" + ;; +(Linux) + ;; +(*) + print -u2 Sorry, not ported to the OS "'$ostype'" yet. exit 1 -else - if [ -z $2 ];then - printf "Please give your install tar archive as second parameter\n" - exit 2 - fi - if [ -f $2 ];then - printf "Installing $2 on $1\n" - else - printf "$2 is not a file, Exiting\n" - exit 1 - fi - if [ -b $1 ];then - printf "Using $1 as CF/USB disk for installation\n" - if [ $quiet -eq 0 ];then - printf "This will destroy all data on $1, are you sure?\n" - printf "Type "y" to continue\n" - read y - fi + ;; +} +for tool in $tools; do + print -n Checking if $tool is installed... + if whence -p $tool >/dev/null; then + print " okay" else - printf "Sorry $1 is not a block device\n" - exit 1 + print " failed" + f=1 fi +done +(( f )) && exit 1 + +tgt=$1 +src=$2 + +if [[ ! -b $tgt ]]; then + print -u2 "'$tgt' is not a block device, exiting" + exit 1 fi - -if [ $(mount | grep $1| wc -l) -ne 0 ];then - printf "Block device $1 is in use, please umount first.\n" +if [[ ! -f $src ]]; then + print -u2 "'$src' is not a file, exiting" exit 1 fi +(( quiet )) || print "Installing $src on $tgt." -case $2 in - wrap*) - speed=38400 - ;; - *) - speed=115200 - ;; -esac - -rootpart=${1}1 -pt=$TOPDIR/bin/tools/pt -# get sector size from block device -maxsector=$(sudo $pt -g $1) -head=16 -sect=63 -rsize=$(($maxsector / 2)) - -printf "Creating partition table ...\n" -table=$(mktemp) -# generate partition table -$pt -o $table -s $sect -h $head -p ${rsize}K -# write partition table to block device -dd if=$table of=$1 bs=512 count=1 2> /dev/null -printf "Creating ext2 filesystem ...\n" -$mke2fs -q ${1}1 - -printf "Extracting install archive ...\n" -tmp=$(mktemp -d) -mount -t ext2 ${rootpart} $tmp -tar -C $tmp -xzpf $2 -printf "Fixing permissions ...\n" -chmod 1777 $tmp/tmp -chmod 4755 $tmp/bin/busybox - -printf "Installing GRUB bootloader ...\n" -mkdir -p $tmp/boot/grub -cat << EOF > $tmp/boot/grub/grub.cfg -set default=0 -set timeout=1 -terminal_output console -terminal_input console - -menuentry "GNU/Linux (OpenADK)" { - insmod ext2 - set root=(hd0,1) - linux /boot/vmlinuz-adk init=/init +case $ostype { +(DragonFly|*BSD*) + basedev=${tgt%c} + tgt=${basedev}c + part=${basedev}i + match=\'${basedev}\''[a-p]' + function mount_ext2fs { + mount -t ext2fs "$1" "$2" + } + ;; +(Darwin) + basedev=$tgt + part=${basedev}s1 + match=\'${basedev}\''?(s+([0-9]))' + function mount_ext2fs { + fuse-ext2 "$1" "$2" -o force + sleep 3 + } + ;; +(Linux) + basedev=$tgt + part=${basedev}1 + match=\'${basedev}\''+([0-9])' + function mount_ext2fs { + mount -t ext2 "$1" "$2" + } + ;; } -EOF -./bin/tools/sbin/grub-install \ - --grub-setup=./bin/tools/sbin/grub-setup \ - --grub-mkimage=./bin/tools/bin/grub-mkimage \ - --grub-mkdevicemap=./bin/tools/sbin/grub-mkdevicemap \ - --no-floppy --modules=ext2 --root-directory=$tmp $1 -umount $tmp -printf "Successfully installed.\n" -rm -rf $tmp + +mount | while read dev rest; do + [[ $dev = $match ]] || continue + print -u2 "Block device $tgt is in use, please umount first." + exit 1 +done + +if (( !quiet )); then + print "WARNING: This will overwrite $basedev - type Yes to continue!" + read x + [[ $x = Yes ]] || exit 0 +fi + +dksz=$(dkgetsz "$tgt") +heads=64 +secs=32 +(( cyls = dksz / heads / secs )) +if (( cyls < (cfgfs + 2) )); then + print -u2 "Size of $tgt is $dksz, this looks fishy?" + exit 1 +fi + +if stat --help >/dev/null 2>&1; then + statcmd='stat -c %s' # GNU stat +else + statcmd='stat -f %z' # BSD stat (or so we assume) +fi + +if ! T=$(mktemp -d /tmp/openadk.XXXXXXXXXX); then + print -u2 Error creating temporary directory. + exit 1 +fi +"$TOPDIR/scripts/tar" -xOzf "$src" ./usr/share/grub-bin/core.img >"$T/core.img" +integer coreimgsz=$($statcmd "$T/core.img") +if (( coreimgsz < 1024 )); then + print -u2 core.img is probably too small: $coreimgsz + rm -rf "$T" + exit 1 +fi +if (( coreimgsz > 65024 )); then + print -u2 core.img is larger than 64K-512: $coreimgsz + rm -rf "$T" + exit 1 +fi +(( coreendsec = (coreimgsz + 511) / 512 )) +# partition offset: at least coreendsec+1 but aligned on a multiple of secs +(( partofs = ((coreendsec / secs) + 1) * secs )) + +(( quiet )) || print Preparing MBR and GRUB2... +dd if=/dev/zero of="$T/firsttrack" count=$partofs 2>/dev/null +echo 1 $coreendsec | mksh "$TOPDIR/scripts/bootgrub.mksh" \ + -A -g $((cyls-cfgfs)):$heads:$secs -M 1:0x83 -O $partofs | \ + dd of="$T/firsttrack" conv=notrunc 2>/dev/null +dd if="$T/core.img" of="$T/firsttrack" conv=notrunc seek=1 2>/dev/null +# set partition where it can find /boot/grub +print -n '\0\0\0\0' | \ + dd of="$T/firsttrack" conv=notrunc bs=1 seek=$((0x414)) 2>/dev/null + +# create cfgfs partition (mostly taken from bootgrub.mksh) +set -A thecode +typeset -Uui8 thecode +mbrpno=0 +set -A g_code $cyls $heads $secs +(( psz = g_code[0] * g_code[1] * g_code[2] )) +(( pofs = (cyls - cfgfs) * g_code[1] * g_code[2] )) +set -A o_code # g_code equivalent for partition offset +(( o_code[2] = pofs % g_code[2] + 1 )) +(( o_code[1] = pofs / g_code[2] )) +(( o_code[0] = o_code[1] / g_code[1] + 1 )) +(( o_code[1] = o_code[1] % g_code[1] + 1 )) +# boot flag; C/H/S offset +thecode[mbrpno++]=0x00 +(( thecode[mbrpno++] = o_code[1] - 1 )) +(( cylno = o_code[0] > 1024 ? 1023 : o_code[0] - 1 )) +(( thecode[mbrpno++] = o_code[2] | ((cylno & 0x0300) >> 2) )) +(( thecode[mbrpno++] = cylno & 0x00FF )) +# partition type; C/H/S end +(( thecode[mbrpno++] = 0x88 )) +(( thecode[mbrpno++] = g_code[1] - 1 )) +(( cylno = g_code[0] > 1024 ? 1023 : g_code[0] - 1 )) +(( thecode[mbrpno++] = g_code[2] | ((cylno & 0x0300) >> 2) )) +(( thecode[mbrpno++] = cylno & 0x00FF )) +# partition offset, size (LBA) +(( thecode[mbrpno++] = pofs & 0xFF )) +(( thecode[mbrpno++] = (pofs >> 8) & 0xFF )) +(( thecode[mbrpno++] = (pofs >> 16) & 0xFF )) +(( thecode[mbrpno++] = (pofs >> 24) & 0xFF )) +(( pssz = psz - pofs )) +(( thecode[mbrpno++] = pssz & 0xFF )) +(( thecode[mbrpno++] = (pssz >> 8) & 0xFF )) +(( thecode[mbrpno++] = (pssz >> 16) & 0xFF )) +(( thecode[mbrpno++] = (pssz >> 24) & 0xFF )) +# write partition table entry +ostr= +curptr=0 +while (( curptr < 16 )); do + ostr=$ostr\\0${thecode[curptr++]#8#} +done +print -n "$ostr" | \ + dd of="$T/firsttrack" conv=notrunc bs=1 seek=$((0x1CE)) 2>/dev/null + +(( quiet )) || print Writing MBR and GRUB2 to target device... +dd if="$T/firsttrack" of="$tgt" + +(( quiet )) || print "Creating ext2fs on ${part}..." +q= +(( quiet )) && q=-q +mke2fs $q "$part" +#partuuid=$(tune2fs -l /dev/sd0i | sed -n '/^Filesystem UUID:[ ]*/s///p') + +(( quiet )) || print Extracting installation archive... +mount_ext2fs "$part" "$T" +gzip -dc "$src" | (cd "$T"; tar -xpf -) +cd "$T" +rnddev=/dev/urandom +[[ -c /dev/arandom ]] && rnddev=/dev/arandom +dd if=$rnddev bs=16 count=1 >>etc/.rnd 2>/dev/null +(( quiet )) || print Fixing up permissions... +chown 0:0 tmp +chmod 1777 tmp +chmod 4755 bin/busybox +(( quiet )) || print Configuring GRUB2 bootloader... +mkdir -p boot/grub +( + print set default=0 + print set timeout=1 + if (( serial )); then + print serial --unit=0 --speed=$speed + print terminal_output serial + print terminal_input serial + consargs="console=ttyS0,$speed console=tty0" + else + print terminal_output console + print terminal_input console + consargs="console=tty0" + fi + print + print 'menuentry "GNU/Linux (OpenADK)" {' +# print "\tlinux /boot/vmlinuz-adk root=UUID=$partuuid $consargs panic=10" + print "\tlinux /boot/vmlinuz-adk $consargs panic=10" + print '}' +) >boot/grub/grub.cfg +set -A grubfiles +ngrubfiles=0 +for a in usr/lib/grub/*-pc/{*.mod,efiemu??.o,command.lst,moddep.lst,fs.lst,handler.lst,parttool.lst}; do + [[ -e $a ]] && grubfiles[ngrubfiles++]=$a +done +cp "${grubfiles[@]}" boot/grub/ +(( quiet )) || print Finishing up... +cd "$TOPDIR" +umount "$T" + +rm -rf "$T" exit 0 -- cgit v1.2.3