blob: 1023a406edfb3764dbd8364ede2184fd2802dd40 [file] [log] [blame]
Shikha Panwar55957112022-08-22 13:54:33 +00001// Copyright 2022, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Append bootconfig to initrd image
16use anyhow::Result;
17
18use std::fs::File;
19use std::io::{Read, Write};
20use std::path::PathBuf;
21use structopt::StructOpt;
22
23const FOOTER_ALIGNMENT: usize = 4;
24const ZEROS: [u8; 4] = [0u8; 4_usize];
25
26#[derive(StructOpt, Debug)]
27struct Args {
28 /// Output
29 #[structopt(parse(from_os_str), long = "output")]
30 output: PathBuf,
31 /// Initrd (without bootconfig)
32 #[structopt(parse(from_os_str))]
33 initrd: PathBuf,
34 /// Bootconfig
35 #[structopt(parse(from_os_str))]
36 bootconfigs: Vec<PathBuf>,
37}
38
39fn get_checksum(file_path: &PathBuf) -> Result<u32> {
40 File::open(file_path)?.bytes().map(|x| Ok(x? as u32)).sum()
41}
42
43// Bootconfig is attached to the initrd in the following way:
44// [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
45fn attach_bootconfig(initrd: PathBuf, bootconfigs: Vec<PathBuf>, output: PathBuf) -> Result<()> {
46 let mut output_file = File::create(&output)?;
47 let mut initrd_file = File::open(&initrd)?;
48 let initrd_size: usize = initrd_file.metadata()?.len().try_into()?;
49 let mut bootconfig_size: usize = 0;
50 let mut checksum: u32 = 0;
51
52 std::io::copy(&mut initrd_file, &mut output_file)?;
53 for bootconfig in bootconfigs {
54 let mut bootconfig_file = File::open(&bootconfig)?;
55 std::io::copy(&mut bootconfig_file, &mut output_file)?;
56 bootconfig_size += bootconfig_file.metadata()?.len() as usize;
57 checksum += get_checksum(&bootconfig)?;
58 }
59
60 let padding_size: usize = FOOTER_ALIGNMENT - (initrd_size + bootconfig_size) % FOOTER_ALIGNMENT;
61 output_file.write_all(&ZEROS[..padding_size])?;
62 output_file.write_all(&((padding_size + bootconfig_size) as u32).to_le_bytes())?;
63 output_file.write_all(&checksum.to_le_bytes())?;
64 output_file.write_all(b"#BOOTCONFIG\n")?;
65 output_file.flush()?;
66 Ok(())
67}
68
69fn try_main() -> Result<()> {
70 let args = Args::from_args_safe()?;
71 attach_bootconfig(args.initrd, args.bootconfigs, args.output)?;
72 Ok(())
73}
74
75fn main() {
76 try_main().unwrap()
77}