blob: e5d6e56805637f34c07c996242f3b68d39ca3e26 [file] [log] [blame]
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
# Convert VM instance to developer mode with mutable rootfs
#
set -o errexit
set -o pipefail
readonly ESPDEV="/dev/sda12"
readonly GRUBCFG="/efi/boot/grub.cfg"
CONFIRMED="no"
KEEP_RO_BYDEFAULT="no"
# trigerring panic instead of reboot is preferrable
# for cos-customizer workflow, in this case customization
# will detect command failure and retry it on the instance
# with R/W-mount
TRIGGER_PANIC="no"
TRIGGER_REBOOT="no"
source /usr/share/vboot/bin/common_minimal.sh
is_dev_mode_enabled() {
local dir
local retval
dir="$(mktemp -d)"
mount -o ro "${ESPDEV}" "${dir}"
local -r grub="${dir}/${GRUBCFG}"
if ! grep -q "defaultA=0" "${grub}" || ! grep -q "defaultB=1" "${grub}"; then
retval=1
else
retval=0
fi
umount "${dir}"
rm -rf "${dir}"
return "${retval}"
}
# This procedure may or may not trigger an immediate reboot. Cos-customizer is
# designed to re-run (and only from) the script that triggered the reboot, so
# it is important that this procedure handles re-entry gracefully.
set_dev_mode() {
local dir
dir="$(mktemp -d)"
mount "${ESPDEV}" "${dir}"
local -r grub="${dir}/${GRUBCFG}"
# set defaultA=0 and defaultB=1
# disable module signaturesh check
sed -i \
-e '/^defaultA=/s:=.*:=0:' \
-e '/^defaultB=/s:=.*:=1:' \
-e 's/module.sig_enforce=1//' \
"${grub}"
# mount rootfs as rw unless requested otherwise
if [[ "${KEEP_RO_BYDEFAULT}" != "yes" ]]; then
sed -i \
-e 's/ ro / rw /' \
"${grub}"
fi
sync
local -r rootdev="$(rootdev -s)"
blockdev --setrw "${rootdev}"
enable_rw_mount "${rootdev}"
umount "${dir}"
rm -rf "${dir}"
# Triggers an immediate reboot.
if [[ "${TRIGGER_REBOOT}" = "yes" ]]; then
reboot
elif [[ "${TRIGGER_PANIC}" = "yes" ]]; then
echo b > /proc/sysrq-trigger
else
echo "COS dev mode will be activated after reboot"
fi
}
usage() {
echo "Usage: $0 [--confirm] [--read-only] [--reboot] [--panic]"
echo "Options:"
echo " --confirm confirm operation without interactive prompt"
echo " --panic force-panic after enabling dev mode"
echo " --read-only disable write-protect but keep rootfs read-only"
echo " --reboot reboot graciously after enabling dev mode"
}
main() {
for opt in "$@"; do
case "${opt}" in
--help|-h)
usage
exit 1
;;
--confirm)
CONFIRMED=yes
;;
--panic)
TRIGGER_PANIC=yes
;;
--read-only)
KEEP_RO_BYDEFAULT=yes
;;
--reboot)
TRIGGER_REBOOT=yes
;;
*)
echo "Unknown option: ${opt}"
usage
exit 1
;;
esac
done
if [[ "${EUID}" -ne 0 ]]; then
echo "Please run as root or use sudo"
exit
fi
if is_dev_mode_enabled; then
echo "COS dev mode is already enabled"
exit 0
fi
if /usr/share/cloud/is-secure-boot; then
echo "Secure boot detected, can't convert to the dev mode"
echo "COS dev mode is not compatible with secure boot"
exit 1
fi
if [[ "${CONFIRMED}" != "yes" ]]; then
while true; do
read -r -p "Do you want to continue? (y/N)"
case "${REPLY}" in
[Yy][Ee][Ss]|[Yy]) break ;;
[Nn][Oo]|[Nn]|"") exit 0;
esac
done
fi
set_dev_mode
}
main "$@"