diff --git a/Makefile b/Makefile index 6616579e..fd8d9b5e 100644 --- a/Makefile +++ b/Makefile @@ -112,6 +112,12 @@ ifeq ($(ENABLE_KVM), 1) CARGO_OSDK_ARGS += --qemu-args="-accel kvm" endif +# Skip GZIP to make encoding and decoding of initramfs faster +ifeq ($(INITRAMFS_SKIP_GZIP),1) +CARGO_OSDK_INITRAMFS_OPTION := --initramfs=$(realpath test/build/initramfs.cpio) +CARGO_OSDK_ARGS += $(CARGO_OSDK_INITRAMFS_OPTION) +endif + # Pass make variables to all subdirectory makes export @@ -243,7 +249,7 @@ ktest: initramfs $(CARGO_OSDK) @# Exclude linux-bzimage-setup from ktest since it's hard to be unit tested @for dir in $(OSDK_CRATES); do \ [ $$dir = "ostd/libs/linux-bzimage/setup" ] && continue; \ - (cd $$dir && OVMF=off cargo osdk test) || exit 1; \ + (cd $$dir && OVMF=off cargo osdk test $(CARGO_OSDK_INITRAMFS_OPTION)) || exit 1; \ tail --lines 10 qemu.log | grep -q "^\\[ktest runner\\] All crates tested." \ || (echo "Test failed" && exit 1); \ done diff --git a/kernel/src/fs/rootfs.rs b/kernel/src/fs/rootfs.rs index 66a02a27..030a6e0c 100644 --- a/kernel/src/fs/rootfs.rs +++ b/kernel/src/fs/rootfs.rs @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 +use core2::io::{Cursor, Read}; use cpio_decoder::{CpioDecoder, FileType}; use lending_iterator::LendingIterator; use libflate::gzip::Decoder as GZipDecoder; @@ -14,17 +15,47 @@ use super::{ }; use crate::{fs::path::is_dot, prelude::*}; +struct BoxedReader<'a>(Box); + +impl<'a> BoxedReader<'a> { + pub fn new(reader: Box) -> Self { + BoxedReader(reader) + } +} + +impl Read for BoxedReader<'_> { + fn read(&mut self, buf: &mut [u8]) -> core2::io::Result { + self.0.read(buf) + } +} + /// Unpack and prepare the rootfs from the initramfs CPIO buffer. pub fn init(initramfs_buf: &[u8]) -> Result<()> { init_root_mount(); procfs::init(); - println!("[kernel] unpacking the initramfs.cpio.gz to rootfs ..."); + let reader = { + let mut initramfs_suffix = ""; + let reader = match &initramfs_buf[..4] { + // Gzip magic number: 0x1F 0x8B + &[0x1F, 0x8B, _, _] => { + initramfs_suffix = ".gz"; + let gzip_decoder = GZipDecoder::new(initramfs_buf) + .map_err(|_| Error::with_message(Errno::EINVAL, "invalid gzip buffer"))?; + BoxedReader::new(Box::new(gzip_decoder)) + } + _ => BoxedReader::new(Box::new(Cursor::new(initramfs_buf))), + }; + + println!( + "[kernel] unpacking the initramfs.cpio{} to rootfs ...", + initramfs_suffix + ); + + reader + }; + let mut decoder = CpioDecoder::new(reader); let fs = FsResolver::new(); - let mut decoder = CpioDecoder::new( - GZipDecoder::new(initramfs_buf) - .map_err(|_| Error::with_message(Errno::EINVAL, "invalid gzip buffer"))?, - ); loop { let Some(entry_result) = decoder.next() else { diff --git a/test/Makefile b/test/Makefile index 493c23f8..5c9a5538 100644 --- a/test/Makefile +++ b/test/Makefile @@ -9,7 +9,12 @@ ATOMIC_WGET := $(CUR_DIR)/../tools/atomic_wget.sh BUILD_DIR := $(CUR_DIR)/build INITRAMFS := $(BUILD_DIR)/initramfs INITRAMFS_FILELIST := $(BUILD_DIR)/initramfs.filelist +INITRAMFS_SKIP_GZIP ?= 0 +ifeq ($(INITRAMFS_SKIP_GZIP),1) +INITRAMFS_IMAGE := $(BUILD_DIR)/initramfs.cpio +else INITRAMFS_IMAGE := $(BUILD_DIR)/initramfs.cpio.gz +endif EXT2_IMAGE := $(BUILD_DIR)/ext2.img EXFAT_IMAGE := $(BUILD_DIR)/exfat.img INITRAMFS_EMPTY_DIRS := \ @@ -107,7 +112,7 @@ $(INITRAMFS)/usr/local: .PHONY: $(INITRAMFS)/test $(INITRAMFS)/test: - @make --no-print-directory -C apps + @$(MAKE) --no-print-directory -C apps $(INITRAMFS)/benchmark: | $(INITRAMFS)/benchmark/bin @cp -rf $(CUR_DIR)/benchmark/* $@ @@ -134,11 +139,11 @@ $(INITRAMFS_EMPTY_DIRS): .PHONY: $(SYSCALL_TEST_DIR) $(SYSCALL_TEST_DIR): - @make --no-print-directory -C syscall_test + @$(MAKE) --no-print-directory -C syscall_test .PHONY: $(INITRAMFS_IMAGE) $(INITRAMFS_IMAGE): $(INITRAMFS_FILELIST) - @if ! cmp -s $(INITRAMFS_FILELIST) $(INITRAMFS_FILELIST).previous ; then \ + @if ! cmp -s $(INITRAMFS_FILELIST) $(INITRAMFS_FILELIST).previous || ! test -f $@; then \ echo "Generating the initramfs image..."; \ cp -f $(INITRAMFS_FILELIST) $(INITRAMFS_FILELIST).previous; \ ( \ @@ -148,7 +153,12 @@ $(INITRAMFS_IMAGE): $(INITRAMFS_FILELIST) # `$(INITRAMFS)` in the second column. This prunes the first \ # column and passes the second column to `cpio`. \ cut -d " " -f 2- $(INITRAMFS_FILELIST) | \ - cpio -o -H newc | gzip \ + cpio -o -H newc | \ + if [ "$(INITRAMFS_SKIP_GZIP)" != 1 ]; then \ + gzip; \ + else \ + cat; \ + fi \ ) > $@; \ fi @@ -175,11 +185,11 @@ build: $(INITRAMFS_IMAGE) $(EXT2_IMAGE) $(EXFAT_IMAGE) .PHONY: format format: - @make --no-print-directory -C apps format + @$(MAKE) --no-print-directory -C apps format .PHONY: check check: - @make --no-print-directory -C apps check + @$(MAKE) --no-print-directory -C apps check .PHONY: clean clean: