1#! /bin/sh
2#
3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4#
5# Copyright (c) 2002 Gordon Tetlow. All rights reserved.
6# Copyright (c) 2012 Sandvine Incorporated. All rights reserved.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions
10# are met:
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in the
15#    documentation and/or other materials provided with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27# SUCH DAMAGE.
28#
29# $FreeBSD$
30
31append="NO"
32delete="NO"
33kenv=
34force="NO"
35nextboot_file="/boot/nextboot.conf"
36zfs=
37
38add_kenv()
39{
40	local var value
41
42	var=$1
43	# strip literal quotes if passed in
44	value=${2%\"*}
45	value=${value#*\"}
46
47	if [ -n "${kenv}" ]; then
48		kenv="${kenv}
49"
50	fi
51	kenv="${kenv}${var}=\"${value}\""
52}
53
54display_usage() {
55	cat <<-EOF
56	Usage: nextboot [-af] [-e variable=value] [-k kernel] [-o options]
57	       nextboot -D
58	EOF
59}
60
61while getopts "aDe:fk:o:" argument ; do
62	case "${argument}" in
63	a)
64		append="YES"
65		;;
66	D)
67		delete="YES"
68		;;
69	e)
70		var=${OPTARG%%=*}
71		value=${OPTARG#*=}
72		if [ -z "$var" -o -z "$value" ]; then
73			display_usage
74			exit 1
75		fi
76		add_kenv "$var" "$value"
77		;;
78	f)
79		force="YES"
80		;;
81	k)
82		kernel="${OPTARG}"
83		add_kenv kernel "$kernel"
84		;;
85	o)
86		add_kenv kernel_options "${OPTARG}"
87		;;
88	*)
89		display_usage
90		exit 1
91		;;
92	esac
93done
94
95if [ ${delete} = "YES" ]; then
96	rm -f ${nextboot_file}
97	exit 0
98fi
99
100if [ -z "${kenv}" ]; then
101	display_usage
102	exit 1
103fi
104
105if [ -n "${kernel}" -a ${force} = "NO" -a ! -d /boot/${kernel} ]; then
106	echo "Error: /boot/${kernel} doesn't exist. Use -f to override."
107	exit 1
108fi
109
110zfs=$(df -Tn "/boot/" 2>/dev/null | while read _fs _type _other ; do
111	[ "zfs" = "${_type}" ] || continue
112	echo "${_fs%/ROOT/*}"
113done)
114
115set -e
116
117nextboot_tmp=$(mktemp $(dirname ${nextboot_file})/nextboot.XXXXXX)
118
119if [ -n "${zfs}" ]; then
120	zfsbootcfg -z ${zfs} -n freebsd:nvstore -k nextboot_enable -v YES
121	cat >> ${nextboot_tmp} << EOF
122$kenv
123EOF
124else
125cat >> ${nextboot_tmp} << EOF
126nextboot_enable="YES"
127$kenv
128EOF
129fi
130
131fsync ${nextboot_tmp}
132
133mv ${nextboot_tmp} ${nextboot_file}
134