• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Loader for bzImage-format Linux kernels as described in
6 // https://www.kernel.org/doc/Documentation/x86/boot.txt
7 
8 use std::io::Read;
9 use std::io::Seek;
10 use std::io::SeekFrom;
11 
12 use base::AsRawDescriptor;
13 use data_model::zerocopy_from_reader;
14 use remain::sorted;
15 use thiserror::Error;
16 use vm_memory::GuestAddress;
17 use vm_memory::GuestMemory;
18 
19 use crate::bootparam::boot_params;
20 
21 #[sorted]
22 #[derive(Error, Debug, PartialEq, Eq)]
23 pub enum Error {
24     #[error("bad kernel header signature")]
25     BadSignature,
26     #[error("invalid setup_sects value")]
27     InvalidSetupSects,
28     #[error("invalid syssize value")]
29     InvalidSysSize,
30     #[error("unable to read boot_params")]
31     ReadBootParams,
32     #[error("unable to read kernel image")]
33     ReadKernelImage,
34     #[error("unable to seek to boot_params")]
35     SeekBootParams,
36     #[error("unable to seek to kernel start")]
37     SeekKernelStart,
38 }
39 
40 pub type Result<T> = std::result::Result<T, Error>;
41 
42 /// Loads a kernel from a bzImage to a slice
43 ///
44 /// # Arguments
45 ///
46 /// * `guest_mem` - The guest memory region the kernel is written to.
47 /// * `kernel_start` - The offset into `guest_mem` at which to load the kernel.
48 /// * `kernel_image` - Input bzImage.
load_bzimage<F>( guest_mem: &GuestMemory, kernel_start: GuestAddress, mut kernel_image: &mut F, ) -> Result<(boot_params, u64)> where F: Read + Seek + AsRawDescriptor,49 pub fn load_bzimage<F>(
50     guest_mem: &GuestMemory,
51     kernel_start: GuestAddress,
52     mut kernel_image: &mut F,
53 ) -> Result<(boot_params, u64)>
54 where
55     F: Read + Seek + AsRawDescriptor,
56 {
57     kernel_image
58         .seek(SeekFrom::Start(0))
59         .map_err(|_| Error::SeekBootParams)?;
60     let params: boot_params =
61         zerocopy_from_reader(&mut kernel_image).map_err(|_| Error::ReadBootParams)?;
62 
63     // bzImage header signature "HdrS"
64     if params.hdr.header != 0x53726448 {
65         return Err(Error::BadSignature);
66     }
67 
68     let setup_sects = if params.hdr.setup_sects == 0 {
69         4u64
70     } else {
71         params.hdr.setup_sects as u64
72     };
73 
74     let kernel_offset = setup_sects
75         .checked_add(1)
76         .ok_or(Error::InvalidSetupSects)?
77         .checked_mul(512)
78         .ok_or(Error::InvalidSetupSects)?;
79     let kernel_size = (params.hdr.syssize as usize)
80         .checked_mul(16)
81         .ok_or(Error::InvalidSysSize)?;
82 
83     kernel_image
84         .seek(SeekFrom::Start(kernel_offset))
85         .map_err(|_| Error::SeekKernelStart)?;
86 
87     // Load the whole kernel image to kernel_start
88     guest_mem
89         .read_to_memory(kernel_start, kernel_image, kernel_size)
90         .map_err(|_| Error::ReadKernelImage)?;
91 
92     Ok((params, kernel_start.offset() + kernel_size as u64))
93 }
94