Files
hackintosh-asus-b760-i7-13700k/hackintosh-guide/Utilities/ShimUtils/shim-make.tool
2026-02-05 14:06:25 +00:00

340 lines
11 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) 2023 Mike Beaton. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
#
# Makes user build of shim which launches OpenCore.efi and includes specified vendor certificate lists.
# Builds on macOS using Ubuntu multipass or on Linux directly (Ubuntu & Fedora tested).
#
# To debug shim (e.g. within OVMF) make with
# ./shim-make.tool make OPTIMIZATIONS="-O0"
# and set 605dab50-e046-4300-abb6-3dd810dd8b23:SHIM_DEBUG to (UINT8)1 (<data>AQ==</data>) in NVRAM
#
ROOT=~/shim_root
SHIM=~/shim_source
OC_SHIM=oc-shim
unamer() {
NAME="$(uname)"
if [ "$(echo "${NAME}" | grep MINGW)" != "" ] || [ "$(echo "${NAME}" | grep MSYS)" != "" ]; then
echo "Windows"
else
echo "${NAME}"
fi
}
shim_command () {
DIR=$1
shift
if [ $DARWIN -eq 1 ] ; then
if [ $ECHO -eq 1 ] ; then
# shellcheck disable=SC2068
echo multipass exec ${OC_SHIM} --working-directory "'${DIR}'" -- $@ 1>/dev/stderr
fi
# shellcheck disable=SC2068,SC2294
eval multipass exec ${OC_SHIM} --working-directory "'${DIR}'" -- $@
else
if [ $ECHO -eq 1 ] ; then
# shellcheck disable=SC2068
echo "[${DIR}]" $@ 1>/dev/stderr
fi
pushd "${DIR}" 1>/dev/null || exit 1
# shellcheck disable=SC2068,SC2294
eval $@
retval=$?
popd 1>/dev/null || exit 1
return $retval
fi
}
shim_command_v () {
FOUND="$(shim_command . command -v "'${1}'" | wc -l)"
return $((1 - $FOUND))
}
usage() {
echo "Usage:"
echo -n " ./${SELFNAME} [args] [setup|clean|make [options]|install [esp-root-path]"
if [ $DARWIN -eq 1 ] ; then
echo -n "|mount [multipass-path]]"
fi
echo "]"
echo
echo "Args:"
echo -n " -r : Specify shim output root, default '${ROOT}'"
if [ $DARWIN -eq 1 ] ; then
echo -n " (shared)"
fi
echo
echo -n " -s : Specify shim source location, default '${SHIM}'"
if [ $DARWIN -eq 1 ] ; then
echo -n " (VM only, unless 'shim-make mount' used for development/debugging)"
fi
echo
echo "If used, -r/-s:"
echo " - Should be specified on every call, they are not remembered from 'setup'"
echo " - Should come before the chosen command"
echo
echo "Examples:"
echo " ./${SELFNAME} setup (sets up directories and installs rhboot/shim source)"
echo " ./${SELFNAME} clean (cleans after previous make)"
LOCATION="."
if [ $DARWIN -eq 1 ] ; then
LOCATION="${ROOT}"
fi
echo -n " ./${SELFNAME} make VENDOR_DB_FILE='${LOCATION}/combined/vendor.db' VENDOR_DBX_FILE='${LOCATION}/combined/vendor.dbx' (makes shim with db and dbx contents"
if [ $DARWIN -eq 1 ] ; then
echo -n "; note VENDOR_DB_FILE and VENDOR_DBX_FILE are inside a directory shared with VM"
fi
echo ")"
echo " ./${SELFNAME} install '${EXAMPLE_ESP}' (installs made files to ESP mounted at '${EXAMPLE_ESP}')"
echo
echo "After installation shimx64.efi and mmx64.efi must be signed by user ISK; OpenCore.efi must have an .sbat section added and be signed by user ISK."
}
mount_path () {
SRC=$1
if [ "${SRC}" = "" ] ; then
echo "Incorrect call to mount_path!"
exit 1
fi
DEST=$2
if [ "${DEST}" = "" ] ; then
DEST=${SRC}
fi
if [ ! -d "${SRC}" ] ; then
echo "Adding ${SRC}..."
mkdir -p "${SRC}" || exit 1
else
echo "${SRC} already present..."
fi
if [ $DARWIN -eq 1 ] ; then
if ! multipass info ${OC_SHIM} | grep "${DEST}" 1>/dev/null ; then
echo "Mounting ${SRC}..."
multipass mount "${SRC}" "${OC_SHIM}:${DEST}" || exit 1
else
echo "${SRC} already mounted..."
fi
fi
}
get_ready () {
if [ $DARWIN -eq 1 ] ; then
if ! command -v multipass 1>/dev/null ; then
echo "Installing Ubuntu multipass..."
brew install --cask multipass || exit 1
else
echo "Ubuntu multipass already installed..."
fi
if ! multipass info ${OC_SHIM} &>/dev/null ; then
echo "Launching ${OC_SHIM} multipass instance..."
multipass launch -n ${OC_SHIM} || exit 1
else
echo "${OC_SHIM} multipass instance already launched..."
fi
fi
mount_path "${ROOT}"
if ! shim_command_v gcc || ! shim_command_v make || ! shim_command_v git || ! shim_command_v sbsign || ! shim_command_v sbsiglist ; then
echo "Installing dependencies..."
if shim_command_v dnf ; then
shim_command . sudo dnf install -y gcc make git elfutils-libelf-devel sbsigntools efitools || exit 1
else
shim_command . sudo apt-get update || exit 1
shim_command . sudo apt install -y gcc make git libelf-dev sbsigntool efitools || exit 1
fi
else
echo "Dependencies already installed..."
fi
#
# For debug/develop purposes on Darwin it would be nicer to keep the source code in
# macOS, just mounted and built in multipass, but the build is about 1/3 the speed of
# building in a native multipass directory.
# For the purposes of having a fast build but code which can be opened e.g.
# within an IDE within macOS, sshfs can be used to mount out from multipass
# to macOS using ./shim-make mount:
# - https://github.com/canonical/multipass/issues/1070
# - https://osxfuse.github.io/
#
if ! shim_command . test -d "'${SHIM}'" ; then
# TODO: Once there is a stable version of Shim containing the commits we need
# - 1f38cb30a5e1dcea97b8d48915515b866ec13c32
# - a8b0b600ddcf02605da8582b4eac1932a3bb13fa
# (i.e. 15.8. hopefully) we should probably check out at a fixed, stable tag, starting
# at 15.8 and then manually updated in this script when a new stable version is released,
# but which can be overridden with any commit or branch with a script option.
echo "Cloning rhboot/shim..."
shim_command . git clone https://github.com/rhboot/shim.git "'${SHIM}'" || exit 1
shim_command "${SHIM}" git submodule update --init || exit 1
else
if ! shim_command "${SHIM}" git remote -v | grep "rhboot/shim" 1>/dev/null ; then
echo "FATAL: VM subdirectory ${SHIM} is already present, but does not contain rhboot/shim!"
exit 1
fi
echo "rhboot/shim already cloned..."
fi
echo "Make.defaults:"
# These two modifications to Make.defaults only required for debugging
FOUND=$(shim_command "${SHIM}" grep "gdwarf" Make.defaults | wc -l)
if [ "$FOUND" -eq 0 ] ; then
echo " Updating gdwarf flags..."
shim_command "${SHIM}" sed -i "'s^-ggdb \\\\^-ggdb -gdwarf-4 -gstrict-dwarf \\\\^g'" Make.defaults
else
echo " gdwarf flags already updated..."
fi
FOUND=$(shim_command "${SHIM}" grep "'${ROOT}'" Make.defaults | wc -l)
if [ "$FOUND" -eq 0 ] ; then
echo " Updating debug directory..."
shim_command "${SHIM}" sed -i "\"s^-DDEBUGDIR='L\\\"/usr/lib/debug/usr/share/shim/\\\$(ARCH_SUFFIX)-\\\$(VERSION)\\\$(DASHRELEASE)/\\\"'^-DDEBUGDIR='L\\\"${ROOT}/usr/lib/debug/boot/efi/EFI/OC/\\\"'^g\"" Make.defaults
else
echo " Debug directory already updated..."
fi
# Work-around for https://github.com/rhboot/shim/issues/596
FOUND=$(shim_command "${SHIM}" grep "'export DEFINES'" Make.defaults | wc -l)
if [ "$FOUND" -eq 0 ] ; then
echo " Updating exports..."
# var assignment to make output piping work normally
# shellcheck disable=SC2034
temp=$(echo "export DEFINES" | shim_command "${SHIM}" tee -a Make.defaults) 1>/dev/null
else
echo " Exports already updated..."
fi
}
SELFNAME="$(/usr/bin/basename "${0}")"
ECHO=0
if [ "$(unamer)" = "Darwin" ] ; then
DARWIN=1
EXAMPLE_ESP='/Volumes/EFI'
else
DARWIN=0
EXAMPLE_ESP='/boot/efi'
fi
OPTS=0
while [ "${1:0:1}" = "-" ] ; do
OPTS=1
if [ "$1" = "-r" ] ; then
shift
if [ "$1" != "" ] && ! [ "${1:0:1}" = "-" ] ; then
ROOT=$1
shift
else
echo "No root directory specified" && exit 1
fi
elif [ "$1" = "-s" ] ; then
shift
if [ "$1" != "" ] && ! [ "${1:0:1}" = "-" ] ; then
SHIM=$1
shift
else
echo "No shim directory specified" && exit 1
fi
elif [ "$1" = "--echo" ] ; then
ECHO=1
shift
else
echo "Unknown option: $1"
exit 1
fi
done
if [ "$1" = "setup" ] ; then
get_ready
echo "Installation complete."
exit 0
elif [ "$1" = "clean" ] ; then
echo "Cleaning..."
shim_command "${SHIM}" make clean
exit 0
elif [ "$1" = "make" ] ; then
echo "Making..."
shift
shim_command "${SHIM}" make DEFAULT_LOADER="\\\\\\\\OpenCore.efi" OVERRIDE_SECURITY_POLICY=1 "$@"
exit 0
elif [ "$1" = "install" ] ; then
echo "Installing..."
rm -rf "${ROOT:?}"/usr
shim_command "${SHIM}" DESTDIR="'${ROOT}'" EFIDIR='OC' OSLABEL='OpenCore' make install
if [ ! "$2" = "" ] ; then
echo "Installing to ESP ${2}..."
cp "${ROOT}"/boot/efi/EFI/OC/* "${2}"/EFI/OC || exit 1
fi
exit 0
elif [ $DARWIN -eq 1 ] && [ "$1" = "mount" ] ; then
MOUNT="$2"
if [ "${MOUNT}" = "" ] ; then
MOUNT=$SHIM
fi
#
# Useful for devel/debug only.
# Note: We are only mounting in the reverse direction because we get much faster build speeds.
#
if ! command -v sshfs 1>/dev/null ; then
echo "sshfs (https://osxfuse.github.io/) is required for mounting directories from multipass into macOS (https://github.com/canonical/multipass/issues/1070)"
exit 1
fi
if [ ! -d "${MOUNT}" ] ; then
echo "Making local directory ${MOUNT}..."
mkdir -p "${MOUNT}" || exit 1
fi
ls "${MOUNT}" 1>/dev/null
if [ $? -ne 0 ] ; then
echo "Directory may be mounted but not ready (no authorized key?)"
echo "Try: umount ${MOUNT}"
exit 1
fi
if mount | grep ":${MOUNT}" ; then
echo "Already mounted at ${MOUNT}"
exit 0
fi
# shellcheck disable=SC2012
if [ "$(ls -A -1 "${MOUNT}" | wc -l)" -ne 0 ] ; then
echo "Directory ${MOUNT} is not empty!"
exit 1
fi
IP=$(multipass info ${OC_SHIM} | grep IPv4 | cut -d ":" -f 2 | sed 's/ //g')
if [ "${IP}" = "" ] ; then
echo "Cannot obtain IPv4 for ${OC_SHIM}"
exit 1
fi
if sshfs "ubuntu@${IP}:$(realpath "${MOUNT}")" "${MOUNT}" ; then
echo "Mounted at ${MOUNT}"
exit 0
else
umount "${MOUNT}"
echo "Directory cannot be mounted, append your ssh public key to .ssh/authorized_keys in the VM and try again."
exit 1
fi
elif [ "$1" = "" ] ; then
if [ $OPTS -eq 0 ] ; then
usage
else
echo "No command specified."
fi
exit 1
else
echo "Unkown command: $1"
exit 1
fi