diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2014-09-27 19:09:53 +0100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2014-09-27 19:53:21 +0100 |
commit | d5f4cd6c34ae573561fd615c7fc207942c599701 (patch) | |
tree | a4ff059eaccd16fbb2fbca19bb94b9f328dc7d5a /lsinitramfs | |
parent | fdec1d37468d1b74b0ea4792599c5e7822d6c0e1 (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-x | lsinitramfs | 51 |
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 |