[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH v2 initramfs-tools 2/3] lsinitramfs: Parse and list files that include early microcode



Look for uncompressed cpio headers and padding at the start of the
initramfs image.  If present, pass the initramfs directly to cpio
and then try to decompress a second cpio archive after the padding.

Closes: #717805
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Thanks: Brett Parker <iDunno@sommitrealweird.co.uk>
Thanks: Olivier Berger <olivier.berger@telecom-sudparis.eu>
---
v2: Redirect dd's stderr to /dev/null because 'dd status=none' doesn't
    work in wheezy

 lsinitramfs | 51 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 47 insertions(+), 4 deletions(-)

diff --git a/lsinitramfs b/lsinitramfs
index db179ca..b1eef7b 100755
--- a/lsinitramfs
+++ b/lsinitramfs
@@ -51,19 +51,62 @@ listarchive()
 		bzip2 -c -d "${archive}" | cpio ${cpio_args}
 	elif lzop -t "${archive}" >/dev/null 2>&1 ; then
 		lzop -c -d "${archive}" | cpio ${cpio_args}
-	elif file "$initramfs" 2>/dev/null | grep -q "cpio archive" ; then
-		echo "lsinitramfs does not yet support cpio archive initramfs files." >&2
-		echo "See http://bugs.debian.org/717805 for more information." >&2
 	fi
 }
 
+# Read bytes out of a file, checking that they are valid hex digits
+readhex()
+{
+	dd < "$1" bs=1 skip="$2" count="$3" 2> /dev/null | \
+		LANG=C grep -E "^[0-9A-Fa-f]{$3}\$"
+}
+
+# Check for a zero byte in a file
+checkzero()
+{
+	dd < "$1" bs=1 skip="$2" count=1 2> /dev/null | \
+		LANG=C grep -q -z '^$'
+}
+
 for initramfs in "$@" ; do
 	if ! [ -r "${initramfs}" ] ; then
 		echo "Specified file could not be read." >&2
 		exit 1
 	else
 		echo "${initramfs}"
-		listarchive "${initramfs}"
+
+		# There may be a prepended uncompressed archive.  cpio
+		# won't tell us the true size of this so we have to
+		# parse the headers and padding ourselves.  This is
+		# very roughly based on linux/lib/earlycpio.c
+		offset=0
+		while true; do
+			if checkzero "$initramfs" $offset; then
+				offset=$((offset + 4))
+				continue
+			fi
+			magic="$(readhex "$initramfs" $offset 6)" || break
+			test $magic = 070701 || test $magic = 070702 || break
+			namesize=0x$(readhex "$initramfs" $((offset + 94)) 8)
+			filesize=0x$(readhex "$initramfs" $((offset + 54)) 8)
+			offset=$(((offset + 110)))
+			offset=$(((offset + $namesize + 3) & ~3))
+			offset=$(((offset + $filesize + 3) & ~3))
+		done
+
+		if [ $offset -ne 0 ]; then
+			# List uncompressed archive
+			cpio ${cpio_args} < "$initramfs"
+
+			# List main archive
+			subarchive=$(mktemp ${TMPDIR:-/var/tmp}/lsinitramfs_XXXXXX)
+			trap "rm -f $subarchive" EXIT
+			dd < "$initramfs" bs="$offset" skip=1 2> /dev/null \
+				> $subarchive
+			listarchive $subarchive
+		else
+			listarchive "${initramfs}"
+		fi
 
 	fi
 done

-- 
Ben Hutchings
The two most common things in the universe are hydrogen and stupidity.

Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: