util/chromeos/crosfirmware: Handle "broken" recovery images

Several recovery images for newer ChromeOS boards fail in
extract_partition() due to parted detecting that there are overlapping
partitions, and therefore failing to print the partition layout
(this is potentially a parted bug; requries further investigation).

To work around this, fall back to using fdisk, making the assumption
that ROOT-A is always partition #3, and calculate the partition
start and size using the sector size.

Test: successfully extract coreboot firmware images from recovery
images which previously failed to extract (fizz, octopus, volteer).

Change-Id: I03234170ba0544af9eb0879253f0a8e0e7bf33f5
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/61616
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
diff --git a/util/chromeos/crosfirmware.sh b/util/chromeos/crosfirmware.sh
index 92018e9..455e7b1 100755
--- a/util/chromeos/crosfirmware.sh
+++ b/util/chromeos/crosfirmware.sh
@@ -61,11 +61,26 @@
 	ROOTP=$( printf "unit\nB\nprint\nquit\n" | \
 		 parted $FILE 2>/dev/null | grep $NAME )
 
-	START=$(( $( echo $ROOTP | cut -f2 -d\ | tr -d "B" ) ))
-	SIZE=$(( $( echo $ROOTP | cut -f4 -d\ | tr -d "B" ) ))
+	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
+		count=$(( $SIZE / $_bs ))  > /dev/null 2>&1
 }
 
 extract_shellball()