blob: 3f1fab52d86c9f6deeea4d3386630f88d2d26f5a [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;
Victor Hsiehb5bcfab2022-09-12 13:06:26 -070017use clap::Parser;
Shikha Panwar55957112022-08-22 13:54:33 +000018use std::fs::File;
19use std::io::{Read, Write};
20use std::path::PathBuf;
Shikha Panwar55957112022-08-22 13:54:33 +000021
22const FOOTER_ALIGNMENT: usize = 4;
23const ZEROS: [u8; 4] = [0u8; 4_usize];
24
Victor Hsiehb5bcfab2022-09-12 13:06:26 -070025#[derive(Parser, Debug)]
Shikha Panwar55957112022-08-22 13:54:33 +000026struct Args {
Shikha Panwar55957112022-08-22 13:54:33 +000027 /// Initrd (without bootconfig)
Shikha Panwar55957112022-08-22 13:54:33 +000028 initrd: PathBuf,
29 /// Bootconfig
Shikha Panwar55957112022-08-22 13:54:33 +000030 bootconfigs: Vec<PathBuf>,
Victor Hsiehb5bcfab2022-09-12 13:06:26 -070031 /// Output
32 #[clap(long = "output")]
33 output: PathBuf,
Shikha Panwar55957112022-08-22 13:54:33 +000034}
35
36fn get_checksum(file_path: &PathBuf) -> Result<u32> {
37 File::open(file_path)?.bytes().map(|x| Ok(x? as u32)).sum()
38}
39
40// Bootconfig is attached to the initrd in the following way:
41// [initrd][bootconfig][padding][size(le32)][checksum(le32)][#BOOTCONFIG\n]
42fn attach_bootconfig(initrd: PathBuf, bootconfigs: Vec<PathBuf>, output: PathBuf) -> Result<()> {
43 let mut output_file = File::create(&output)?;
44 let mut initrd_file = File::open(&initrd)?;
45 let initrd_size: usize = initrd_file.metadata()?.len().try_into()?;
46 let mut bootconfig_size: usize = 0;
47 let mut checksum: u32 = 0;
48
49 std::io::copy(&mut initrd_file, &mut output_file)?;
50 for bootconfig in bootconfigs {
51 let mut bootconfig_file = File::open(&bootconfig)?;
52 std::io::copy(&mut bootconfig_file, &mut output_file)?;
53 bootconfig_size += bootconfig_file.metadata()?.len() as usize;
54 checksum += get_checksum(&bootconfig)?;
55 }
56
Shikha Panwar58fdf032023-01-10 05:36:20 +000057 let padding_size: usize =
58 (FOOTER_ALIGNMENT - (initrd_size + bootconfig_size) % FOOTER_ALIGNMENT) % FOOTER_ALIGNMENT;
Shikha Panwar55957112022-08-22 13:54:33 +000059 output_file.write_all(&ZEROS[..padding_size])?;
60 output_file.write_all(&((padding_size + bootconfig_size) as u32).to_le_bytes())?;
61 output_file.write_all(&checksum.to_le_bytes())?;
62 output_file.write_all(b"#BOOTCONFIG\n")?;
63 output_file.flush()?;
64 Ok(())
65}
66
67fn try_main() -> Result<()> {
Victor Hsiehb5bcfab2022-09-12 13:06:26 -070068 let args = Args::parse();
Shikha Panwar55957112022-08-22 13:54:33 +000069 attach_bootconfig(args.initrd, args.bootconfigs, args.output)?;
70 Ok(())
71}
72
73fn main() {
74 try_main().unwrap()
75}