diff --git a/coreboot-t440p/main.sh b/coreboot-t440p/main.sh index 19a6af9..2eb265d 100755 --- a/coreboot-t440p/main.sh +++ b/coreboot-t440p/main.sh @@ -72,7 +72,7 @@ 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 2 ] && run_step 2 "Connect 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 diff --git a/coreboot-t440p/steps/attach_ch341a.sh b/coreboot-t440p/steps/attach_ch341a.sh index 397020f..d41ab13 100755 --- a/coreboot-t440p/steps/attach_ch341a.sh +++ b/coreboot-t440p/steps/attach_ch341a.sh @@ -1,31 +1,53 @@ #!/bin/sh -# Step: Verify CH341A programmer connection +# Step: Confirm CH341A programmer is connected to USB + +# CH341A USB vendor:product ID +CH341A_USB_ID="1a86:5512" step_attach_ch341a() { - section "Verify CH341A Programmer" + section "Connect 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" + info "Before continuing:" + echo " 1. Plug the CH341A into a USB port" + echo " 2. Set the voltage jumper to 3.3V (NEVER 5V)" + echo " 3. Leave the SOIC-8 clip UNATTACHED for now" + echo "" + warn "Using 5V WILL permanently damage the BIOS chips on the T440p." + echo "" + info "Clip orientation rules (applies later when reading/writing chips):" + echo " - The red wire on the ribbon = pin 1" + echo " - The dot/notch on the EEPROM chip = pin 1" + echo " - These MUST align, or the chip will be misread or damaged" + echo "" + + # Show reference image (cached locally, rendered inline if possible) + show_image "spi_flasher_assembly.png" "Reference: CH341A + SOIC-8 clip assembly" 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!" + info "Checking USB for CH341A (id $CH341A_USB_ID)..." + + if ! check_command lsusb; then + warn "lsusb not found. Install usbutils to enable programmer detection." + if prompt_yes_default "Continue without USB verification?"; then + return 0 + fi + return 1 + fi + + if lsusb | grep -qi "$CH341A_USB_ID"; then + success "CH341A detected on USB bus." return 0 fi - error "CH341A programmer not detected." + error "CH341A not found on USB bus." 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 " - Re-plug the programmer (try a different USB port)" + echo " - Check with: lsusb | grep $CH341A_USB_ID" + echo " - If lsusb sees it under a different ID, the device may be" + echo " a clone with different firmware — note the ID and retry" echo "" if prompt_yes_no "Retry detection?"; then diff --git a/coreboot-t440p/steps/extract_bios.sh b/coreboot-t440p/steps/extract_bios.sh index 5849731..4198b44 100755 --- a/coreboot-t440p/steps/extract_bios.sh +++ b/coreboot-t440p/steps/extract_bios.sh @@ -1,41 +1,74 @@ #!/bin/sh # Step: Extract original BIOS from both EEPROM chips +# +# Order rationale: read 4MB (top) chip first — smaller, faster, +# surfaces setup issues (clip alignment, voltage, ribbon) sooner. + +# Read a chip with inline retry on failure. +# $1 = output filename +# $2 = human label (e.g. "4MB (top) — read 1 of 2") +_read_with_retry() { + _out="$1" + _label="$2" + + while true; do + info "Reading $_label ..." + if run_cmd "sudo flashrom --programmer ch341a_spi -r $_out"; then + return 0 + fi + + echo "" + warn "Read failed. Most common causes:" + echo " - Clip not seated flush on chip (try pressing down gently)" + echo " - Pin 1 misaligned (red wire must match chip's dot/notch)" + echo " - Laptop still has residual power (remove battery + CMOS)" + echo " - Cheap SOIC-8 clips can make intermittent contact" + echo "" + echo " 1) Re-seat clip and retry" + echo " 2) Abort" + echo "" + printf "${CYAN}Choice [1-2]:${NC} " + read -r _choice + case "$_choice" in + 1) continue ;; + *) return 1 ;; + esac + done +} 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" + info "The T440p has two EEPROM chips beside the SODIMM slots:" + echo " - 4MB (top) — smaller SOIC-8, farther from CPU" + echo " - 8MB (bottom) — larger SOIC-8, closer to CPU (holds ME firmware)" + echo "" + info "Each chip is read twice so we can diff the results and catch flaky reads." + echo "" + + # Show reference image for chip locations + show_image "eeprom_chips_location.png" "Reference: EEPROM chip locations on T440p mainboard" 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 --- + # --- 4MB chip (do first: smaller = faster iteration on setup) --- echo "" - info "Attach the programmer to the 4MB (top) chip." + info "Clip the CH341A onto the ${BOLD}4MB (top)${NC} chip." + info "Align the red ribbon wire with the dot/notch on the chip (pin 1)." 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 - + _read_with_retry "4mb_backup1.bin" "4MB chip (read 1 of 2)" || return 1 + _read_with_retry "4mb_backup2.bin" "4MB chip (read 2 of 2)" || return 1 success "4MB chip reads complete." # --- 8MB chip --- echo "" - info "Now attach the programmer to the 8MB (bottom) chip." + info "Now move the clip to the ${BOLD}8MB (bottom)${NC} chip." + info "Re-check pin 1 alignment before pressing down." 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 - + _read_with_retry "8mb_backup1.bin" "8MB chip (read 1 of 2)" || return 1 + _read_with_retry "8mb_backup2.bin" "8MB chip (read 2 of 2)" || return 1 success "8MB chip reads complete." } diff --git a/coreboot-t440p/system.sh b/coreboot-t440p/system.sh index 4de1514..24baf4c 100755 --- a/coreboot-t440p/system.sh +++ b/coreboot-t440p/system.sh @@ -7,31 +7,32 @@ install_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" + run_cmd "sudo pacman -S --needed base-devel curl git gcc-ada ncurses zlib nasm sharutils unzip flashrom usbutils chafa" ;; 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" + run_cmd "sudo apt install -y build-essential curl git gnat libncurses-dev zlib1g-dev nasm sharutils unzip flashrom usbutils chafa" ;; 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" + run_cmd "sudo dnf install -y @development-tools curl git gcc-gnat ncurses-devel zlib-devel nasm sharutils unzip flashrom usbutils chafa" ;; 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" + 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 sys-apps/usbutils media-gfx/chafa" ;; nix) info "Installing packages via nix-env..." - run_cmd "nix-env -i stdenv curl git gcc gnat ncurses zlib nasm sharutils unzip flashrom" + run_cmd "nix-env -i stdenv curl git gcc gnat ncurses zlib nasm sharutils unzip flashrom usbutils chafa" ;; *) 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 " ncurses, zlib, nasm, sharutils, unzip, flashrom, usbutils" + echo " Optional: chafa (for inline image previews in this script)" echo "" prompt_continue return 0 diff --git a/coreboot-t440p/utils.sh b/coreboot-t440p/utils.sh index d14fe81..dbb66a3 100755 --- a/coreboot-t440p/utils.sh +++ b/coreboot-t440p/utils.sh @@ -79,6 +79,74 @@ run_cmd() { return $_status } +# --- Inline image rendering --- + +# Base URL for blog assets (override via env if needed). +IMAGE_BASE_URL="${IMAGE_BASE_URL:-https://timmypidashev.dev/blog/thinkpad-t440p-coreboot-guide}" + +# Attempt to render $1 inline. Returns 0 on success, 1 if no supported backend. +_render_image() { + _path="$1" + + # chafa handles kitty / iterm2 / sixel / ANSI fallback automatically + if check_command chafa; then + chafa --size=60x25 "$_path" 2>/dev/null && return 0 + fi + + # Native kitty icat + if [ -n "$KITTY_WINDOW_ID" ] && check_command kitty; then + kitty +kitten icat --align=left "$_path" 2>/dev/null && return 0 + fi + + # iTerm2 / WezTerm inline image protocol + case "$TERM_PROGRAM" in + iTerm.app|WezTerm) + if check_command base64; then + _b64=$(base64 < "$_path" | tr -d '\n') + _sz=$(wc -c < "$_path") + printf '\033]1337;File=inline=1;size=%s:%s\a\n' "$_sz" "$_b64" + return 0 + fi + ;; + esac + + return 1 +} + +# show_image [caption] +# Downloads $IMAGE_BASE_URL/ into $WORK_DIR/.images/, +# renders inline if possible, otherwise prints the URL. +show_image() { + _name="$1" + _caption="$2" + _url="$IMAGE_BASE_URL/$_name" + _cache="${WORK_DIR:-/tmp}/.images" + _local="$_cache/$_name" + + mkdir -p "$_cache" + + if [ ! -f "$_local" ]; then + if ! curl -fsSL "$_url" -o "$_local" 2>/dev/null; then + rm -f "$_local" + info "Reference image: $_url" + [ -n "$_caption" ] && info "$_caption" + return 1 + fi + fi + + if _render_image "$_local"; then + [ -n "$_caption" ] && printf " ${DIM}%s${NC}\n" "$_caption" + return 0 + fi + + # No renderer available + info "Reference image: $_url" + if ! check_command chafa; then + info "(Install 'chafa' for inline image previews: sudo pacman -S chafa)" + fi + [ -n "$_caption" ] && info "$_caption" +} + # Handle step failure - ask user how to proceed handle_failure() { echo ""