summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2018-07-18 05:25:13 +0100
committerBen Hutchings <ben@decadent.org.uk>2018-07-18 05:50:17 +0100
commit28536f665ccbef9a76d775fde557d0902426df49 (patch)
tree369201bac0aa52fbe877a96da52eb66b063b5a84
parent211e0507a80c2ede3bfbc78fa222be363561fe85 (diff)
unmkinitramfs, lsinitramfs: Split multiple early initramfs sections
It is possible for the early initramfs to consist of multiple sections, each a valid uncompressed cpio archive, for example if amd64-microcode and intel-microcode are both installed and explicitly enabled. Each cpio archive ends with an EOF marker consisting of four zero bytes and possibly additional zero padding. The kernel's early microcode loader simply skips the zero bytes, but cpio will stop. So whenever we find such a group of zero bytes, we need to stop parsing cpio headers, run cpio over what we found, and then repeat the process on the following bytes. Closes: #886424 Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
-rwxr-xr-xunmkinitramfs68
1 files changed, 45 insertions, 23 deletions
diff --git a/unmkinitramfs b/unmkinitramfs
index 7e3d977..bd7bacf 100755
--- a/unmkinitramfs
+++ b/unmkinitramfs
@@ -55,42 +55,64 @@ splitinitramfs()
dir="$2"
shift 2
- # 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
+ count=0
+ start=0
while true; do
- if checkzero "$initramfs" $offset; then
- offset=$((offset + 4))
- continue
+ # There may be prepended uncompressed archives. cpio
+ # won't tell us the true size of these so we have to
+ # parse the headers and padding ourselves. This is
+ # very roughly based on linux/lib/earlycpio.c
+ end=$start
+ while true; do
+ if checkzero "$initramfs" $end; then
+ # This is the EOF marker. There might
+ # be more zero padding before the next
+ # archive, so read through all of it.
+ end=$((end + 4))
+ while checkzero "$initramfs" $end; do
+ end=$((end + 4))
+ done
+ break
+ fi
+ magic="$(readhex "$initramfs" $end 6)" || break
+ test $magic = 070701 || test $magic = 070702 || break
+ namesize=0x$(readhex "$initramfs" $((end + 94)) 8)
+ filesize=0x$(readhex "$initramfs" $((end + 54)) 8)
+ end=$(((end + 110)))
+ end=$(((end + $namesize + 3) & ~3))
+ end=$(((end + $filesize + 3) & ~3))
+ done
+ if [ $end -eq $start ]; then
+ break
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
- # uncompressed archive
+ # Extract to early, early2, ... subdirectories
+ count=$((count + 1))
+ if [ $count -eq 1 ]; then
+ subdir=early
+ else
+ subdir=early$count
+ fi
+ dd < "$initramfs" skip=$start count=$((end - start)) iflag=skip_bytes 2> /dev/null |
(
if [ -n "$dir" ]; then
- mkdir -p -- "$dir/early"
- cd -- "$dir/early"
+ mkdir -p -- "$dir/$subdir"
+ cd -- "$dir/$subdir"
fi
cpio -i "$@"
- ) < "$initramfs"
+ )
+ start=$end
+ done
- # main archive
+ if [ $end -gt 0 ]; then
+ # Extract to main subdirectory
subarchive=$(mktemp ${TMPDIR:-/var/tmp}/unmkinitramfs_XXXXXX)
trap "rm -f '$subarchive'" EXIT
- dd < "$initramfs" bs="$offset" skip=1 2> /dev/null \
+ dd < "$initramfs" skip=$end iflag=skip_bytes 2> /dev/null \
> $subarchive
xcpio "$subarchive" "${dir:+$dir/main}" -i "$@"
else
+ # Don't use subdirectories (for backward compatibility)
xcpio "$initramfs" "$dir" -i "$@"
fi
}