Skip to content

Commit e983c6a

Browse files
bjzhjingrbradford
authored andcommitted
loader: Define a kernel loader trait
Convert the ELF loader to it, the bzImage support will also implement that trait. Having a trait allows us to support further kernel image formats in a common way. Signed-off-by: Cathy Zhang <cathy.zhang@intel.com>
1 parent 49da615 commit e983c6a

File tree

1 file changed

+58
-30
lines changed

1 file changed

+58
-30
lines changed

src/loader/mod.rs

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,29 @@ impl Display for Error {
8181
}
8282
}
8383

84-
pub struct ElfLoader;
84+
/// * `kernel_load` - The actual `guest_mem` address where kernel image is loaded start.
85+
/// * `kernel_end` - The offset of `guest_mem` where kernel image load is loaded finish, return
86+
/// in case of loading initrd adjacent to kernel image.
87+
#[derive(Debug, Default, Copy, Clone, PartialEq)]
88+
pub struct KernelLoaderResult {
89+
pub kernel_load: GuestAddress,
90+
pub kernel_end: GuestUsize,
91+
}
92+
93+
pub trait KernelLoader {
94+
fn load<F>(
95+
guest_mem: &GuestMemoryMmap,
96+
kernel_start: Option<GuestAddress>,
97+
kernel_image: &mut F,
98+
lowest_kernel_start: Option<GuestAddress>,
99+
) -> Result<(KernelLoaderResult)>
100+
where
101+
F: Read + Seek;
102+
}
103+
104+
pub struct Elf;
85105

86-
impl ElfLoader {
106+
impl KernelLoader for Elf {
87107
/// Loads a kernel from a vmlinux elf image to a slice
88108
///
89109
/// kernel is loaded into guest memory at offset phdr.p_paddr specified by elf image.
@@ -96,15 +116,13 @@ impl ElfLoader {
96116
/// * `lowest_kernel_start` - This is the start of the high memory, kernel should above it.
97117
///
98118
/// # Returns
99-
/// * GuestAddress - GuestAddress where kernel is loaded.
100-
/// * usize - the length of kernel image. Return this in case of other part
101-
/// like initrd will be loaded adjacent to the kernel part.
102-
pub fn load_kernel<F>(
119+
/// * KernelLoaderResult
120+
fn load<F>(
103121
guest_mem: &GuestMemoryMmap,
104122
kernel_start: Option<GuestAddress>,
105123
kernel_image: &mut F,
106124
lowest_kernel_start: Option<GuestAddress>,
107-
) -> Result<(GuestAddress, GuestUsize)>
125+
) -> Result<(KernelLoaderResult)>
108126
where
109127
F: Read + Seek,
110128
{
@@ -140,8 +158,10 @@ impl ElfLoader {
140158
return Err(Error::InvalidEntryAddress);
141159
}
142160
}
161+
162+
let mut loader_result: KernelLoaderResult = Default::default();
143163
// where the kernel will be start loaded.
144-
let kernel_loaded_addr = match kernel_start {
164+
loader_result.kernel_load = match kernel_start {
145165
Some(start) => GuestAddress(start.raw_value() + (ehdr.e_entry as u64)),
146166
None => GuestAddress(ehdr.e_entry as u64),
147167
};
@@ -155,8 +175,6 @@ impl ElfLoader {
155175
.map_err(|_| Error::ReadProgramHeader)?
156176
};
157177

158-
let mut kernel_end: GuestUsize = 0;
159-
160178
// Read in each section pointed to by the program headers.
161179
for phdr in &phdrs {
162180
if phdr.p_type != elf::PT_LOAD || phdr.p_filesz == 0 {
@@ -180,10 +198,11 @@ impl ElfLoader {
180198
.read_exact_from(mem_offset, kernel_image, phdr.p_filesz as usize)
181199
.map_err(|_| Error::ReadKernelImage)?;
182200

183-
kernel_end = mem_offset.raw_value() as GuestUsize + phdr.p_memsz as GuestUsize;
201+
loader_result.kernel_end =
202+
mem_offset.raw_value() as GuestUsize + phdr.p_memsz as GuestUsize;
184203
}
185204

186-
Ok((kernel_loaded_addr, kernel_end))
205+
Ok(loader_result)
187206
}
188207
}
189208

@@ -221,8 +240,8 @@ pub fn load_cmdline(
221240
#[cfg(test)]
222241
mod test {
223242
use super::*;
224-
use vm_memory::{Address, GuestAddress, GuestMemoryMmap};
225243
use std::io::Cursor;
244+
use vm_memory::{Address, GuestAddress, GuestMemoryMmap};
226245

227246
const MEM_SIZE: u64 = 0x1000000;
228247

@@ -243,36 +262,45 @@ mod test {
243262
let image = make_elf_bin();
244263
let kernel_addr = GuestAddress(0x200000);
245264
let mut lowest_kernel_start = GuestAddress(0x0);
246-
247-
let mut x = ElfLoader::load_kernel(
265+
let mut loader_result = Elf::load(
248266
&gm,
249267
Some(kernel_addr),
250268
&mut Cursor::new(&image),
251269
Some(lowest_kernel_start),
270+
)
271+
.unwrap();
272+
println!(
273+
"load elf at address {:8x} \n",
274+
loader_result.kernel_load.raw_value()
252275
);
253-
assert_eq!(x.is_ok(), true);
254-
let mut entry_addr = x.unwrap().0;
255-
println!("load elf at address {:8x} \n", entry_addr.raw_value());
256276

257-
x = ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&image), None);
258-
assert_eq!(x.is_ok(), true);
259-
entry_addr = x.unwrap().0;
260-
println!("load elf at address {:8x} \n", entry_addr.raw_value());
277+
loader_result = Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&image), None).unwrap();
278+
println!(
279+
"load elf at address {:8x} \n",
280+
loader_result.kernel_load.raw_value()
281+
);
261282

262-
x = ElfLoader::load_kernel(
283+
loader_result = Elf::load(
263284
&gm,
264285
None,
265286
&mut Cursor::new(&image),
266287
Some(lowest_kernel_start),
288+
)
289+
.unwrap();
290+
println!(
291+
"load elf at address {:8x} \n",
292+
loader_result.kernel_load.raw_value()
267293
);
268-
assert_eq!(x.is_ok(), true);
269-
entry_addr = x.unwrap().0;
270-
println!("load elf at address {:8x} \n", entry_addr.raw_value());
271294

272295
lowest_kernel_start = GuestAddress(0xa00000);
273296
assert_eq!(
274297
Err(Error::InvalidEntryAddress),
275-
ElfLoader::load_kernel(&gm, None, &mut Cursor::new(&image), Some(lowest_kernel_start))
298+
Elf::load(
299+
&gm,
300+
None,
301+
&mut Cursor::new(&image),
302+
Some(lowest_kernel_start)
303+
)
276304
);
277305
}
278306

@@ -326,7 +354,7 @@ mod test {
326354
bad_image[0x1] = 0x33;
327355
assert_eq!(
328356
Err(Error::InvalidElfMagicNumber),
329-
ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None)
357+
Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None)
330358
);
331359
}
332360

@@ -339,7 +367,7 @@ mod test {
339367
bad_image[0x5] = 2;
340368
assert_eq!(
341369
Err(Error::BigEndianElfOnLittle),
342-
ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None)
370+
Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None)
343371
);
344372
}
345373

@@ -352,7 +380,7 @@ mod test {
352380
bad_image[0x20] = 0x10;
353381
assert_eq!(
354382
Err(Error::InvalidProgramHeaderOffset),
355-
ElfLoader::load_kernel(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None)
383+
Elf::load(&gm, Some(kernel_addr), &mut Cursor::new(&bad_image), None)
356384
);
357385
}
358386
}

0 commit comments

Comments
 (0)