diff --git a/README.md b/README.md index 8edaacb..75046b5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ -# kvs -KVS: Kernel Version Switcher, made to easily switch the tpm_kernver for Chromebooks. +# KVS +KVS: Kernel Version Switcher + + +# Credits +kxtzownsu - Writing KVS & Providing kernver 0 & 1 files +crossystem - Providing kerner 2 files +?? - Providing kernver 3 files (very sorry, but I couldn't find their username) +katie - Getting me a working POC (told me to use `tpmc` instead of `tpm_manager_client`) +Google - y'know.. writing `tpmc` and giving me the idea for this (due to a glitch, my one chromebook got set to kernver 0) \ No newline at end of file diff --git a/builder/builder.sh b/builder/builder.sh index df0ebe4..fe7bd9d 100644 --- a/builder/builder.sh +++ b/builder/builder.sh @@ -1,4 +1,10 @@ #!/bin/bash +# KVS Builder v1 +# Basically a skidded wax, please forgive me +# Credits to the Mercury Workshop team for the shim shrinking stuff :3 +# Made by kxtzownsu +# 3-6-2024 +# GNU Affero GPL v3 SCRIPT_DIR=$(dirname "$0") SCRIPT_DIR=${SCRIPT_DIR:-"."} @@ -9,34 +15,50 @@ echo "KVS Shim Builder v$VERSION" echo "-=-=-=-=-=-=-=-=-=-" [ "$EUID" -ne 0 ] && error "Please run KVS builder as root" [ "$1" == "" ] && error "Shim not specified, remember, usage is $0 " -echo "Requirements: cgpt, e2fsprogs, sgdisk" +[ $(echo $1 | grep -qs '.bin' - && echo true || echo false) == "false" ] && error "Shim is NOT a .bin file!" +echo "Requirements: cgpt, e2fsprogs, sgdisk, raw shim" echo "-=-=-=-=-=-=-=-=-=-" +echo "Before the shim starts building, I'd like to say thank you to the Mercury Workshop team, most of the code (shim shrinking, verity disabling, etc) is from them." +echo "Pres Enter to continue building" +read -r STATE_SIZE=$((4 * 1024 * 1024)) # 4MiB STATE_MNT=$(mktemp -d) +ROOT_MNT=$(mktemp -d) LOOPDEV=$(losetup -f) +clean_mnts(){ + umount -R "$STATE_MNT" + umount -R "$ROOT_MNT" + rm -rf "$STATE_MNT" + rm -rf "$ROOT_MNT" +} + create_stateful() { - log "Creating KVS/Stateful partition" + log "Creating KVS/Stateful partition (1/" local final_sector=$(get_final_sector "$LOOPDEV") local sector_size=$(get_sector_size "$LOOPDEV") cgpt add "$LOOPDEV" -i 1 -b $((final_sector + 1)) -s $((STATE_SIZE / sector_size)) -t data -l KVS partx -u -n 1 "$LOOPDEV" mkfs.ext4 -F -L KVS "${LOOPDEV}p1" &> /dev/null - sync - sleep 0.2 + safesync mount "${LOOPDEV}p1" "$STATE_MNT" touch "$STATE_MNT/dev_image/etc/lsb-factory" chmod -R +x "$STATE_MNT" umount "$STATE_MNT" - rmdir "$STATE_MNT" +} + +inject_stateful(){ + log "Injecting Stateful (2" + + mount } shrink_root() { - log "Shrinking ROOT" + log "Shrinking ROOT (4" enable_rw_mount "${LOOPDEV}p3" suppress e2fsck -fy "${LOOPDEV}p3" @@ -47,15 +69,43 @@ shrink_root() { local block_size=$(tune2fs -l "${LOOPDEV}p3" | grep "Block size" | awk '{print $3}') local block_count=$(tune2fs -l "${LOOPDEV}p3" | grep "Block count" | awk '{print $3}') - log_debug "sector size: ${sector_size}, block size: ${block_size}, block count: ${block_count}" + log "sector size: ${sector_size}, block size: ${block_size}, block count: ${block_count}" - local original_sectors=$("$CGPT" show -i 3 -s -n -q "$LOOPDEV") + local original_sectors=$(cgpt show -i 3 -s -n -q "$LOOPDEV") local original_bytes=$((original_sectors * sector_size)) local resized_bytes=$((block_count * block_size)) local resized_sectors=$((resized_bytes / sector_size)) - log_info "Resizing ROOT from $(format_bytes ${original_bytes}) to $(format_bytes ${resized_bytes})" + log "Resizing ROOT from $(format_bytes ${original_bytes}) to $(format_bytes ${resized_bytes})" "$CGPT" add -i 3 -s "$resized_sectors" "$LOOPDEV" partx -u -n 3 "$LOOPDEV" -} \ No newline at end of file +} + +inject_root(){ + enable_rw_mount "${LOOPDEV}p3" + log "Injecting scripts (3" + + mount "${LOOPDEV}p3" "${ROOT_MNT}" + + # scary if ROOT_MNT gets set to nothing! + cp -r scripts/* "${ROOT_MNT}/usr/sbin" +} + + +create_stateful +inject_stateful +inject_root +shrink_root +shrink_partitions "$LOOPDEV" + +# for prebuilt bins hosted on dl.kxtz.dev +if [ "$2" == "--noskid" ]; then + disable_rw_mount "${LOOPDEV}p3" + log "Disabled RW mounting for ROOT-A" +fi + +clean_mnts +losetup -D "$LOOPDEV" + +truncate_image "$1" \ No newline at end of file diff --git a/builder/functions.sh b/builder/functions.sh index ba72fd2..72dec46 100644 --- a/builder/functions.sh +++ b/builder/functions.sh @@ -2,20 +2,125 @@ COLOR_RESET="\033[0m" COLOR_BLACK_B="\033[1;30m" +COLOR_RED="\033[0;31m" COLOR_RED_B="\033[1;31m" COLOR_GREEN="\033[0;32m" COLOR_GREEN_B="\033[1;32m" COLOR_YELLOW="\033[0;33m" COLOR_YELLOW_B="\033[1;33m" +COLOR_BLUE="\033[0;34m" COLOR_BLUE_B="\033[1;34m" +COLOR_MAGENTA="\033[0;35m" COLOR_MAGENTA_B="\033[1;35m" +COLOR_CYAN="\033[0;36m" COLOR_CYAN_B="\033[1;36m" +readlink /proc/$$/exe | grep -q bash || error "You MUST execute this with Bash!" + log(){ printf '${COLOR_GREEN}Info: %b${COLOR_RESET}\n' "$*" } error(){ - printf '${COLOR_RED_B}ERR: &b${COLOR_RESET}\n' "$*" + printf "${COLOR_RED_B}ERR: %b${COLOR_RESET}\n" "$*" >&2 || : + printf "${COLOR_RED}Exiting... ${COLOR_RESET}\n" >&2 || : exit 1 -} \ No newline at end of file +} + +suppress() { + if [ "${FLAGS_debug:-0}" = "${FLAGS_TRUE:-1}" ]; then + "$@" + else + "$@" &>/dev/null + fi +} + +get_sector_size() { + fdisk -l "$1" | grep "Sector size" | awk '{print $4}' +} + +get_final_sector() { + fdisk -l -o end "$1" | grep "^\s*[0-9]" | awk '{print $1}' | sort -nr | head -n 1 +} + +is_ext2() { + local rootfs="$1" + local offset="${2-0}" + + local sb_magic_offset=$((0x438)) + local sb_value=$(dd if="$rootfs" skip=$((offset + sb_magic_offset)) \ + count=2 bs=1 2>/dev/null) + local expected_sb_value=$(printf '\123\357') + if [ "$sb_value" = "$expected_sb_value" ]; then + return 0 + fi + return 1 +} + +enable_rw_mount() { + local rootfs="$1" + local offset="${2-0}" + + if ! is_ext2 "$rootfs" $offset; then + echo "enable_rw_mount called on non-ext2 filesystem: $rootfs $offset" 1>&2 + return 1 + fi + + local ro_compat_offset=$((0x464 + 3)) + printf '\000' | + dd of="$rootfs" seek=$((offset + ro_compat_offset)) \ + conv=notrunc count=1 bs=1 2>/dev/null +} + +disable_rw_mount() { + local rootfs="$1" + local offset="${2-0}" + + if ! is_ext2 "$rootfs" $offset; then + echo "disable_rw_mount called on non-ext2 filesystem: $rootfs $offset" 1>&2 + return 1 + fi + + local ro_compat_offset=$((0x464 + 3)) + printf '\377' | + dd of="$rootfs" seek=$((offset + ro_compat_offset)) \ + conv=notrunc count=1 bs=1 2>/dev/null +} + +shrink_partitions() { + local shim="$1" + fdisk "$shim" <&1 | sed 's/\a//g' +} diff --git a/builder/scripts/functions.sh b/builder/scripts/kvs/functions.sh similarity index 100% rename from builder/scripts/functions.sh rename to builder/scripts/kvs/functions.sh diff --git a/builder/scripts/tpmutil.sh b/builder/scripts/kvs/tpmutil.sh similarity index 100% rename from builder/scripts/tpmutil.sh rename to builder/scripts/kvs/tpmutil.sh