# How MagiskBoot Unpacks and Repacks Android Boot Images with Multi-Format Compression Support

> Learn how MagiskBoot unpacks and repacks Android boot images. Discover its multi-format compression support including gzip, lz4, xz, and more with efficient Rust encoders.

- Repository: [John Wu/Magisk](https://github.com/topjohnwu/Magisk)
- Tags: internals
- Published: 2026-03-05

---

**MagiskBoot automatically detects compression formats by inspecting magic bytes and uses Rust-based streaming encoders/decoders to transparently handle gzip, lz4, lzma, xz, bzip2, and lzop during boot image extraction and reconstruction.**

The `magiskboot` binary serves as the core boot image manipulation engine in the topjohnwu/Magisk repository. Written primarily in Rust with a thin C++ shim interface, the tool processes raw Android and ChromeOS boot images to extract and reconstruct kernel, ramdisk, and device tree components regardless of their underlying compression scheme.

## Magic Byte Detection in bootimg.cpp

When reading a boot image or individual section, `magiskboot` identifies compression formats through the `check_fmt()` function defined in [[`native/src/boot/bootimg.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/boot/bootimg.cpp)](https://github.com/topjohnwu/Magisk/blob/master/native/src/boot/bootimg.cpp#L69-L102). This utility examines the first few bytes of the data buffer to recognize magic signatures for **gzip**, **lz4** (including legacy and LG variants), **lzma**, **xz**, **bzip2**, **lzop**, as well as raw Android/AOSP and ChromeOS boot image headers.

The detection mechanism maps these magic bytes to the `FileFormat` enum, enabling the rest of the pipeline to select appropriate handlers without user intervention.

## Streaming Decompression via compress.rs

Once a format is identified, the C++ helper `decompress()` forwards raw bytes to the Rust function `decompress_bytes()` implemented in [[`native/src/boot/compress.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/boot/compress.rs)](https://github.com/topjohnwu/Magisk/blob/master/native/src/boot/compress.rs#L90-L98). This function retrieves a streaming decoder via `get_decoder()`, which maps each `FileFormat` to its corresponding implementation—such as `GzDecoder`, `LZ4FrameDecoder`, or `XzDecoder`.

The architecture copies data directly to the output file descriptor in a streaming fashion, writing each component (kernel, ramdisk, dtb) in its original uncompressed form unless the user passes the `-n` flag to skip decompression entirely.

## Unpacking Boot Images with magiskboot unpack

When invoked as `magiskboot unpack <bootimg>`, the command-line driver in [[`native/src/boot/cli.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/boot/cli.rs)](https://github.com/topjohnwu/Magisk/blob/master/native/src/boot/cli.rs) parses the boot header using the `dyn_img_hdr` structure. The tool extracts each section according to offsets stored in the dynamic header and invokes `decompress()` for any compressed segments.

Files are written to the current directory with canonical names: `kernel`, `ramdisk.cpio`, `second`, `dtb`, and others. This standardization allows shell scripts like [`boot_patch.sh`](https://github.com/topjohnwu/Magisk/blob/main/boot_patch.sh) to locate and modify specific components predictably.

## Repacking and Compression Restoration

The `repack` command accepts the original boot image path to reuse its header metadata and size constraints. During reconstruction, `magiskboot` examines each component file in the working directory to determine if compression is required (unless `-n` is specified).

The Rust function `compress_bytes()` in [[`native/src/boot/compress.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/boot/compress.rs)](https://github.com/topjohnwu/Magisk/blob/master/native/src/boot/compress.rs#L79-L87) handles encoding via `get_encoder()`, selecting implementations like `GzEncoder`, `LZ4FrameEncoder`, or `XzEncoder` to stream data into the output file. The `dyn_img_hdr` struct tracks size changes, and the updated header is written to the final boot image (`new-boot.img` by default).

## Header Management and Architecture

The `dyn_img_hdr` struct in [[`bootimg.cpp`](https://github.com/topjohnwu/Magisk/blob/main/bootimg.cpp)](https://github.com/topjohnwu/Magisk/blob/master/native/src/boot/bootimg.cpp) encapsulates all boot image metadata including kernel size, ramdisk size, and version fields. During repack, `dyn_img_hdr::print()` and `dump_hdr_file()` generate a temporary `header` file for user editing. After all sections are processed, header values reflect the new compressed sizes.

The overall architecture separates concerns between a **C++ front-end** handling command-line parsing and file I/O, and a **Rust core library** implementing format detection and streaming compression. Shell wrappers like [`scripts/boot_patch.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/boot_patch.sh) orchestrate these binaries for installation workflows.

## Practical Command Examples

Unpack a boot image with automatic format detection:

```bash
./magiskboot unpack boot.img

# Generates: kernel, ramdisk.cpio, second, dtb, ...

```

Repack after modifying components:

```bash
./magiskboot repack boot.img

# Produces new-boot.img with compression types restored

```

Skip all compression handling to preserve raw blobs:

```bash
./magiskboot unpack -n boot.img
./magiskboot repack -n boot.img

```

Force specific compression for a component:

```bash
./magiskboot compress=xz ramdisk.cpio
./magiskboot repack boot.img

```

## Summary

- **Magic byte inspection** via `check_fmt()` in [`bootimg.cpp`](https://github.com/topjohnwu/Magisk/blob/main/bootimg.cpp) automatically identifies gzip, lz4, lzma, xz, bzip2, and lzop formats without user flags.
- **Streaming decompression** occurs through `decompress_bytes()` in [`compress.rs`](https://github.com/topjohnwu/Magisk/blob/main/compress.rs), mapping formats to Rust decoders like `GzDecoder` and `XzDecoder`.
- The **`magiskboot unpack`** command extracts components to canonical filenames using header offsets from `dyn_img_hdr`.
- **Repacking** reuses original headers and calls `compress_bytes()` to restore compression via `get_encoder()`, updating size metadata in the boot image header.
- A **hybrid C++/Rust architecture** separates CLI handling from core compression logic, exposed through FFI in [`lib.rs`](https://github.com/topjohnwu/Magisk/blob/main/lib.rs).

## Frequently Asked Questions

### What compression formats does MagiskBoot support?

MagiskBoot supports **gzip**, **lz4** (including legacy and LG variants), **lzma**, **xz**, **bzip2**, and **lzop**, as well as raw uncompressed data. The `check_fmt()` function in [`native/src/boot/bootimg.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/boot/bootimg.cpp) recognizes each format by inspecting magic bytes at the start of the data stream.

### How does MagiskBoot detect compression formats automatically?

The tool inspects the first few bytes of any section using `check_fmt()` to match against known magic numbers. This detection happens transparently during both unpacking and repacking, eliminating the need for users to specify format flags manually.

### Can I prevent MagiskBoot from decompressing files during unpack?

Yes. Passing the `-n` flag to the unpack command skips decompression entirely, preserving sections exactly as stored in the original image. This is useful when working with proprietary or non-standard compression schemes.

### How does repack preserve the original compression format?

During repack, `magiskboot` references the original boot image header to determine the previous compression state. It then uses `compress_bytes()` in [`compress.rs`](https://github.com/topjohnwu/Magisk/blob/main/compress.rs) to apply the appropriate encoder via `get_encoder()`, ensuring the reconstructed image matches the original format specification unless explicitly overridden.