From aaa53d6a0911e8632984593c87013b8fe37e68ab Mon Sep 17 00:00:00 2001 From: Timothy Pidashev Date: Tue, 14 Apr 2026 01:16:13 -0700 Subject: [PATCH] update t440p script --- coreboot-t440p/config.sh | 63 +++++++++++ coreboot-t440p/main.sh | 149 ++++++++++++++++++++++++ coreboot-t440p/manifest.txt | 2 +- coreboot-t440p/steps/attach_ch341a.sh | 37 ++++++ coreboot-t440p/steps/backup_bios.sh | 48 ++++++++ coreboot-t440p/steps/build_bios.sh | 34 ++++++ coreboot-t440p/steps/build_cbfstool.sh | 17 +++ coreboot-t440p/steps/build_ifdtool.sh | 60 ++++++++++ coreboot-t440p/steps/build_peppy.sh | 42 +++++++ coreboot-t440p/steps/clone_coreboot.sh | 42 +++++++ coreboot-t440p/steps/combine_bios.sh | 27 +++++ coreboot-t440p/steps/configure.sh | 151 +++++++++++++++++++++++++ coreboot-t440p/steps/extract_bios.sh | 41 +++++++ coreboot-t440p/steps/flash_bios.sh | 58 ++++++++++ coreboot-t440p/steps/revert_bios.sh | 85 ++++++++++++++ coreboot-t440p/steps/update_bios.sh | 25 ++++ coreboot-t440p/system.sh | 58 ++++++++++ coreboot-t440p/utils.sh | 98 ++++++++++++++++ run.sh | 20 ++-- 19 files changed, 1046 insertions(+), 11 deletions(-) create mode 100755 coreboot-t440p/steps/attach_ch341a.sh create mode 100755 coreboot-t440p/steps/backup_bios.sh create mode 100755 coreboot-t440p/steps/build_bios.sh create mode 100755 coreboot-t440p/steps/build_cbfstool.sh create mode 100755 coreboot-t440p/steps/build_ifdtool.sh create mode 100755 coreboot-t440p/steps/build_peppy.sh create mode 100755 coreboot-t440p/steps/clone_coreboot.sh create mode 100755 coreboot-t440p/steps/combine_bios.sh create mode 100755 coreboot-t440p/steps/configure.sh create mode 100755 coreboot-t440p/steps/extract_bios.sh create mode 100755 coreboot-t440p/steps/flash_bios.sh create mode 100755 coreboot-t440p/steps/revert_bios.sh create mode 100755 coreboot-t440p/steps/update_bios.sh diff --git a/coreboot-t440p/config.sh b/coreboot-t440p/config.sh index e69de29..b094335 100755 --- a/coreboot-t440p/config.sh +++ b/coreboot-t440p/config.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# Configuration for coreboot-t440p interactive script + +# Paths +WORK_DIR="${WORK_DIR:-$HOME/t440p-coreboot}" +COREBOOT_DIR="$WORK_DIR/coreboot" + +# The coreboot commit known to work with this guide +COREBOOT_COMMIT="e1e762716cf925c621d58163133ed1c3e006a903" + +# Blob paths (populated after extraction) +BLOB_IFD="$WORK_DIR/ifd.bin" +BLOB_ME="$WORK_DIR/me.bin" +BLOB_GBE="$WORK_DIR/gbe.bin" +BLOB_MRC="$WORK_DIR/mrc.bin" +ORIGINAL_ROM="$WORK_DIR/t440p-original.rom" + +# Expected ROM sizes in bytes +SIZE_4MB=4194304 +SIZE_8MB=8388608 +SIZE_12MB=12582912 + +# Detect the Linux distribution +detect_distro() { + if [ -f /etc/os-release ]; then + . /etc/os-release + case "$ID" in + arch|manjaro|endeavouros|artix|garuda) + DISTRO="arch" ;; + debian|ubuntu|pop|linuxmint|elementary|zorin|kali) + DISTRO="debian" ;; + fedora|centos|rhel|rocky|alma|nobara) + DISTRO="fedora" ;; + gentoo|funtoo) + DISTRO="gentoo" ;; + nixos) + DISTRO="nix" ;; + *) + DISTRO="unknown" ;; + esac + elif command -v nix-env >/dev/null 2>&1; then + DISTRO="nix" + elif command -v pacman >/dev/null 2>&1; then + DISTRO="arch" + elif command -v apt >/dev/null 2>&1; then + DISTRO="debian" + elif command -v dnf >/dev/null 2>&1; then + DISTRO="fedora" + elif command -v emerge >/dev/null 2>&1; then + DISTRO="gentoo" + else + DISTRO="unknown" + fi + + export DISTRO +} + +# Create working directory +setup_work_dir() { + if [ ! -d "$WORK_DIR" ]; then + mkdir -p "$WORK_DIR" + fi +} diff --git a/coreboot-t440p/main.sh b/coreboot-t440p/main.sh index e69de29..19a6af9 100755 --- a/coreboot-t440p/main.sh +++ b/coreboot-t440p/main.sh @@ -0,0 +1,149 @@ +#!/bin/sh +# Coreboot T440p Interactive Installer +# https://timmypidashev.dev/blog/thinkpad-t440p-coreboot-guide + +set -e + +# Resolve script directory +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +# Source dependencies +. "$SCRIPT_DIR/utils.sh" +. "$SCRIPT_DIR/config.sh" +. "$SCRIPT_DIR/system.sh" + +# Source all step scripts +for _step_file in "$SCRIPT_DIR/steps/"*.sh; do + [ -f "$_step_file" ] && . "$_step_file" +done + +# Disable set -e after sourcing (we handle errors per-step) +set +e + +# --- Banner --- + +show_banner() { + printf "${BOLD}${PURPLE}" + echo "" + echo " ╔════════════════════════════════════════════════════╗" + echo " ║ Coreboot T440p Interactive Installer ║" + echo " ╚════════════════════════════════════════════════════╝" + printf "${NC}" + echo "" + echo " Guide: timmypidashev.dev/blog/thinkpad-t440p-coreboot-guide" + echo "" +} + +# --- Step runner --- + +# Run a step function with retry/skip handling +run_step() { + _step_num="$1" + _step_name="$2" + _step_func="$3" + + printf "\n${BOLD}${CYAN}[Step %s/12] %s${NC}\n" "$_step_num" "$_step_name" + echo "" + + while true; do + "$_step_func" + _rc=$? + + if [ $_rc -eq 0 ]; then + return 0 + fi + + # Step failed - ask what to do + handle_failure "$_step_name" + _decision=$? + + if [ $_decision -eq 0 ]; then + # Skip + warn "Skipping: $_step_name" + return 0 + fi + # Otherwise retry (loop continues) + done +} + +# --- Main flow --- + +run_full_install() { + _start="${1:-1}" + + [ "$_start" -le 1 ] && run_step 1 "Install Dependencies" install_dependencies + [ "$_start" -le 2 ] && run_step 2 "Verify CH341A Programmer" step_attach_ch341a + [ "$_start" -le 3 ] && run_step 3 "Extract Original BIOS" step_extract_bios + [ "$_start" -le 4 ] && run_step 4 "Verify BIOS Backups" step_backup_bios + [ "$_start" -le 5 ] && run_step 5 "Combine BIOS Images" step_combine_bios + [ "$_start" -le 6 ] && run_step 6 "Clone Coreboot Repository" step_clone_coreboot + [ "$_start" -le 7 ] && run_step 7 "Build ifdtool & Extract Blobs" step_build_ifdtool + [ "$_start" -le 8 ] && run_step 8 "Build cbfstool" step_build_cbfstool + [ "$_start" -le 9 ] && run_step 9 "Obtain mrc.bin" step_build_peppy + [ "$_start" -le 10 ] && run_step 10 "Configure Coreboot" step_configure + [ "$_start" -le 11 ] && run_step 11 "Build Coreboot" step_build_bios + [ "$_start" -le 12 ] && run_step 12 "Flash Coreboot" step_flash_bios + + echo "" + printf "${BOLD}${GREEN}" + echo " ╔════════════════════════════════════════════════════╗" + echo " ║ All steps complete! ║" + echo " ╚════════════════════════════════════════════════════╝" + printf "${NC}\n" +} + +# --- Entry point --- + +main() { + show_banner + detect_distro + + info "Detected distro: $DISTRO" + + setup_work_dir + info "Working directory: $WORK_DIR" + echo "" + + echo " What would you like to do?" + echo "" + echo " 1) Full install - Run all steps from the beginning" + echo " 2) Resume from step - Start from a specific step" + echo " 3) Update coreboot - Internal flash (already running coreboot)" + echo " 4) Revert to original - Restore original BIOS" + echo " 5) Quit" + echo "" + + printf "${CYAN}Choice [1-5]:${NC} " + read -r _choice + + case "$_choice" in + 1) + run_full_install 1 + ;; + 2) + echo "" + echo " Steps:" + echo " 1. Install dependencies 7. Build ifdtool & extract blobs" + echo " 2. Verify CH341A programmer 8. Build cbfstool" + echo " 3. Extract original BIOS 9. Obtain mrc.bin" + echo " 4. Verify BIOS backups 10. Configure coreboot" + echo " 5. Combine BIOS images 11. Build coreboot" + echo " 6. Clone coreboot repo 12. Flash coreboot" + echo "" + _start=$(prompt_value "Start from step" "1") + run_full_install "$_start" + ;; + 3) + step_update_bios + ;; + 4) + step_revert_bios + ;; + *) + echo "Exiting." + exit 0 + ;; + esac +} + +main "$@" diff --git a/coreboot-t440p/manifest.txt b/coreboot-t440p/manifest.txt index a4ba149..cab5587 100644 --- a/coreboot-t440p/manifest.txt +++ b/coreboot-t440p/manifest.txt @@ -11,7 +11,7 @@ steps/backup_bios.sh steps/combine_bios.sh steps/clone_coreboot.sh steps/build_ifdtool.sh -steps/build_cbfstool.tsh +steps/build_cbfstool.sh steps/build_peppy.sh steps/configure.sh steps/build_bios.sh diff --git a/coreboot-t440p/steps/attach_ch341a.sh b/coreboot-t440p/steps/attach_ch341a.sh new file mode 100755 index 0000000..397020f --- /dev/null +++ b/coreboot-t440p/steps/attach_ch341a.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Step: Verify CH341A programmer connection + +step_attach_ch341a() { + section "Verify CH341A Programmer" + + info "Make sure your CH341A programmer is:" + echo " 1. Connected to your computer via USB" + echo " 2. Set to 3.3V (NOT 5V!)" + echo " 3. Ribbon cable seated in the correct orientation" + echo "" + warn "Using 5V WILL damage your BIOS chip permanently!" + + prompt_continue + + info "Checking if flashrom detects the CH341A programmer..." + if run_cmd "flashrom --programmer ch341a_spi"; then + success "CH341A programmer detected!" + return 0 + fi + + error "CH341A programmer not detected." + echo "" + echo " Troubleshooting:" + echo " - Ensure the programmer is plugged in" + echo " - Try a different USB port" + echo " - Check the driver: lsusb | grep 1a86:5512" + echo " - Make sure you have permissions (try with sudo)" + echo "" + + if prompt_yes_no "Retry detection?"; then + step_attach_ch341a + return $? + fi + + return 1 +} diff --git a/coreboot-t440p/steps/backup_bios.sh b/coreboot-t440p/steps/backup_bios.sh new file mode 100755 index 0000000..d3cb671 --- /dev/null +++ b/coreboot-t440p/steps/backup_bios.sh @@ -0,0 +1,48 @@ +#!/bin/sh +# Step: Verify BIOS backup integrity + +step_backup_bios() { + section "Verify BIOS Backups" + + cd "$WORK_DIR" || return 1 + + info "Verifying 4MB chip reads match..." + if diff 4mb_backup1.bin 4mb_backup2.bin >/dev/null 2>&1; then + success "4MB chip reads are identical." + else + error "4MB chip reads do NOT match!" + warn "The chip may not be reading reliably. Re-seat the programmer and try again." + return 1 + fi + + info "Verifying 8MB chip reads match..." + if diff 8mb_backup1.bin 8mb_backup2.bin >/dev/null 2>&1; then + success "8MB chip reads are identical." + else + error "8MB chip reads do NOT match!" + warn "The chip may not be reading reliably. Re-seat the programmer and try again." + return 1 + fi + + # Validate file sizes + _size_4mb=$(wc -c < 4mb_backup1.bin) + _size_8mb=$(wc -c < 8mb_backup1.bin) + info "4MB chip size: $_size_4mb bytes (expected $SIZE_4MB)" + info "8MB chip size: $_size_8mb bytes (expected $SIZE_8MB)" + + if [ "$_size_4mb" -ne "$SIZE_4MB" ]; then + warn "4MB chip size mismatch. Expected $SIZE_4MB bytes, got $_size_4mb." + if ! prompt_yes_no "Continue anyway?"; then + return 1 + fi + fi + + if [ "$_size_8mb" -ne "$SIZE_8MB" ]; then + warn "8MB chip size mismatch. Expected $SIZE_8MB bytes, got $_size_8mb." + if ! prompt_yes_no "Continue anyway?"; then + return 1 + fi + fi + + success "All BIOS backups verified." +} diff --git a/coreboot-t440p/steps/build_bios.sh b/coreboot-t440p/steps/build_bios.sh new file mode 100755 index 0000000..f7cf28e --- /dev/null +++ b/coreboot-t440p/steps/build_bios.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# Step: Build coreboot + +step_build_bios() { + section "Build Coreboot" + + cd "$COREBOOT_DIR" || return 1 + + if [ ! -f ".config" ]; then + error "No .config found. Run the configure step first." + return 1 + fi + + _nproc=$(nproc 2>/dev/null || echo 1) + + # Build the cross-compiler + info "Building cross-compiler toolchain (this will take a while)..." + info "Using $_nproc parallel jobs." + run_cmd "make crossgcc-i386 CPUS=$_nproc" || return 1 + success "Cross-compiler ready." + + # Build coreboot + echo "" + info "Building coreboot..." + run_cmd "make -j$_nproc" || return 1 + + if [ ! -f "$COREBOOT_DIR/build/coreboot.rom" ]; then + error "coreboot.rom not found after build." + return 1 + fi + + _size=$(wc -c < "$COREBOOT_DIR/build/coreboot.rom") + success "Build complete: $COREBOOT_DIR/build/coreboot.rom ($_size bytes)" +} diff --git a/coreboot-t440p/steps/build_cbfstool.sh b/coreboot-t440p/steps/build_cbfstool.sh new file mode 100755 index 0000000..4507365 --- /dev/null +++ b/coreboot-t440p/steps/build_cbfstool.sh @@ -0,0 +1,17 @@ +#!/bin/sh +# Step: Build cbfstool + +step_build_cbfstool() { + section "Build cbfstool" + + info "Building cbfstool (Coreboot Filesystem tool)..." + cd "$COREBOOT_DIR" || return 1 + run_cmd "make -C util/cbfstool" || return 1 + + if [ ! -f "$COREBOOT_DIR/util/cbfstool/cbfstool" ]; then + error "cbfstool binary not found after build." + return 1 + fi + + success "cbfstool built." +} diff --git a/coreboot-t440p/steps/build_ifdtool.sh b/coreboot-t440p/steps/build_ifdtool.sh new file mode 100755 index 0000000..d09fb07 --- /dev/null +++ b/coreboot-t440p/steps/build_ifdtool.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# Step: Build ifdtool and extract firmware blobs + +step_build_ifdtool() { + section "Build ifdtool & Extract Firmware Blobs" + + # Build ifdtool + info "Building ifdtool (Intel Firmware Descriptor tool)..." + cd "$COREBOOT_DIR/util/ifdtool" || return 1 + run_cmd "make" || return 1 + + if [ ! -f "$COREBOOT_DIR/util/ifdtool/ifdtool" ]; then + error "ifdtool binary not found after build." + return 1 + fi + success "ifdtool built." + + # Extract firmware blobs from the original ROM + echo "" + info "Extracting firmware blobs from original BIOS..." + + if [ ! -f "$ORIGINAL_ROM" ]; then + error "Original ROM not found: $ORIGINAL_ROM" + error "Complete the BIOS extraction steps first." + return 1 + fi + + run_cmd "./ifdtool -x $ORIGINAL_ROM" || return 1 + + # Move blobs to working directory + if [ -f "flashregion_0_flashdescriptor.bin" ]; then + mv flashregion_0_flashdescriptor.bin "$BLOB_IFD" + success "Extracted: ifd.bin (flash descriptor)" + else + error "Flash descriptor not found in extraction output." + return 1 + fi + + if [ -f "flashregion_2_intel_me.bin" ]; then + mv flashregion_2_intel_me.bin "$BLOB_ME" + success "Extracted: me.bin (Intel ME firmware)" + else + error "Intel ME firmware not found in extraction output." + return 1 + fi + + if [ -f "flashregion_3_gbe.bin" ]; then + mv flashregion_3_gbe.bin "$BLOB_GBE" + success "Extracted: gbe.bin (Gigabit Ethernet config)" + else + error "GbE config not found in extraction output." + return 1 + fi + + # Clean up any other extraction artifacts + rm -f flashregion_*.bin + + echo "" + success "All firmware blobs extracted to $WORK_DIR" +} diff --git a/coreboot-t440p/steps/build_peppy.sh b/coreboot-t440p/steps/build_peppy.sh new file mode 100755 index 0000000..4e33bf3 --- /dev/null +++ b/coreboot-t440p/steps/build_peppy.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# Step: Download peppy ChromeOS image and extract mrc.bin + +step_build_peppy() { + section "Obtain mrc.bin" + + info "mrc.bin is a memory reference code blob needed for Haswell platforms." + info "It will be extracted from a ChromeOS peppy firmware image." + echo "" + + cd "$COREBOOT_DIR/util/chromeos" || return 1 + + # Download peppy firmware + info "Downloading peppy ChromeOS firmware image (this may take a while)..." + run_cmd "./crosfirmware.sh peppy" || return 1 + + # Find the downloaded image + _peppy_image=$(ls coreboot-*.bin 2>/dev/null | head -1) + if [ -z "$_peppy_image" ]; then + error "Peppy firmware image not found after download." + return 1 + fi + info "Downloaded: $_peppy_image" + + # Extract mrc.bin using cbfstool + info "Extracting mrc.bin..." + run_cmd "../cbfstool/cbfstool $_peppy_image extract -f mrc.bin -n mrc.bin -r RO_SECTION" || return 1 + + if [ ! -f "mrc.bin" ]; then + error "mrc.bin not found after extraction." + return 1 + fi + + mv mrc.bin "$BLOB_MRC" + success "mrc.bin extracted to $BLOB_MRC" + + # Clean up the large peppy image + if prompt_yes_default "Remove peppy firmware image to save space?"; then + rm -f coreboot-*.bin + info "Cleaned up peppy firmware image." + fi +} diff --git a/coreboot-t440p/steps/clone_coreboot.sh b/coreboot-t440p/steps/clone_coreboot.sh new file mode 100755 index 0000000..cd1df0d --- /dev/null +++ b/coreboot-t440p/steps/clone_coreboot.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# Step: Clone and prepare the coreboot repository + +step_clone_coreboot() { + section "Clone Coreboot Repository" + + if [ -d "$COREBOOT_DIR" ]; then + warn "Coreboot directory already exists: $COREBOOT_DIR" + if prompt_yes_no "Remove and re-clone?"; then + rm -rf "$COREBOOT_DIR" + else + info "Using existing coreboot directory." + cd "$COREBOOT_DIR" || return 1 + + _current=$(git rev-parse HEAD 2>/dev/null) + if [ "$_current" = "$COREBOOT_COMMIT" ]; then + success "Already on correct commit." + return 0 + else + warn "Current commit ($_current) differs from expected ($COREBOOT_COMMIT)." + if prompt_yes_no "Checkout the correct commit?"; then + run_cmd "git checkout $COREBOOT_COMMIT" || return 1 + run_cmd "git submodule update --init --checkout" || return 1 + fi + return 0 + fi + fi + fi + + info "Cloning coreboot (this may take a while)..." + run_cmd "git clone https://review.coreboot.org/coreboot $COREBOOT_DIR" || return 1 + + cd "$COREBOOT_DIR" || return 1 + + info "Checking out commit: $COREBOOT_COMMIT" + run_cmd "git checkout $COREBOOT_COMMIT" || return 1 + + info "Initializing submodules..." + run_cmd "git submodule update --init --checkout" || return 1 + + success "Coreboot repository ready." +} diff --git a/coreboot-t440p/steps/combine_bios.sh b/coreboot-t440p/steps/combine_bios.sh new file mode 100755 index 0000000..0951354 --- /dev/null +++ b/coreboot-t440p/steps/combine_bios.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# Step: Combine BIOS chip images into a single ROM + +step_combine_bios() { + section "Combine BIOS Images" + + cd "$WORK_DIR" || return 1 + + info "Combining 8MB (bottom) + 4MB (top) into a single 12MB ROM..." + run_cmd "cat 8mb_backup1.bin 4mb_backup1.bin > t440p-original.rom" || return 1 + + _size=$(wc -c < t440p-original.rom) + info "Combined ROM size: $_size bytes" + + if [ "$_size" -eq "$SIZE_12MB" ]; then + success "ROM size correct (12MB)." + else + warn "ROM size is not 12MB ($_size bytes). This may indicate an issue." + if ! prompt_yes_no "Continue anyway?"; then + return 1 + fi + fi + + success "Original BIOS saved: $WORK_DIR/t440p-original.rom" + echo "" + warn "Keep this file safe! You will need it if you ever want to revert." +} diff --git a/coreboot-t440p/steps/configure.sh b/coreboot-t440p/steps/configure.sh new file mode 100755 index 0000000..9f87942 --- /dev/null +++ b/coreboot-t440p/steps/configure.sh @@ -0,0 +1,151 @@ +#!/bin/sh +# Step: Configure coreboot + +step_configure() { + section "Configure Coreboot" + + cd "$COREBOOT_DIR" || return 1 + + # Verify all blobs are present + info "Checking for required firmware blobs..." + _missing=0 + for _blob in "$BLOB_IFD" "$BLOB_ME" "$BLOB_GBE" "$BLOB_MRC"; do + if [ -f "$_blob" ]; then + success "Found: $_blob" + else + error "Missing: $_blob" + _missing=1 + fi + done + + if [ "$_missing" -eq 1 ]; then + error "Some blobs are missing. Complete the previous steps first." + return 1 + fi + + echo "" + info "Choose a payload for your coreboot build:" + echo "" + echo " 1) GRUB2 - Direct Linux boot, includes memtest/nvramcui/coreinfo" + echo " 2) SeaBIOS - Traditional BIOS, best compatibility (Windows/BSD)" + echo " 3) edk2 - UEFI firmware, modern boot interface" + echo " 4) Custom - Open the full configuration menu" + echo "" + + _payload="" + while [ -z "$_payload" ]; do + printf "${CYAN}Choice [1-4]:${NC} " + read -r _choice + case "$_choice" in + 1) _payload="grub2" ;; + 2) _payload="seabios" ;; + 3) _payload="edk2" ;; + 4) _payload="custom" ;; + *) echo "Please enter 1-4." ;; + esac + done + + _has_dgpu="n" + if [ "$_payload" != "custom" ]; then + echo "" + if prompt_yes_no "Does your T440p have the GT730M dGPU?"; then + _has_dgpu="y" + fi + fi + + if [ "$_payload" = "custom" ]; then + info "Opening full coreboot configuration..." + info "Key settings to configure:" + echo " - Mainboard vendor: Lenovo" + echo " - Mainboard model: ThinkPad T440p / W541" + echo " - Set blob paths under Chipset:" + echo " IFD: $BLOB_IFD" + echo " ME: $BLOB_ME" + echo " GbE: $BLOB_GBE" + echo " MRC: $BLOB_MRC" + echo "" + prompt_continue + make nconfig + return $? + fi + + # Generate seed .config + info "Generating configuration for: $_payload" + + cat > .config << COREBOOT_CONFIG +# Mainboard +CONFIG_VENDOR_LENOVO=y +CONFIG_BOARD_LENOVO_HASWELL=y + +# Firmware blobs +CONFIG_HAVE_IFD_BIN=y +CONFIG_IFD_BIN_PATH="$BLOB_IFD" +CONFIG_HAVE_ME_BIN=y +CONFIG_ME_BIN_PATH="$BLOB_ME" +CONFIG_HAVE_GBE_BIN=y +CONFIG_GBE_BIN_PATH="$BLOB_GBE" +CONFIG_HAVE_MRC=y +CONFIG_MRC_FILE="$BLOB_MRC" +COREBOOT_CONFIG + + # Payload-specific options + case "$_payload" in + grub2) + cat >> .config << 'GRUB_CONFIG' + +# Payload +CONFIG_PAYLOAD_GRUB2=y +CONFIG_GRUB2_INCLUDE_RUNTIME_CONFIG_FILE=y + +# Secondary payloads +CONFIG_PAYLOAD_FILE_IS_GRUB2=y +CONFIG_MEMTEST_SECONDARY_PAYLOAD=y +CONFIG_NVRAMCUI_SECONDARY_PAYLOAD=y +CONFIG_COREINFO_SECONDARY_PAYLOAD=y +GRUB_CONFIG + ;; + seabios) + cat >> .config << 'SEABIOS_CONFIG' + +# Payload +CONFIG_PAYLOAD_SEABIOS=y +CONFIG_SEABIOS_STABLE=y +SEABIOS_CONFIG + ;; + edk2) + cat >> .config << 'EDK2_CONFIG' + +# Payload +CONFIG_PAYLOAD_EDK2=y +EDK2_CONFIG + ;; + esac + + # dGPU option ROM + if [ "$_has_dgpu" = "y" ]; then + cat >> .config << 'DGPU_CONFIG' + +# dGPU (GT730M) VGA option ROM +CONFIG_VGA_BIOS=y +CONFIG_VGA_BIOS_DGPU=y +DGPU_CONFIG + info "dGPU option ROM support enabled." + fi + + # Fill in remaining defaults + info "Resolving full configuration with defaults..." + run_cmd "make olddefconfig" || { + warn "olddefconfig failed. Opening full configuration menu instead." + make nconfig + return $? + } + + success "Configuration generated for: $_payload" + + echo "" + if prompt_yes_no "Open the configuration menu to review/customize?"; then + make nconfig + fi + + return 0 +} diff --git a/coreboot-t440p/steps/extract_bios.sh b/coreboot-t440p/steps/extract_bios.sh new file mode 100755 index 0000000..5849731 --- /dev/null +++ b/coreboot-t440p/steps/extract_bios.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# Step: Extract original BIOS from both EEPROM chips + +step_extract_bios() { + section "Extract Original BIOS" + + info "The T440p has two EEPROM chips that need to be read:" + echo " - 4MB (top) chip" + echo " - 8MB (bottom) chip" + echo "" + info "Each chip will be read twice to verify data integrity." + warn "Make sure the programmer is attached to the correct chip!" + + cd "$WORK_DIR" || return 1 + + # --- 4MB chip --- + echo "" + info "Attach the programmer to the 4MB (top) chip." + prompt_continue + + info "Reading 4MB chip (read 1 of 2)..." + run_cmd "sudo flashrom --programmer ch341a_spi -r 4mb_backup1.bin" || return 1 + + info "Reading 4MB chip (read 2 of 2)..." + run_cmd "sudo flashrom --programmer ch341a_spi -r 4mb_backup2.bin" || return 1 + + success "4MB chip reads complete." + + # --- 8MB chip --- + echo "" + info "Now attach the programmer to the 8MB (bottom) chip." + prompt_continue + + info "Reading 8MB chip (read 1 of 2)..." + run_cmd "sudo flashrom --programmer ch341a_spi -r 8mb_backup1.bin" || return 1 + + info "Reading 8MB chip (read 2 of 2)..." + run_cmd "sudo flashrom --programmer ch341a_spi -r 8mb_backup2.bin" || return 1 + + success "8MB chip reads complete." +} diff --git a/coreboot-t440p/steps/flash_bios.sh b/coreboot-t440p/steps/flash_bios.sh new file mode 100755 index 0000000..3625771 --- /dev/null +++ b/coreboot-t440p/steps/flash_bios.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# Step: Flash coreboot to the T440p + +step_flash_bios() { + section "Flash Coreboot" + + cd "$COREBOOT_DIR/build" || return 1 + + if [ ! -f "coreboot.rom" ]; then + error "coreboot.rom not found. Run the build step first." + return 1 + fi + + # Split the ROM + info "Splitting ROM for 8MB (bottom) and 4MB (top) chips..." + run_cmd "dd if=coreboot.rom of=bottom.rom bs=1M count=8" || return 1 + run_cmd "dd if=coreboot.rom of=top.rom bs=1M skip=8" || return 1 + + _bottom_size=$(wc -c < bottom.rom) + _top_size=$(wc -c < top.rom) + info "bottom.rom: $_bottom_size bytes" + info "top.rom: $_top_size bytes" + + echo "" + warn "You are about to flash coreboot onto your T440p." + warn "Make sure your laptop is powered off and the battery is removed." + warn "DO NOT interrupt the flashing process!" + echo "" + + if ! prompt_yes_no "Ready to flash?"; then + info "Flash cancelled." + return 0 + fi + + # Flash 4MB (top) chip + echo "" + info "Attach the programmer to the 4MB (top) chip." + prompt_continue + + info "Flashing 4MB chip..." + run_cmd "sudo flashrom --programmer ch341a_spi -w top.rom" || return 1 + success "4MB chip flashed." + + # Flash 8MB (bottom) chip + echo "" + info "Now attach the programmer to the 8MB (bottom) chip." + prompt_continue + + info "Flashing 8MB chip..." + run_cmd "sudo flashrom --programmer ch341a_spi -w bottom.rom" || return 1 + success "8MB chip flashed." + + echo "" + success "Coreboot has been flashed successfully!" + echo "" + info "Reassemble your laptop and power it on." + info "If everything went well, you should see coreboot boot!" +} diff --git a/coreboot-t440p/steps/revert_bios.sh b/coreboot-t440p/steps/revert_bios.sh new file mode 100755 index 0000000..707659d --- /dev/null +++ b/coreboot-t440p/steps/revert_bios.sh @@ -0,0 +1,85 @@ +#!/bin/sh +# Step: Revert to original BIOS + +step_revert_bios() { + section "Revert to Original BIOS" + + if [ ! -f "$ORIGINAL_ROM" ]; then + error "Original ROM not found: $ORIGINAL_ROM" + error "Cannot revert without the original backup." + return 1 + fi + + echo " How would you like to revert?" + echo "" + echo " 1) Can't boot - Use external CH341A programmer" + echo " 2) Can boot - Flash internally (requires iomem=relaxed)" + echo " 3) Cancel" + echo "" + + printf "${CYAN}Choice [1-3]:${NC} " + read -r _choice + + case "$_choice" in + 1) _revert_external ;; + 2) _revert_internal ;; + *) info "Revert cancelled."; return 0 ;; + esac +} + +_revert_external() { + info "Reverting via external programmer..." + echo "" + + cd "$WORK_DIR" || return 1 + + # Split original ROM for both chips + info "Splitting original ROM..." + run_cmd "dd if=t440p-original.rom of=bottom.rom bs=1M count=8" || return 1 + run_cmd "dd if=t440p-original.rom of=top.rom bs=1M skip=8" || return 1 + + # Flash 4MB (top) chip + info "Attach the programmer to the 4MB (top) chip." + prompt_continue + + info "Flashing original 4MB chip..." + run_cmd "sudo flashrom --programmer ch341a_spi -w top.rom" || return 1 + success "4MB chip restored." + + # Flash 8MB (bottom) chip + echo "" + info "Now attach the programmer to the 8MB (bottom) chip." + prompt_continue + + info "Flashing original 8MB chip..." + run_cmd "sudo flashrom --programmer ch341a_spi -w bottom.rom" || return 1 + success "8MB chip restored." + + echo "" + success "Original BIOS restored! Reassemble and power on." +} + +_revert_internal() { + info "Reverting via internal flash..." + echo "" + + warn "This requires the kernel parameter iomem=relaxed." + echo "" + + if prompt_yes_default "Set iomem=relaxed in GRUB and reboot first?"; then + info "Adding iomem=relaxed to GRUB config..." + run_cmd "sudo sed -i '/GRUB_CMDLINE_LINUX_DEFAULT/ s/\"/ iomem=relaxed\"/2' /etc/default/grub" || return 1 + run_cmd "sudo grub-mkconfig -o /boot/grub/grub.cfg" || return 1 + echo "" + warn "You must reboot now for iomem=relaxed to take effect." + info "After rebooting, run this script again and choose the internal revert option." + return 0 + fi + + info "Flashing original BIOS internally..." + run_cmd "sudo flashrom -p internal:laptop=force_I_want_a_brick -w $ORIGINAL_ROM" || return 1 + + success "Original BIOS restored! Reboot to apply." + echo "" + warn "Remember to remove iomem=relaxed from your GRUB config after reverting." +} diff --git a/coreboot-t440p/steps/update_bios.sh b/coreboot-t440p/steps/update_bios.sh new file mode 100755 index 0000000..b5b5495 --- /dev/null +++ b/coreboot-t440p/steps/update_bios.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# Step: Update coreboot internally (when already running coreboot) + +step_update_bios() { + section "Update Coreboot (Internal Flash)" + + info "This updates your coreboot installation without an external programmer." + info "Only use this if your T440p is already running coreboot." + echo "" + + if [ ! -f "$COREBOOT_DIR/build/coreboot.rom" ]; then + error "coreboot.rom not found. Build coreboot first." + return 1 + fi + + warn "This will overwrite your current BIOS using internal flashing." + if ! prompt_yes_no "Continue?"; then + return 0 + fi + + info "Flashing coreboot internally..." + run_cmd "sudo flashrom -p internal:laptop=force_I_want_a_brick -w $COREBOOT_DIR/build/coreboot.rom" || return 1 + + success "Coreboot updated! Reboot to apply." +} diff --git a/coreboot-t440p/system.sh b/coreboot-t440p/system.sh index e69de29..4de1514 100755 --- a/coreboot-t440p/system.sh +++ b/coreboot-t440p/system.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# System dependency installation for coreboot-t440p + +install_dependencies() { + section "Installing Dependencies" + + case "$DISTRO" in + arch) + info "Installing packages via pacman..." + run_cmd "sudo pacman -S --needed base-devel curl git gcc-ada ncurses zlib nasm sharutils unzip flashrom" + ;; + debian) + info "Installing packages via apt..." + run_cmd "sudo apt update" + run_cmd "sudo apt install -y build-essential curl git gnat libncurses-dev zlib1g-dev nasm sharutils unzip flashrom" + ;; + fedora) + info "Installing packages via dnf..." + run_cmd "sudo dnf install -y @development-tools curl git gcc-gnat ncurses-devel zlib-devel nasm sharutils unzip flashrom" + ;; + gentoo) + info "Installing packages via emerge..." + run_cmd "sudo emerge --ask sys-devel/base-devel net-misc/curl dev-vcs/git sys-devel/gcc ncurses dev-libs/zlib dev-lang/nasm app-arch/sharutils app-arch/unzip sys-apps/flashrom" + ;; + nix) + info "Installing packages via nix-env..." + run_cmd "nix-env -i stdenv curl git gcc gnat ncurses zlib nasm sharutils unzip flashrom" + ;; + *) + warn "Could not detect your distribution." + echo "" + echo " Please install these packages manually:" + echo " build-essential/base-devel, curl, git, gcc-ada/gnat," + echo " ncurses, zlib, nasm, sharutils, unzip, flashrom" + echo "" + prompt_continue + return 0 + ;; + esac + + echo "" + _missing=0 + for _cmd in git make gcc flashrom; do + if check_command "$_cmd"; then + success "$_cmd found" + else + error "$_cmd not found" + _missing=1 + fi + done + + if [ "$_missing" -eq 1 ]; then + error "Some required tools are missing. Please install them before continuing." + return 1 + fi + + success "All dependencies installed." +} diff --git a/coreboot-t440p/utils.sh b/coreboot-t440p/utils.sh index e69de29..d14fe81 100755 --- a/coreboot-t440p/utils.sh +++ b/coreboot-t440p/utils.sh @@ -0,0 +1,98 @@ +#!/bin/sh +# Utility functions for coreboot-t440p interactive script + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +CYAN='\033[0;36m' +BOLD='\033[1m' +DIM='\033[2m' +NC='\033[0m' + +# Logging +info() { printf "${BLUE}[*]${NC} %s\n" "$1"; } +warn() { printf "${YELLOW}[!]${NC} %s\n" "$1"; } +error() { printf "${RED}[x]${NC} %s\n" "$1"; } +success() { printf "${GREEN}[+]${NC} %s\n" "$1"; } + +# Print a section header +section() { + printf "\n${BOLD}${PURPLE}--- %s ---${NC}\n\n" "$1" +} + +# Prompt user to continue or quit +prompt_continue() { + printf "\n${CYAN}Press Enter to continue (or 'q' to quit)...${NC} " + read -r _response + case "$_response" in + q|Q) echo "Exiting."; exit 0 ;; + esac +} + +# Prompt yes/no, default no +prompt_yes_no() { + printf "${CYAN}%s [y/N]:${NC} " "$1" + read -r _response + case "$_response" in + [yY]|[yY][eE][sS]) return 0 ;; + *) return 1 ;; + esac +} + +# Prompt yes/no, default yes +prompt_yes_default() { + printf "${CYAN}%s [Y/n]:${NC} " "$1" + read -r _response + case "$_response" in + [nN]|[nN][oO]) return 1 ;; + *) return 0 ;; + esac +} + +# Prompt for a value with a default +prompt_value() { + printf "${CYAN}%s [%s]:${NC} " "$1" "$2" + read -r _response + if [ -z "$_response" ]; then + echo "$2" + else + echo "$_response" + fi +} + +# Check if a command is available +check_command() { + command -v "$1" >/dev/null 2>&1 +} + +# Run a command with display +run_cmd() { + printf " ${DIM}\$ %s${NC}\n" "$1" + eval "$1" + _status=$? + if [ $_status -ne 0 ]; then + error "Command failed (exit code $_status)" + fi + return $_status +} + +# Handle step failure - ask user how to proceed +handle_failure() { + echo "" + error "Step failed: $1" + echo "" + echo " 1) Retry this step" + echo " 2) Skip and continue" + echo " 3) Quit" + echo "" + printf "${CYAN}Choice [1-3]:${NC} " + read -r _choice + case "$_choice" in + 1) return 1 ;; # Signal retry + 2) return 0 ;; # Signal skip + *) exit 1 ;; + esac +} diff --git a/run.sh b/run.sh index fc42983..7553bd9 100755 --- a/run.sh +++ b/run.sh @@ -42,14 +42,14 @@ download_script() { mkdir -p "$(dirname "$output_path")" # Download the script - echo "Downloading $script_path..." + echo "Downloading $script_path..." >&2 curl -fsSL "$BASE_URL/$script_path" -o "$output_path" - + # Make executable if it's a script if echo "$script_path" | grep -q "\.\(sh\|bash\|pl\|py\)$"; then chmod +x "$output_path" fi - + echo "$output_path" } @@ -70,12 +70,12 @@ download_directory() { dir_path="$1" output_dir="$TEMP_DIR/$dir_path" - echo "Downloading directory: $dir_path" + echo "Downloading directory: $dir_path" >&2 mkdir -p "$output_dir" - + # Option 1: If you have a manifest.txt file that lists all files in the directory if curl -s -f "$BASE_URL/$dir_path/manifest.txt" -o "$output_dir/manifest.txt"; then - echo "Found manifest.txt, using it to download files..." + echo "Found manifest.txt, using it to download files..." >&2 while read -r file; do # Skip empty lines and comments [ -z "$file" ] || [ "${file#\#}" != "$file" ] && continue @@ -125,14 +125,14 @@ fi case "$SCRIPT_TYPE" in coreboot-t440p) # Download the entire directory structure - script_dir=$(download_directory "scripts/coreboot-t440p") - + script_dir=$(download_directory "coreboot-t440p") + # Run the main script if it exists if [ -f "$script_dir/main.sh" ]; then "$script_dir/main.sh" "$@" else - # Try to find any executable script - main_script=$(find "$script_dir" -name "*.sh" -executable | head -1) + # Try to find any shell script + main_script=$(find "$script_dir" -name "*.sh" -perm +111 | head -1) if [ -n "$main_script" ]; then "$main_script" "$@" else