If $BOARD is not all lowercase, then certain subfunctions of the
script will fail due to case-sensitive comparisons therein. To avoid
this, since all matched strings are fully lowercase, set $BOARD
to lowercase.
TEST: './crosfirmware.sh {akemi/Akemi/AKEMI}' all succeed.
Change-Id: I8ecb613a8d9384e2cccaff5183470e2e9956d0a2
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/82232
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Felix Singer <service+coreboot-gerrit@felixsinger.de>
		
	
		
			
				
	
	
		
			173 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env bash
 | |
| #
 | |
| # SPDX-License-Identifier: GPL-2.0-only
 | |
| 
 | |
| # On some systems, `parted` and `debugfs` are located in /sbin.
 | |
| export PATH="$PATH:/sbin"
 | |
| 
 | |
| exit_if_uninstalled() {
 | |
| 	local cmd_name="$1"
 | |
| 	local deb_pkg_name="$2"
 | |
| 
 | |
| 	if type "$cmd_name" >/dev/null 2>&1; then
 | |
| 		return
 | |
| 	fi
 | |
| 
 | |
| 	printf '`%s` was not found. ' "$cmd_name" >&2
 | |
| 	printf 'On Debian-based systems, it can be installed\n' >&2
 | |
| 	printf 'by running `apt install %s`.\n' "$deb_pkg_name" >&2
 | |
| 
 | |
| 	exit 1
 | |
| }
 | |
| 
 | |
| exit_if_dependencies_are_missing() {
 | |
| 	exit_if_uninstalled "uudecode" "sharutils"
 | |
| 	exit_if_uninstalled "debugfs" "e2fsprogs"
 | |
| 	exit_if_uninstalled "parted" "parted"
 | |
| 	exit_if_uninstalled "curl" "curl"
 | |
| 	exit_if_uninstalled "unzip" "unzip"
 | |
| }
 | |
| 
 | |
| get_inventory() {
 | |
| 	_conf=$1
 | |
| 	_url=https://dl.google.com/dl/edgedl/chromeos/recovery/recovery.conf
 | |
| 
 | |
| 	echo "Downloading recovery image inventory..."
 | |
| 
 | |
| 	curl -s "$_url" >$_conf
 | |
| }
 | |
| 
 | |
| download_image() {
 | |
| 	_url=$1
 | |
| 	_file=$2
 | |
| 
 | |
| 	echo "Downloading recovery image"
 | |
| 	curl "$_url" >"$_file.zip"
 | |
| 	echo "Decompressing recovery image"
 | |
| 	unzip -q "$_file.zip"
 | |
| 	rm "$_file.zip"
 | |
| }
 | |
| 
 | |
| extract_partition() {
 | |
| 	NAME=$1
 | |
| 	FILE=$2
 | |
| 	ROOTFS=$3
 | |
| 	_bs=1024
 | |
| 
 | |
| 	echo "Extracting ROOT-A partition"
 | |
| 	ROOTP=$(printf "unit\nB\nprint\nquit\n" |
 | |
| 		parted $FILE 2>/dev/null | grep $NAME)
 | |
| 
 | |
| 	if [ "$ROOTP" == "" ]; then
 | |
| 		# Automatic extraction failed, likely due to parted detecting
 | |
| 		# overlapping partitions. Fall back to using fdisk and assume
 | |
| 		# ROOT-A is partition #3
 | |
| 		echo "(Extracting via parted failed; falling back to fdisk)"
 | |
| 		_ssize=$(printf "p q" | fdisk $FILE | grep "Sector size" |
 | |
| 			cut -f2 -d: | cut -f2 -d ' ')
 | |
| 		_start=$(printf "p q" | fdisk $FILE | grep "bin3" | tr -s ' ' |
 | |
| 			cut -f2 -d ' ')
 | |
| 		_nsec=$(printf "p q" | fdisk $FILE | grep "bin3" | tr -s ' ' |
 | |
| 			cut -f4 -d ' ')
 | |
| 		START=$(($_ssize * $_start))
 | |
| 		SIZE=$(($_ssize * $_nsec))
 | |
| 	else
 | |
| 		START=$(($(echo $ROOTP | cut -f2 -d\  | tr -d "B")))
 | |
| 		SIZE=$(($(echo $ROOTP | cut -f4 -d\  | tr -d "B")))
 | |
| 	fi
 | |
| 
 | |
| 	dd if=$FILE of=$ROOTFS bs=$_bs skip=$(($START / $_bs)) \
 | |
| 		count=$(($SIZE / $_bs)) >/dev/null 2>&1
 | |
| }
 | |
| 
 | |
| extract_shellball() {
 | |
| 	ROOTFS=$1
 | |
| 	SHELLBALL=$2
 | |
| 
 | |
| 	echo "Extracting chromeos-firmwareupdate"
 | |
| 	printf "cd /usr/sbin\ndump chromeos-firmwareupdate $SHELLBALL\nquit" |
 | |
| 		debugfs $ROOTFS >/dev/null 2>&1
 | |
| }
 | |
| 
 | |
| extract_coreboot() {
 | |
| 	_shellball=$1
 | |
| 	_unpacked=$(mktemp -d)
 | |
| 
 | |
| 	echo "Extracting coreboot image"
 | |
| 	if ! sh $_shellball --unpack $_unpacked >/dev/null 2>&1; then
 | |
| 		sh $_shellball --sb_extract $_unpacked >/dev/null 2>&1
 | |
| 	fi
 | |
| 
 | |
| 	if [ -d $_unpacked/models/ ]; then
 | |
| 		_version=$(cat $_unpacked/VERSION | grep -m 1 -e Model.*$_board -A5 |
 | |
| 			grep "BIOS (RW) version:" | cut -f2 -d: | tr -d \ )
 | |
| 		if [ "$_version" == "" ]; then
 | |
| 			_version=$(cat $_unpacked/VERSION | grep -m 1 -e Model.*$_board -A5 |
 | |
| 				grep "BIOS version:" | cut -f2 -d: | tr -d \ )
 | |
| 		fi
 | |
| 		_bios_image=$(grep "IMAGE_MAIN" $_unpacked/models/$_board/setvars.sh |
 | |
| 			cut -f2 -d\")
 | |
| 	else
 | |
| 		_version=$(cat $_unpacked/VERSION | grep BIOS\ version: |
 | |
| 			cut -f2 -d: | tr -d \ )
 | |
| 		_bios_image=bios.bin
 | |
| 	fi
 | |
| 	if cp $_unpacked/$_bios_image coreboot-$_version.bin; then
 | |
| 		echo "Extracted coreboot-$_version.bin"
 | |
| 	fi
 | |
| 	rm -rf "$_unpacked"
 | |
| 	rm $_shellball
 | |
| }
 | |
| 
 | |
| do_one_board() {
 | |
| 	_board=$1
 | |
| 	_url=$2
 | |
| 	_file=$3
 | |
| 
 | |
| 	download_image $_url $_file
 | |
| 
 | |
| 	extract_partition ROOT-A $_file root-a.ext2
 | |
| 	extract_shellball root-a.ext2 chromeos-firmwareupdate-$_board
 | |
| 	rm $_file root-a.ext2
 | |
| 
 | |
| 	extract_coreboot chromeos-firmwareupdate-$_board
 | |
| }
 | |
| 
 | |
| #
 | |
| # Main
 | |
| #
 | |
| 
 | |
| BOARD=${1,,}
 | |
| 
 | |
| exit_if_dependencies_are_missing
 | |
| 
 | |
| if [ "$BOARD" == "all" ]; then
 | |
| 	CONF=$(mktemp)
 | |
| 	get_inventory $CONF
 | |
| 
 | |
| 	grep ^name= $CONF | while read _line; do
 | |
| 		name=$(echo $_line | cut -f2 -d=)
 | |
| 		echo Processing board $name
 | |
| 		eval $(grep -v hwid= $CONF | grep -A11 "$_line" |
 | |
| 			grep '\(url=\|file=\)')
 | |
| 		BOARD=$(echo $url | cut -f3 -d_)
 | |
| 		do_one_board $BOARD $url $file
 | |
| 	done
 | |
| 
 | |
| 	rm "$CONF"
 | |
| elif [ "$BOARD" != "" ]; then
 | |
| 	CONF=$(mktemp)
 | |
| 	get_inventory $CONF
 | |
| 
 | |
| 	echo Processing board $BOARD
 | |
| 	eval $(grep -i $BOARD -A8 $CONF | grep '\(url=\|file=\)')
 | |
| 	do_one_board $BOARD $url $file
 | |
| 
 | |
| 	rm "$CONF"
 | |
| else
 | |
| 	echo "Usage: $0 <boardname>"
 | |
| 	echo "       $0 all"
 | |
| 	echo
 | |
| 	exit 1
 | |
| fi
 |