update t440p script
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 "$@"
|
||||
|
||||
@@ -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
|
||||
|
||||
Executable
+37
@@ -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
|
||||
}
|
||||
Executable
+48
@@ -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."
|
||||
}
|
||||
Executable
+34
@@ -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)"
|
||||
}
|
||||
Executable
+17
@@ -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."
|
||||
}
|
||||
Executable
+60
@@ -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"
|
||||
}
|
||||
Executable
+42
@@ -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
|
||||
}
|
||||
Executable
+42
@@ -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."
|
||||
}
|
||||
Executable
+27
@@ -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."
|
||||
}
|
||||
Executable
+151
@@ -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
|
||||
}
|
||||
Executable
+41
@@ -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."
|
||||
}
|
||||
Executable
+58
@@ -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!"
|
||||
}
|
||||
Executable
+85
@@ -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."
|
||||
}
|
||||
Executable
+25
@@ -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."
|
||||
}
|
||||
@@ -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."
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user