efipack — self-extracting EFI
github.com/go-coff/efipack is a pure-Go library that compresses PE32+/EFI
binaries into a self-extracting PE32+/EFI image — the UPX-equivalent that
does not otherwise exist for this format. It was designed to mitigate the EDK2
OVMF amd64 CpuPageTableLib #GP that fires on LoadImage / StartImage of
sufficiently large EFI binaries (cloud-boot M6.2 milestone).
go get github.com/go-coff/efipack
Host side only (as of this revision)
This revision ships the host side: it compresses an input and assembles
the self-extracting envelope, but the emitted .stub section still carries
a TODO_STUB placeholder — the output is not yet a runnable EFI. The
per-arch runtime decompressor stub, the pectl pack integration and the
cross-arch boot-smoke matrix land in later PRs.
API surface
import "github.com/go-coff/efipack"
// Detect the architecture of an input PE32+ from its COFF header.
arch, err := efipack.InferArch(peBytes)
// arch ∈ {AmdArch, ArmArch, RiscvArch, LoongArch}
in, _ := os.Open("BOOTX64.EFI")
out, _ := os.Create("BOOTX64-packed.EFI")
res, err := efipack.Pack(in, out, efipack.Options{
Compressor: efipack.Flate, // default; zero stub cost
Level: 0, // 0 → codec default
})
// res.OriginalSize, res.CompressedSize, res.PackedSize, res.Arch, res.Compressor
| Type / constant | Purpose |
|---|---|
Pack(in, out, opts) (PackResult, error) |
host-side compress + envelope |
Options{Compressor, Level} |
knobs; zero value = Flate at default level |
PackResult{OriginalSize, CompressedSize, PackedSize, Compressor, Arch} |
summary |
Compressor (Flate / LZFSE / LZ4) |
algorithm switch |
Arch (AmdArch / ArmArch / RiscvArch / LoongArch) |
PE machine |
InferArch(pe) (Arch, error) |
read COFF.Machine without debug/pe (works on loong64) |
ReadPayload(pe) (algo, uncompressedSize, body, err) |
inverse of Pack's envelope |
ErrCompressorNotImplemented |
sentinel for codecs not yet wired (LZ4) |
The envelope is a standard PE32+/EFI structure: DOS stub + PE signature + COFF +
optional header + section table + a .stub placeholder + a .payload body.
.payload wire format
PE/COFF — and this envelope — are little-endian:
.payload section body:
magic [4]byte "CBP0" — cloud-boot pack v0
algo [4]byte "FLAT" | "LZFS" | "LZ4 "
uncompressed uint64 little-endian — host-input size in bytes
compressed uint64 little-endian — body size in bytes
body [N]byte exactly N=compressed bytes; codec-specific stream
The (future) runtime stub reads this header, allocates exactly the right number
of EfiBootServicesCode pages, decompresses, then chain-loads via
gBS->LoadImage + gBS->StartImage.
Why Flate as the default?
Cloud-boot binaries already link compress/gzip, so a Flate-based stub adds
zero bytes versus LZFSE's ~100–200 KiB cost. The ~1-point raw-ratio gap
(LZFSE 40.13 % vs Flate 39.11 %) is negligible against the multi-MiB binaries
being compressed. Flate is therefore the zero-value default; LZFSE is
host-side only and LZ4 is reserved.
Licensed BSD-3-Clause.