mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
x86_64: load initrd at max address
This matches behavior of other bootloaders (grub2, iPXE), and the kernel seems to be relying on this; decompression of the initrd fails if the initrd is loaded right after the kernel as before, but succeeds if loaded at the maximum address. BUG=None TEST=Boot Debian kernel + initrd on workstation Change-Id: If7712efb05f55ef413a419dfe276ed3f68c335b7 Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1616989 Tested-by: kokoro <noreply+kokoro@google.com> Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
be1ad40a0e
commit
3007ff3cf4
2 changed files with 69 additions and 6 deletions
|
@ -271,6 +271,7 @@ pub fn add_serial_devices(
|
||||||
/// Errors for image loading.
|
/// Errors for image loading.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LoadImageError {
|
pub enum LoadImageError {
|
||||||
|
BadAlignment(u64),
|
||||||
Seek(io::Error),
|
Seek(io::Error),
|
||||||
ImageSizeTooLarge(u64),
|
ImageSizeTooLarge(u64),
|
||||||
ReadToMemory(GuestMemoryError),
|
ReadToMemory(GuestMemoryError),
|
||||||
|
@ -281,6 +282,7 @@ impl Display for LoadImageError {
|
||||||
use self::LoadImageError::*;
|
use self::LoadImageError::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
|
BadAlignment(a) => write!(f, "Alignment not a power of two: {}", a),
|
||||||
Seek(e) => write!(f, "Seek failed: {}", e),
|
Seek(e) => write!(f, "Seek failed: {}", e),
|
||||||
ImageSizeTooLarge(size) => write!(f, "Image size too large: {}", size),
|
ImageSizeTooLarge(size) => write!(f, "Image size too large: {}", size),
|
||||||
ReadToMemory(e) => write!(f, "Reading image into memory failed: {}", e),
|
ReadToMemory(e) => write!(f, "Reading image into memory failed: {}", e),
|
||||||
|
@ -326,3 +328,54 @@ where
|
||||||
|
|
||||||
Ok(size)
|
Ok(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load an image from a file into guest memory at the highest possible address.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `guest_mem` - The memory to be used by the guest.
|
||||||
|
/// * `image` - The file containing the image to be loaded.
|
||||||
|
/// * `min_guest_addr` - The minimum address of the start of the image.
|
||||||
|
/// * `max_guest_addr` - The address to load the last byte of the image.
|
||||||
|
/// * `align` - The minimum alignment of the start address of the image in bytes
|
||||||
|
/// (must be a power of two).
|
||||||
|
///
|
||||||
|
/// The guest address and size in bytes of the loaded image are returned.
|
||||||
|
pub fn load_image_high<F>(
|
||||||
|
guest_mem: &GuestMemory,
|
||||||
|
image: &mut F,
|
||||||
|
min_guest_addr: GuestAddress,
|
||||||
|
max_guest_addr: GuestAddress,
|
||||||
|
align: u64,
|
||||||
|
) -> Result<(GuestAddress, usize), LoadImageError>
|
||||||
|
where
|
||||||
|
F: Read + Seek,
|
||||||
|
{
|
||||||
|
if !align.is_power_of_two() {
|
||||||
|
return Err(LoadImageError::BadAlignment(align));
|
||||||
|
}
|
||||||
|
|
||||||
|
let max_size = max_guest_addr.offset_from(min_guest_addr) & !(align - 1);
|
||||||
|
let size = image.seek(SeekFrom::End(0)).map_err(LoadImageError::Seek)?;
|
||||||
|
|
||||||
|
if size > usize::max_value() as u64 || size > max_size {
|
||||||
|
return Err(LoadImageError::ImageSizeTooLarge(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
image
|
||||||
|
.seek(SeekFrom::Start(0))
|
||||||
|
.map_err(LoadImageError::Seek)?;
|
||||||
|
|
||||||
|
// Load image at the maximum aligned address allowed.
|
||||||
|
// The subtraction cannot underflow because of the size checks above.
|
||||||
|
let guest_addr = GuestAddress((max_guest_addr.offset() - size) & !(align - 1));
|
||||||
|
|
||||||
|
// This is safe due to the bounds check above.
|
||||||
|
let size = size as usize;
|
||||||
|
|
||||||
|
guest_mem
|
||||||
|
.read_to_memory(guest_addr, image, size)
|
||||||
|
.map_err(LoadImageError::ReadToMemory)?;
|
||||||
|
|
||||||
|
Ok((guest_addr, size))
|
||||||
|
}
|
||||||
|
|
|
@ -458,16 +458,26 @@ impl X8664arch {
|
||||||
|
|
||||||
let initrd = match initrd_file {
|
let initrd = match initrd_file {
|
||||||
Some(mut initrd_file) => {
|
Some(mut initrd_file) => {
|
||||||
let initrd_start = free_addr;
|
let mut initrd_addr_max = u64::from(params.hdr.initrd_addr_max);
|
||||||
let initrd_max_size = mem_size - initrd_start;
|
// Default initrd_addr_max for old kernels (see Documentation/x86/boot.txt).
|
||||||
let initrd_size = arch::load_image(
|
if initrd_addr_max == 0 {
|
||||||
|
initrd_addr_max = 0x37FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mem_max = mem.end_addr().offset() - 1;
|
||||||
|
if initrd_addr_max > mem_max {
|
||||||
|
initrd_addr_max = mem_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (initrd_start, initrd_size) = arch::load_image_high(
|
||||||
mem,
|
mem,
|
||||||
&mut initrd_file,
|
&mut initrd_file,
|
||||||
GuestAddress(initrd_start),
|
GuestAddress(free_addr),
|
||||||
initrd_max_size,
|
GuestAddress(initrd_addr_max),
|
||||||
|
sys_util::pagesize() as u64,
|
||||||
)
|
)
|
||||||
.map_err(Error::LoadInitrd)?;
|
.map_err(Error::LoadInitrd)?;
|
||||||
Some((GuestAddress(initrd_start), initrd_size))
|
Some((initrd_start, initrd_size))
|
||||||
}
|
}
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue