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