Utilize libflate crate to compress and decompress payload

This commit is contained in:
azongchang
2024-07-20 12:12:46 +00:00
committed by Tate, Hongliang Tian
parent 930b0d208d
commit 6752baf166
15 changed files with 321 additions and 37 deletions

View File

@ -11,5 +11,6 @@ repository = "https://github.com/asterinas/asterinas"
[dependencies]
bytemuck = { version = "1.14.0", features = ["derive"] }
bitflags = "1.3"
libflate = "2.1.0"
serde = { version = "1.0.192", features = ["derive"] }
xmas-elf = "0.9.1"

View File

@ -0,0 +1,65 @@
// SPDX-License-Identifier: MPL-2.0
//! This module is used to compress kernel ELF.
use std::{
ffi::{OsStr, OsString},
io::Write,
str::FromStr,
};
use libflate::{gzip, zlib};
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum PayloadEncoding {
#[default]
#[serde(rename = "raw")]
Raw,
#[serde(rename = "gzip")]
Gzip,
#[serde(rename = "zlib")]
Zlib,
}
impl FromStr for PayloadEncoding {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"raw" => Ok(Self::Raw),
"gzip" => Ok(Self::Gzip),
"zlib" => Ok(Self::Zlib),
_ => Err(format!("Invalid encoding format: {}", s)),
}
}
}
impl From<OsString> for PayloadEncoding {
fn from(os_string: OsString) -> Self {
PayloadEncoding::from_str(&os_string.to_string_lossy()).unwrap()
}
}
impl From<&OsStr> for PayloadEncoding {
fn from(os_str: &OsStr) -> Self {
PayloadEncoding::from_str(&os_str.to_string_lossy()).unwrap()
}
}
/// Encoding the kernel ELF using the provided format.
pub fn encode_kernel(kernel: Vec<u8>, encoding: PayloadEncoding) -> Vec<u8> {
match encoding {
PayloadEncoding::Raw => kernel,
PayloadEncoding::Gzip => {
let mut encoder = gzip::Encoder::new(Vec::new()).unwrap();
encoder.write_all(&kernel).unwrap();
encoder.finish().into_result().unwrap()
}
PayloadEncoding::Zlib => {
let mut encoder = zlib::Encoder::new(Vec::new()).unwrap();
encoder.write_all(&kernel).unwrap();
encoder.finish().into_result().unwrap()
}
}
}

View File

@ -13,6 +13,7 @@
//! The setup code should be built into the ELF target and we convert it to a flat binary
//! in the builder.
pub mod encoder;
mod mapping;
mod pe_header;
@ -22,6 +23,8 @@ use std::{
path::Path,
};
use encoder::encode_kernel;
pub use encoder::PayloadEncoding;
use mapping::{SetupFileOffset, SetupVA};
use xmas_elf::program::SegmentData;
@ -39,13 +42,15 @@ pub enum BzImageType {
/// - `target_image_path`: The path to the target bzImage;
/// - `image_type`: The type of the bzImage that we are building;
/// - `kernel_path`: The path to the kernel ELF;
/// - `setup_elf_path`: The path to the setup ELF.
/// - `setup_elf_path`: The path to the setup ELF;
/// - `encoding`: The encoding format for compressing the kernel ELF.
///
pub fn make_bzimage(
target_image_path: &Path,
image_type: BzImageType,
kernel_path: &Path,
setup_elf_path: &Path,
encoding: PayloadEncoding,
) {
let mut setup_elf = Vec::new();
File::open(setup_elf_path)
@ -61,7 +66,10 @@ pub fn make_bzimage(
.unwrap()
.read_to_end(&mut kernel)
.unwrap();
let payload = kernel;
let payload = match image_type {
BzImageType::Legacy32 => kernel,
BzImageType::Efi64 => encode_kernel(kernel, encoding),
};
let setup_len = setup.len();
let payload_len = payload.len();