blob: e72ff7d3950bd7e4d14fcf656610358041ab4a7f [file] [log] [blame]
Yegor Timoshenkoc2e49412018-10-07 01:58:27 +00001#!/usr/bin/env bash
Joe Pillow9a4881a2016-02-19 15:18:14 -08002#
Patrick Georgi7333a112020-05-08 20:48:04 +02003# SPDX-License-Identifier: GPL-2.0-only
Joe Pillow9a4881a2016-02-19 15:18:14 -08004
Tristan Corrickdf90c622018-12-31 20:34:36 +13005# On some systems, `parted` and `debugfs` are located in /sbin.
6export PATH="$PATH:/sbin"
7
Tristan Corrickd80607d2018-12-31 20:54:42 +13008exit_if_uninstalled() {
9 local cmd_name="$1"
10 local deb_pkg_name="$2"
11
12 if type "$cmd_name" >/dev/null 2>&1; then
13 return
14 fi
15
16 printf '`%s` was not found. ' "$cmd_name" >&2
17 printf 'On Debian-based systems, it can be installed\n' >&2
18 printf 'by running `apt install %s`.\n' "$deb_pkg_name" >&2
19
20 exit 1
21}
22
23exit_if_dependencies_are_missing() {
24 exit_if_uninstalled "uudecode" "sharutils"
25 exit_if_uninstalled "debugfs" "e2fsprogs"
26 exit_if_uninstalled "parted" "parted"
27 exit_if_uninstalled "curl" "curl"
Mete Balci63cdea22019-03-08 11:13:45 +000028 exit_if_uninstalled "unzip" "unzip"
Tristan Corrickd80607d2018-12-31 20:54:42 +130029}
30
Matt DeVillier1dc1a562022-02-03 21:43:00 -060031get_inventory() {
Joe Pillow9a4881a2016-02-19 15:18:14 -080032 _conf=$1
33 _url=https://dl.google.com/dl/edgedl/chromeos/recovery/recovery.conf
34
Tristan Corrickf50bd6d2018-12-31 20:58:43 +130035 echo "Downloading recovery image inventory..."
Joe Pillow9a4881a2016-02-19 15:18:14 -080036
Matt DeVillier1dc1a562022-02-03 21:43:00 -060037 curl -s "$_url" >$_conf
Joe Pillow9a4881a2016-02-19 15:18:14 -080038}
39
Matt DeVillier1dc1a562022-02-03 21:43:00 -060040download_image() {
Joe Pillow9a4881a2016-02-19 15:18:14 -080041 _url=$1
42 _file=$2
43
Tristan Corrickf50bd6d2018-12-31 20:58:43 +130044 echo "Downloading recovery image"
Matt DeVillier1dc1a562022-02-03 21:43:00 -060045 curl "$_url" >"$_file.zip"
Tristan Corrickf50bd6d2018-12-31 20:58:43 +130046 echo "Decompressing recovery image"
Joe Pillow9a4881a2016-02-19 15:18:14 -080047 unzip -q "$_file.zip"
48 rm "$_file.zip"
49}
50
Matt DeVillier1dc1a562022-02-03 21:43:00 -060051extract_partition() {
Joe Pillow9a4881a2016-02-19 15:18:14 -080052 NAME=$1
53 FILE=$2
54 ROOTFS=$3
55 _bs=1024
56
Tristan Corrickf50bd6d2018-12-31 20:58:43 +130057 echo "Extracting ROOT-A partition"
Matt DeVillier1dc1a562022-02-03 21:43:00 -060058 ROOTP=$(printf "unit\nB\nprint\nquit\n" |
59 parted $FILE 2>/dev/null | grep $NAME)
Joe Pillow9a4881a2016-02-19 15:18:14 -080060
Matt DeVillierb0844492022-02-03 21:31:34 -060061 if [ "$ROOTP" == "" ]; then
62 # Automatic extraction failed, likely due to parted detecting
63 # overlapping partitions. Fall back to using fdisk and assume
64 # ROOT-A is partition #3
65 echo "(Extracting via parted failed; falling back to fdisk)"
Matt DeVillier1dc1a562022-02-03 21:43:00 -060066 _ssize=$(printf "p q" | fdisk $FILE | grep "Sector size" |
Matt DeVillierb0844492022-02-03 21:31:34 -060067 cut -f2 -d: | cut -f2 -d ' ')
Matt DeVillier1dc1a562022-02-03 21:43:00 -060068 _start=$(printf "p q" | fdisk $FILE | grep "bin3" | tr -s ' ' |
Matt DeVillierb0844492022-02-03 21:31:34 -060069 cut -f2 -d ' ')
Matt DeVillier1dc1a562022-02-03 21:43:00 -060070 _nsec=$(printf "p q" | fdisk $FILE | grep "bin3" | tr -s ' ' |
Matt DeVillierb0844492022-02-03 21:31:34 -060071 cut -f4 -d ' ')
72 START=$(($_ssize * $_start))
73 SIZE=$(($_ssize * $_nsec))
74 else
Matt DeVillier1dc1a562022-02-03 21:43:00 -060075 START=$(($(echo $ROOTP | cut -f2 -d\ | tr -d "B")))
76 SIZE=$(($(echo $ROOTP | cut -f4 -d\ | tr -d "B")))
Matt DeVillierb0844492022-02-03 21:31:34 -060077 fi
Joe Pillow9a4881a2016-02-19 15:18:14 -080078
Matt DeVillier1dc1a562022-02-03 21:43:00 -060079 dd if=$FILE of=$ROOTFS bs=$_bs skip=$(($START / $_bs)) \
80 count=$(($SIZE / $_bs)) >/dev/null 2>&1
Joe Pillow9a4881a2016-02-19 15:18:14 -080081}
82
Matt DeVillier1dc1a562022-02-03 21:43:00 -060083extract_shellball() {
Joe Pillow9a4881a2016-02-19 15:18:14 -080084 ROOTFS=$1
85 SHELLBALL=$2
86
Tristan Corrickf50bd6d2018-12-31 20:58:43 +130087 echo "Extracting chromeos-firmwareupdate"
Matt DeVillier1dc1a562022-02-03 21:43:00 -060088 printf "cd /usr/sbin\ndump chromeos-firmwareupdate $SHELLBALL\nquit" |
89 debugfs $ROOTFS >/dev/null 2>&1
Joe Pillow9a4881a2016-02-19 15:18:14 -080090}
91
Matt DeVillier1dc1a562022-02-03 21:43:00 -060092extract_coreboot() {
Joe Pillow9a4881a2016-02-19 15:18:14 -080093 _shellball=$1
Matt DeVillier1dc1a562022-02-03 21:43:00 -060094 _unpacked=$(mktemp -d)
Joe Pillow9a4881a2016-02-19 15:18:14 -080095
Tristan Corrickf50bd6d2018-12-31 20:58:43 +130096 echo "Extracting coreboot image"
Matt DeVillier1dc1a562022-02-03 21:43:00 -060097 if ! sh $_shellball --unpack $_unpacked >/dev/null 2>&1; then
98 sh $_shellball --sb_extract $_unpacked >/dev/null 2>&1
Matt DeVilliere4273162022-02-03 19:18:29 -060099 fi
Joe Pillow9a4881a2016-02-19 15:18:14 -0800100
Matt DeVilliere4273162022-02-03 19:18:29 -0600101 if [ -d $_unpacked/models/ ]; then
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600102 _version=$(cat $_unpacked/VERSION | grep -m 1 -e Model.*$_board -A5 |
103 grep "BIOS (RW) version:" | cut -f2 -d: | tr -d \ )
Matt DeVilliere4273162022-02-03 19:18:29 -0600104 if [ "$_version" == "" ]; then
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600105 _version=$(cat $_unpacked/VERSION | grep -m 1 -e Model.*$_board -A5 |
106 grep "BIOS version:" | cut -f2 -d: | tr -d \ )
Matt DeVilliere4273162022-02-03 19:18:29 -0600107 fi
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600108 _bios_image=$(grep "IMAGE_MAIN" $_unpacked/models/$_board/setvars.sh |
109 cut -f2 -d\")
Matt DeVilliere4273162022-02-03 19:18:29 -0600110 else
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600111 _version=$(cat $_unpacked/VERSION | grep BIOS\ version: |
112 cut -f2 -d: | tr -d \ )
Matt DeVilliere4273162022-02-03 19:18:29 -0600113 _bios_image=bios.bin
114 fi
115 if cp $_unpacked/$_bios_image coreboot-$_version.bin; then
116 echo "Extracted coreboot-$_version.bin"
117 fi
118 rm -rf "$_unpacked"
119 rm $_shellball
Joe Pillow9a4881a2016-02-19 15:18:14 -0800120}
121
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600122do_one_board() {
Joe Pillow9a4881a2016-02-19 15:18:14 -0800123 _board=$1
124 _url=$2
125 _file=$3
126
127 download_image $_url $_file
128
129 extract_partition ROOT-A $_file root-a.ext2
130 extract_shellball root-a.ext2 chromeos-firmwareupdate-$_board
131 rm $_file root-a.ext2
132
133 extract_coreboot chromeos-firmwareupdate-$_board
134}
135
136#
137# Main
138#
139
Matt DeVillier5470ae72024-05-07 08:40:41 -0500140BOARD=${1,,}
Joe Pillow9a4881a2016-02-19 15:18:14 -0800141
Tristan Corrickd80607d2018-12-31 20:54:42 +1300142exit_if_dependencies_are_missing
143
Joe Pillow9a4881a2016-02-19 15:18:14 -0800144if [ "$BOARD" == "all" ]; then
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600145 CONF=$(mktemp)
Joe Pillow9a4881a2016-02-19 15:18:14 -0800146 get_inventory $CONF
147
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600148 grep ^name= $CONF | while read _line; do
149 name=$(echo $_line | cut -f2 -d=)
Joe Pillow9a4881a2016-02-19 15:18:14 -0800150 echo Processing board $name
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600151 eval $(grep -v hwid= $CONF | grep -A11 "$_line" |
152 grep '\(url=\|file=\)')
153 BOARD=$(echo $url | cut -f3 -d_)
Joe Pillow9a4881a2016-02-19 15:18:14 -0800154 do_one_board $BOARD $url $file
155 done
156
157 rm "$CONF"
158elif [ "$BOARD" != "" ]; then
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600159 CONF=$(mktemp)
Joe Pillow9a4881a2016-02-19 15:18:14 -0800160 get_inventory $CONF
161
162 echo Processing board $BOARD
Matt DeVillier1dc1a562022-02-03 21:43:00 -0600163 eval $(grep -i $BOARD -A8 $CONF | grep '\(url=\|file=\)')
Joe Pillow9a4881a2016-02-19 15:18:14 -0800164 do_one_board $BOARD $url $file
165
166 rm "$CONF"
167else
168 echo "Usage: $0 <boardname>"
169 echo " $0 all"
170 echo
171 exit 1
172fi