• Diese Seite verwendet Cookies. Indem du diese Website weiterhin nutzt, erklärst du dich mit der Verwendung von Cookies einverstanden. Erfahre mehr

Bootloader updaten

Kamikaze

Warrior of Sunlight
Themenstarter #1
Letztens ist mir aufgefallen, dass der Bootloader irgendeine Fehlermeldung raushaut direkt bevor das Terminal zurückgesetzt wird und der Kernel übernimmt. So fiel mir dann ein, dass ich nie den Bootloader kram mit update. Also habe ich mir jetzt ein kleines Skript geschrieben. Der Output sieht so aus:

Code:
root# updategptboot nvd0
updategptboot> gpart bootcode -b /boot/pmbr nvd0
bootcode written to nvd0
updategptboot> gpart bootcode -p /boot/gptzfsboot -i 1 nvd0
partcode written to nvd0p1
updategptboot> install /boot/loader.efi nvd0p2:/efi/boot/FreeBSD-amd64.efi
updategptboot> efibootmgr -cl "nvd0p2:/efi/boot/FreeBSD-amd64.efi" -L "nvd0/amd64/FreeBSD AprilRyan.norad 12.1-STABLE FreeBSD 12.1-STABLE 4b39aea0c0b(kami/12) S403  amd64"
updategptboot> efibootmgr -a 0000
BootCurrent: 0000
Timeout    : 0 seconds
BootOrder  : 0000, 0003, 2001, 2002, 2003
+Boot0000* nvd0/amd64/FreeBSD AprilRyan.norad 12.1-STABLE FreeBSD 12.1-STABLE 4b39aea0c0b(kami/12) S403  amd64
 Boot0003* nvd1/amd64/FreeBSD AprilRyan.norad 12.1-STABLE FreeBSD 12.1-STABLE 4b39aea0c0b(kami/12) S403  amd64
 Boot2001* EFI USB Device
 Boot2002* EFI DVD/CDROM
 Boot2003* EFI Network
root#
Ich habe bei mir das Bootzeug für EFI und Legacy (BIOS) auf der Platte. Das Skript updated beides, sofern die entsprechenden Partitionen vorhanden sind. Wenn keine freebsd-ufs aber eine freebsd-zfs Partition vorhanden ist wird /boot/gptzfsboot in die freebsd-boot Parition installiert, sonst /boot/gptboot. Ich würde die Entscheidung gerne nach dem Active bit der Partitionen setzen. Aber ich habe schlicht in der gpart Manpage nicht gefunden wie ich das auslese.

In eine EFI Partition wird der Loader installiert.

Vielleicht hat ja noch jemand einen Nutzen davon oder Vorschläge?

Code:
#!/bin/sh
set -fe
readonly arch="$(uname -p)" os="$(uname -s)"
readonly tmpdir="$(mktemp -dt updatezfsboot)"
trap "rmdir ${tmpdir} 2>&- || (umount ${tmpdir} && rmdir ${tmpdir})" EXIT

getefivar() {
	local var tag tail
	efibootmgr | while read -r var tag tail; do
		if [ "$tag" = "$1" ]; then
			var="${var#*Boot}"
			echo "${var%\*}"
			return 0
		fi
	done
}

run() {
	echo "${0##*/}> ${*}"
	"$@"
}

for drive in "$@"; do
	unset efi freebsd_boot freebsd_zfs freebsd_ufs
	if ! gpart show "$drive" >&- 2>&-; then
		echo "no such drive: ${drive}" >&2
		exit 1
	fi
	eval "$(gpart show "$drive" | awk '
	$0 && NR > 1 {
		gsub(/[^[:alnum:]+]/, "_", $4)
		print $4 "=" $3
	}')"
	if [ -z "${freebsd_zfs}${freebsd_ufs}" ]; then
		echo "no freebsd-zfs or ufs partition on ${drive}" >&2
		exit 2
	fi

	if [ -z "${efi}${freebsd_boot}" ]; then
		echo "no efi or freebsd-boot partition on ${drive}" >&2
		exit 3
	fi
	run gpart bootcode -b /boot/pmbr "${drive}" || exit 4
	if [ -n "$freebsd_boot" ]; then
		if [ -n "$freebsd_ufs" ]; then
			run gpart bootcode -p /boot/gptboot -i "${freebsd_boot}" "${drive}" || exit 5
		else
			run gpart bootcode -p /boot/gptzfsboot -i "${freebsd_boot}" "${drive}" || exit 5
		fi
	fi
	if [ -n "$efi" ]; then
		mount -t msdosfs "/dev/${drive}p${efi}" "${tmpdir}" || exit 6
		path="/efi/boot"
		file="${path}/${os}-${arch}.efi"
		echo "${0##*/}> install /boot/loader.efi ${drive}p${efi}:${file}"
		mkdir -p "${tmpdir}${path}" || exit 6
		cp /boot/loader.efi "${tmpdir}${file}" || exit 6
		tag="${drive}/${arch}/${os}"
		label="${tag%/*}/$(uname -a)"
		var="$(getefivar "$tag")"
		if [ -n "$var" ]; then
			efibootmgr -B "$var" >&- || exit 6
		fi
		echo "${0##*/}> efibootmgr -cl \"${drive}p${efi}:${file}\" -L \"${label}\""
		efibootmgr -cl "${tmpdir}${file}" -L "$label" >&- || exit 6
		var="$(getefivar "$tag")"
		if [ -n "$var" ]; then
			run efibootmgr -a "$var" || exit 6
		else
			echo "failed to register efi: ${label}" >&2
			exit 6
		fi
		umount "$tmpdir" || exit 6
	fi
done