summaryrefslogtreecommitdiff
path: root/lsinitramfs
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2014-09-27 19:09:53 +0100
committerBen Hutchings <ben@decadent.org.uk>2014-09-27 19:53:21 +0100
commitd5f4cd6c34ae573561fd615c7fc207942c599701 (patch)
treea4ff059eaccd16fbb2fbca19bb94b9f328dc7d5a /lsinitramfs
parentfdec1d37468d1b74b0ea4792599c5e7822d6c0e1 (diff)
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>
Diffstat (limited to 'lsinitramfs')
-rwxr-xr-xlsinitramfs51
1 files 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