-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
139 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
#!/bin/bash | ||
# vim: softtabstop=2 shiftwidth=2 expandtab | ||
|
||
cleanup() { | ||
if [[ -f "${TEMP_EFI}" && -z "${PRESERVE_TEMP_EFI}" ]]; then | ||
rm "${TEMP_EFI}" | ||
fi | ||
[ -f "${TEMP_KCL}" ] && rm "${TEMP_KCL}" | ||
} | ||
|
||
usage() { | ||
cat <<-EOF | ||
USAGE: $0 [-e <arg>] [-f <arg>] [-k <arg>] [-o <arg>] | ||
-e <arg> ZFSBootMenu EFI file | ||
-f <arg> Replace kernel command line with contents of file | ||
-k <arg> Replace kernel command line with quoted arguments | ||
-o <arg> Output file; if undefined the input file will be replaced | ||
If neither -f or -k are provided, the command line from the | ||
input EFI will be opened in \$EDITOR. | ||
EOF | ||
} | ||
|
||
INPUT_EFI= | ||
OUTPUT_EFI= | ||
ARG_FILE= | ||
ARG_VAR= | ||
|
||
while getopts "e:f:k:o:" opt; do | ||
case "${opt}" in | ||
e) | ||
INPUT_EFI="${OPTARG}" | ||
if [ ! -f "${INPUT_EFI}" ]; then | ||
echo "Unable to open ${INPUT_EFI}" | ||
exit 1 | ||
fi | ||
# Set OUTPUT_EFI to the input by default | ||
[ -z "${OUTPUT_EFI}" ] && OUTPUT_EFI="${INPUT_EFI}" | ||
;; | ||
o) | ||
# Override the output file | ||
OUTPUT_EFI="${OPTARG}" | ||
;; | ||
f) | ||
ARG_FILE="${OPTARG}" | ||
ARG_VAR= | ||
if [ ! -f "${ARG_FILE}" ]; then | ||
echo "Unable to open ${ARG_FILE}" | ||
exit 1 | ||
fi | ||
;; | ||
k) | ||
ARG_VAR="${OPTARG}" | ||
ARG_FILE= | ||
;; | ||
*) | ||
usage | ||
exit 1 | ||
;; | ||
esac | ||
done | ||
|
||
if [ -z "${INPUT_EFI}" ]; then | ||
usage | ||
exit 1 | ||
fi | ||
|
||
if ! command -v objcopy > /dev/null 2>&1 ; then | ||
echo "Missing required binary 'objcopy'" | ||
exit 1 | ||
fi | ||
|
||
trap cleanup EXIT INT TERM | ||
|
||
TEMP_EFI="$(mktemp)" | ||
if ! objout="$( objcopy --remove-section .cmdline "${INPUT_EFI}" "${TEMP_EFI}" 2>&1 )"; then | ||
echo "Unable to remove .cmdline from '${INPUT_EFI}'" | ||
echo "${objout}" | ||
exit 1 | ||
fi | ||
|
||
TEMP_KCL="$(mktemp)" | ||
if [ -n "${ARG_VAR}" ]; then | ||
echo -n "${ARG_VAR}" > "${TEMP_KCL}" | ||
elif [ -n "${ARG_FILE}" ]; then | ||
cp "${ARG_FILE}" "${TEMP_KCL}" || exit 1 | ||
else | ||
if ! objout="$( objcopy --dump-section .cmdline="${TEMP_KCL}" "${INPUT_EFI}" 2>&1 )"; then | ||
echo "Unable to extract cmdline from '${INPUT_EFI}'" | ||
echo "${objout}" | ||
exit 1 | ||
fi | ||
|
||
# Remove null terminators | ||
sed -i 's/\x0//g' "${TEMP_KCL}" | ||
|
||
# Strip leading and trailing spaces | ||
sed -i 's/^[[:space:]]*//g;s/[[:space:]]*$//g' "${TEMP_KCL}" | ||
|
||
if ! command -v "${EDITOR:=vi}" >/dev/null 2>&1 ; then | ||
echo "define \$EDITOR to edit" | ||
exit 1 | ||
fi | ||
|
||
if ! "${EDITOR}" "${TEMP_KCL}"; then | ||
echo "failed to edit KCL for ${INPUT_EFI}" | ||
exit 1 | ||
fi | ||
fi | ||
|
||
# Strip leading and trailing spaces | ||
sed -i 's/^[[:space:]]*//g;s/[[:space:]]*$//g' "${TEMP_KCL}" | ||
|
||
# Remove existing null terminators | ||
sed -i 's/\x0//g' "${TEMP_KCL}" | ||
|
||
# Collapse multiple lines into one | ||
sed -i -z 's/\n/ /g' "${TEMP_KCL}" | ||
|
||
# Pad with a space; replicating Dracut behavior. | ||
# FIXME: Is this strictly needed? | ||
sed -i 's/^/ /' "${TEMP_KCL}" | ||
|
||
# Add a null terminator for the efi stub; replicating Dracut behavior | ||
echo -ne "\x00" >> "${TEMP_KCL}" | ||
|
||
if objout="$( objcopy --add-section .cmdline="${TEMP_KCL}" --change-section-vma .cmdline=0x30000 "${TEMP_EFI}" 2>&1 )"; then | ||
if ! cp "${TEMP_EFI}" "${OUTPUT_EFI}" ; then | ||
echo "Unable to copy ${TEMP_EFI} to ${OUTPUT}" | ||
echo "Preserving '${TEMP_EFI}'" | ||
PRESERVE_TEMP_EFI=1 | ||
exit 1 | ||
fi | ||
else | ||
echo "Unable to add commandline to ${TEMP_KCL}" | ||
echo "${objout}" | ||
exit 1 | ||
fi |