| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 | #!/usr/bin/env bash#-# Copyright © 2010, 2011#	Waldemar Brodkorb <wbx@openadk.org>#	Thorsten Glaser <tg@mirbsd.org>## 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 partitionTOPDIR=$(pwd)me=$0case :$PATH: in(*:$TOPDIR/bin/tools:*) ;;(*) export PATH=$PATH:$TOPDIR/bin/tools ;;esactest -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 -c lto || exit 1	cp mksh "$TOPDIR"/bin/tools/	cd "$TOPDIR"	rm -rf build_mkshfitest -n "$KSH_VERSION" || exec mksh "$me" "$@"if test -z "$KSH_VERSION"; then	echo >&2 Fatal error: could not run myself with mksh!	exit 255fi### run with mksh from here onwards ###me=${me##*/}if (( USER_ID )); then	print -u2 Installation is only possible as root!	exit 1fiTOPDIR=$(realpath .)ostype=$(uname -s)cfgfs=1noformat=0quiet=0serial=0speed=115200panicreboot=10function usage {cat >&2 <<EOFSyntax: $me [-c cfgfssize] [-p panictime] [±q] [-s serialspeed]    [±t] -n /dev/sdb imageDefaults: -c 1 -p 10 -s 115200; -t = enable serial consoleEOF	exit $1}while getopts "c:hp:qs:nt" ch; do	case $ch {	(c)	if (( (cfgfs = OPTARG) < 0 || cfgfs > 5 )); then			print -u2 "$me: -c $OPTARG out of bounds"			exit 1		fi ;;	(h)	usage 0 ;;	(p)	if (( (panicreboot = OPTARG) < 0 || panicreboot > 300 )); then			print -u2 "$me: -p $OPTARG out of bounds"			exit 1		fi ;;	(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		fi		speed=$OPTARG ;;	(n)	noformat=1 ;;	(t)	serial=1 ;;	(+t)	serial=0 ;;	(*)	usage 1 ;;	}doneshift $((OPTIND - 1))(( $# == 2 )) || usage 1f=0tools='mke2fs tune2fs'case $ostype {(DragonFly|*BSD*)	;;(Darwin)	tools="$tools fuse-ext2"	;;(Linux)	;;(*)	print -u2 Sorry, not ported to the OS "'$ostype'" yet.	exit 1	;;}for tool in $tools; do	print -n Checking if $tool is installed...	if whence -p $tool >/dev/null; then		print " okay"	else		print " failed"		f=1	fidone(( f )) && exit 1tgt=$1src=$2if [[ ! -b $tgt ]]; then	print -u2 "'$tgt' is not a block device, exiting"	exit 1fiif [[ ! -f $src ]]; then	print -u2 "'$src' is not a file, exiting"	exit 1fi(( quiet )) || print "Installing $src on $tgt."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 rw+		sleep 3	}	;;(Linux)	basedev=$tgt	part=${basedev}1	match=\'${basedev}\''+([0-9])'	function mount_ext2fs {		mount -t ext2 "$1" "$2"	}	;;}mount |&while read -p dev rest; do	eval [[ \$dev = $match ]] || continue	print -u2 "Block device $tgt is in use, please umount first."	exit 1doneif (( !quiet )); then	print "WARNING: This will overwrite $basedev - type Yes to continue!"	read x	[[ $x = Yes ]] || exit 0fidksz=$(dkgetsz "$tgt")heads=64secs=32(( cyls = dksz / heads / secs ))if (( cyls < (cfgfs + 2) )); then	print -u2 "Size of $tgt is $dksz, this looks fishy?"	exit 1fiif stat -qs .>/dev/null 2>&1; then	statcmd='stat -f %z'	# BSD stat (or so we assume)else	statcmd='stat -c %s'	# GNU statfiif ! T=$(mktemp -d /tmp/openadk.XXXXXXXXXX); then	print -u2 Error creating temporary directory.	exit 1fitar -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 1fiif (( coreimgsz > 65024 )); then	print -u2 core.img is larger than 64K-512: $coreimgsz	rm -rf "$T"	exit 1fi(( coreendsec = (coreimgsz + 511) / 512 ))if [[ $basedev = /dev/svnd+([0-9]) ]]; then	# BSD svnd0 mode: protect sector #1	corestartsec=2	(( ++coreendsec ))	corepatchofs=$((0x614))else	corestartsec=1	corepatchofs=$((0x414))fi# 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/nullecho $corestartsec $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/nulldd if="$T/core.img" of="$T/firsttrack" conv=notrunc seek=$corestartsec \    2>/dev/null# set partition where it can find /boot/grubprint -n '\0\0\0\0' | \    dd of="$T/firsttrack" conv=notrunc bs=1 seek=$corepatchofs 2>/dev/null# create cfgfs partition (mostly taken from bootgrub.mksh)set -A thecodetypeset -Uui8 thecodembrpno=0set -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 offsetthecode[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 entryostr=curptr=0while (( curptr < 16 )); do	ostr=$ostr\\0${thecode[curptr++]#8#}doneprint -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"if [[ $basedev = /dev/svnd+([0-9]) ]]; then	(( quiet )) || print "Creating BSD disklabel on target device..."	# c: whole device (must be so)	# i: ext2fs (matching first partition)	# j: cfgfs (matching second partition)	# p: MBR and GRUB2 area (by tradition)	cat >"$T/bsdlabel" <<-EOF		type: vnd		disk: vnd device		label: OpenADK		flags:		bytes/sector: 512		sectors/track: $secs		tracks/cylinder: $heads		sectors/cylinder: $((heads * secs))		cylinders: $cyls		total sectors: $((cyls * heads * secs))		rpm: 3600		interleave: 1		trackskew: 0		cylinderskew: 0		headswitch: 0		track-to-track seek: 0		drivedata: 0		16 partitions:		c: $((cyls * heads * secs)) 0 unused		i: $(((cyls - cfgfs) * heads * secs - partofs)) $partofs ext2fs		j: $((cfgfs * heads * secs)) $(((cyls - cfgfs) * heads * secs)) unknown		p: $partofs 0 unknownEOF	disklabel -R ${basedev#/dev/} "$T/bsdlabel"fi(( quiet )) || print "Creating ext2fs on ${part}..."q=(( quiet )) && q=-q(( noformat )) || mke2fs $q "$part"partuuid=$(tune2fs -l "$part" | sed -n '/^Filesystem UUID:[	 ]*/s///p')(( noformat )) || tune2fs -c 0 -i 0 "$part"(( quiet )) || print Extracting installation archive...mount_ext2fs "$part" "$T"gzip -dc "$src" | (cd "$T"; tar -xvpf -)cd "$T"rnddev=/dev/urandom[[ -c /dev/arandom ]] && rnddev=/dev/arandomdd if=$rnddev bs=16 count=1 >>etc/.rnd 2>/dev/null(( quiet )) || print Fixing up permissions...chown 0:0 tmpchmod 1777 tmpchmod 4755 bin/busybox[[ -f usr/bin/Xorg ]] && chmod 4755 usr/bin/Xorg[[ -f usr/bin/sudo ]] && chmod 4755 usr/bin/sudo(( 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)" {'	linuxargs="root=UUID=$partuuid $consargs"	(( panicreboot )) && linuxargs="$linuxargs panic=$panicreboot"	print "\tlinux /boot/kernel $linuxargs"	print '}') >boot/grub/grub.cfgset -A grubfilesngrubfiles=0for a in usr/lib/grub/*-pc/{*.mod,efiemu??.o,command.lst,moddep.lst,fs.lst,handler.lst,parttool.lst}; do	[[ -e $a ]] && grubfiles[ngrubfiles++]=$adonecp "${grubfiles[@]}" boot/grub/(( quiet )) || print Finishing up...cd "$TOPDIR"umount "$T"(( quiet )) || print "\nNote: the rootfs UUID is: $partuuid"rm -rf "$T"exit 0
 |