From 2c39d0234d8257382e98d54c4c2f93716b86429c Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 21 Aug 2025 10:55:55 -0700 Subject: [PATCH] Fix compression format detection --- native/src/boot/bootimg.cpp | 18 +++++++++--------- native/src/boot/cli.rs | 2 -- native/src/boot/format.hpp | 3 --- native/src/boot/format.rs | 24 ++++++++++++++++-------- native/src/boot/lib.rs | 8 +++++--- 5 files changed, 30 insertions(+), 25 deletions(-) diff --git a/native/src/boot/bootimg.cpp b/native/src/boot/bootimg.cpp index d993b398c..6ee91e6bb 100644 --- a/native/src/boot/bootimg.cpp +++ b/native/src/boot/bootimg.cpp @@ -588,7 +588,7 @@ int split_image_dtb(rust::Utf8CStr filename, bool skip_decomp) { if (size_t off = find_dtb_offset(img.buf(), img.sz()); off > 0) { FileFormat fmt = check_fmt_lg(img.buf(), img.sz()); - if (!skip_decomp && COMPRESSED(fmt)) { + if (!skip_decomp && fmt_compressed(fmt)) { int fd = creat(KERNEL_FILE, 0644); decompress(fmt, fd, img.buf(), off); close(fd); @@ -610,7 +610,7 @@ int unpack(rust::Utf8CStr image, bool skip_decomp, bool hdr) { boot.hdr->dump_hdr_file(); // Dump kernel - if (!skip_decomp && COMPRESSED(boot.k_fmt)) { + if (!skip_decomp && fmt_compressed(boot.k_fmt)) { if (boot.hdr->kernel_size() != 0) { int fd = creat(KERNEL_FILE, 0644); decompress(boot.k_fmt, fd, boot.kernel, boot.hdr->kernel_size()); @@ -641,13 +641,13 @@ int unpack(rust::Utf8CStr image, bool skip_decomp, bool hdr) { } owned_fd fd = xopenat(dirfd, file_name, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644); FileFormat fmt = check_fmt_lg(boot.ramdisk + it.ramdisk_offset, it.ramdisk_size); - if (!skip_decomp && COMPRESSED(fmt)) { + if (!skip_decomp && fmt_compressed(fmt)) { decompress(fmt, fd, boot.ramdisk + it.ramdisk_offset, it.ramdisk_size); } else { xwrite(fd, boot.ramdisk + it.ramdisk_offset, it.ramdisk_size); } } - } else if (!skip_decomp && COMPRESSED(boot.r_fmt)) { + } else if (!skip_decomp && fmt_compressed(boot.r_fmt)) { if (boot.hdr->ramdisk_size() != 0) { int fd = creat(RAMDISK_FILE, 0644); decompress(boot.r_fmt, fd, boot.ramdisk, boot.hdr->ramdisk_size()); @@ -661,7 +661,7 @@ int unpack(rust::Utf8CStr image, bool skip_decomp, bool hdr) { dump(boot.second, boot.hdr->second_size(), SECOND_FILE); // Dump extra - if (!skip_decomp && COMPRESSED(boot.e_fmt)) { + if (!skip_decomp && fmt_compressed(boot.e_fmt)) { if (boot.hdr->extra_size() != 0) { int fd = creat(EXTRA_FILE, 0644); decompress(boot.e_fmt, fd, boot.extra, boot.hdr->extra_size()); @@ -748,7 +748,7 @@ void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp) { } if (access(KERNEL_FILE, R_OK) == 0) { mmap_data m(KERNEL_FILE); - if (!skip_comp && !COMPRESSED_ANY(check_fmt(m.buf(), m.sz())) && COMPRESSED(boot.k_fmt)) { + if (!skip_comp && !fmt_compressed_any(check_fmt(m.buf(), m.sz())) && fmt_compressed(boot.k_fmt)) { // Always use zopfli for zImage compression auto fmt = (boot.flags[ZIMAGE_KERNEL] && boot.k_fmt == FileFormat::GZIP) ? FileFormat::ZOPFLI : boot.k_fmt; hdr->kernel_size() = compress_len(fmt, m, fd); @@ -816,7 +816,7 @@ void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp) { mmap_data m(dirfd, file_name); FileFormat fmt = check_fmt_lg(boot.ramdisk + it.ramdisk_offset, it.ramdisk_size); it.ramdisk_offset = ramdisk_offset; - if (!skip_comp && !COMPRESSED_ANY(check_fmt(m.buf(), m.sz())) && COMPRESSED(fmt)) { + if (!skip_comp && !fmt_compressed_any(check_fmt(m.buf(), m.sz())) && fmt_compressed(fmt)) { it.ramdisk_size = compress_len(fmt, m, fd); } else { it.ramdisk_size = xwrite(fd, m.buf(), m.sz()); @@ -836,7 +836,7 @@ void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp) { fprintf(stderr, "RAMDISK_FMT: [%s] -> [%s]\n", fmt2name(r_fmt), fmt2name(FileFormat::LZ4_LEGACY)); r_fmt = FileFormat::LZ4_LEGACY; } - if (!skip_comp && !COMPRESSED_ANY(check_fmt(m.buf(), m.sz())) && COMPRESSED(r_fmt)) { + if (!skip_comp && !fmt_compressed_any(check_fmt(m.buf(), m.sz())) && fmt_compressed(r_fmt)) { hdr->ramdisk_size() = compress_len(r_fmt, m, fd); } else { hdr->ramdisk_size() = xwrite(fd, m.buf(), m.sz()); @@ -855,7 +855,7 @@ void repack(rust::Utf8CStr src_img, rust::Utf8CStr out_img, bool skip_comp) { off.extra = lseek(fd, 0, SEEK_CUR); if (access(EXTRA_FILE, R_OK) == 0) { mmap_data m(EXTRA_FILE); - if (!skip_comp && !COMPRESSED_ANY(check_fmt(m.buf(), m.sz())) && COMPRESSED(boot.e_fmt)) { + if (!skip_comp && !fmt_compressed_any(check_fmt(m.buf(), m.sz())) && fmt_compressed(boot.e_fmt)) { hdr->extra_size() = compress_len(boot.e_fmt, m, fd); } else { hdr->extra_size() = xwrite(fd, m.buf(), m.sz()); diff --git a/native/src/boot/cli.rs b/native/src/boot/cli.rs index 30688f50b..5f4723468 100644 --- a/native/src/boot/cli.rs +++ b/native/src/boot/cli.rs @@ -243,7 +243,6 @@ Supported actions: If [outfile] is not specified, then will be replaced with another file suffixed with a matching file extension. Supported formats: - {1} decompress [outfile] @@ -252,7 +251,6 @@ Supported actions: If [outfile] is not specified, then will be replaced with another file removing its archive format file extension. Supported formats: - {1} "#, cmd, diff --git a/native/src/boot/format.hpp b/native/src/boot/format.hpp index 65eb178b8..7e23b4093 100644 --- a/native/src/boot/format.hpp +++ b/native/src/boot/format.hpp @@ -2,9 +2,6 @@ enum class FileFormat : ::std::uint8_t; -#define COMPRESSED(fmt) ((+fmt) >= +FileFormat::GZIP && (+fmt) < +FileFormat::LZOP) -#define COMPRESSED_ANY(fmt) ((+fmt) >= +FileFormat::GZIP && (+fmt) <= +FileFormat::LZOP) - #define BUFFER_MATCH(buf, s) (memcmp(buf, s, sizeof(s) - 1) == 0) #define BUFFER_CONTAIN(buf, sz, s) (memmem(buf, sz, s, sizeof(s) - 1) != nullptr) #define CHECKED_MATCH(s) (len >= (sizeof(s) - 1) && BUFFER_MATCH(buf, s)) diff --git a/native/src/boot/format.rs b/native/src/boot/format.rs index 520459a3d..ea8eba03a 100644 --- a/native/src/boot/format.rs +++ b/native/src/boot/format.rs @@ -23,12 +23,12 @@ impl FromStr for FileFormat { impl Display for FileFormat { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str(self.to_cstr()) + f.write_str(self.as_cstr()) } } impl FileFormat { - fn to_cstr(&self) -> &'static Utf8CStr { + fn as_cstr(&self) -> &'static Utf8CStr { match *self { Self::GZIP => cstr!("gzip"), Self::ZOPFLI => cstr!("zopfli"), @@ -46,10 +46,6 @@ impl FileFormat { } } -pub fn fmt2name(fmt: FileFormat) -> *const libc::c_char { - fmt.to_cstr().as_ptr() -} - impl FileFormat { pub fn ext(&self) -> &'static str { match *self { @@ -68,7 +64,6 @@ impl FileFormat { *self, Self::GZIP | Self::ZOPFLI - | Self::LZOP | Self::XZ | Self::LZMA | Self::BZIP2 @@ -88,9 +83,22 @@ impl FileFormat { Self::LZ4, Self::LZ4_LEGACY, Self::LZ4_LG, - Self::LZOP, ] .map(|f| f.to_string()) .join(" ") } } + +// C++ FFI + +pub fn fmt2name(fmt: FileFormat) -> *const libc::c_char { + fmt.as_cstr().as_ptr() +} + +pub fn fmt_compressed(fmt: FileFormat) -> bool { + fmt.is_compressed() +} + +pub fn fmt_compressed_any(fmt: FileFormat) -> bool { + fmt.is_compressed() || matches!(fmt, FileFormat::LZOP) +} diff --git a/native/src/boot/lib.rs b/native/src/boot/lib.rs index 82b67f6ce..1385bfde5 100644 --- a/native/src/boot/lib.rs +++ b/native/src/boot/lib.rs @@ -5,18 +5,18 @@ pub use base; use compress::{compress_bytes, decompress_bytes}; -use format::fmt2name; +use format::{fmt_compressed, fmt_compressed_any, fmt2name}; use sign::{SHA, get_sha, sha256_hash, sign_payload_for_cxx}; use std::env; +mod cli; mod compress; mod cpio; mod dtb; +mod format; mod patch; mod payload; // Suppress warnings in generated code -mod cli; -mod format; #[allow(warnings)] mod proto; mod sign; @@ -78,6 +78,8 @@ pub mod ffi { fn compress_bytes(format: FileFormat, in_bytes: &[u8], out_fd: i32); fn decompress_bytes(format: FileFormat, in_bytes: &[u8], out_fd: i32); fn fmt2name(fmt: FileFormat) -> *const c_char; + fn fmt_compressed(fmt: FileFormat) -> bool; + fn fmt_compressed_any(fmt: FileFormat) -> bool; #[cxx_name = "sign_payload"] fn sign_payload_for_cxx(payload: &[u8]) -> Vec;