blob: 0ee9b666a4c7493c9d319fdf2c91c053990370da [file] [log] [blame]
// Copyright 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Device tree source (dts) for comparing device tree contents
//! i.e. sorted dts decompiled by `dtc -s -O dts`.
use anyhow::{anyhow, Result};
use libfdt::Fdt;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio};
/// Device tree source (dts)
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct Dts {
dts: String,
}
impl Dts {
/// Creates a device tree source from /proc/device-tree style directory
pub fn from_fs(path: &Path) -> Result<Self> {
let path = path.to_str().unwrap();
let res = Command::new("./dtc_static")
.args(["-f", "-s", "-I", "fs", "-O", "dts", path])
.output()?;
if !res.status.success() {
return Err(anyhow!("Failed to run dtc_static, res={res:?}"));
}
Ok(Self { dts: String::from_utf8(res.stdout)? })
}
/// Creates a device tree source from dtb
pub fn from_dtb(path: &Path) -> Result<Self> {
let path = path.to_str().unwrap();
let res = Command::new("./dtc_static")
.args(["-f", "-s", "-I", "dtb", "-O", "dts", path])
.output()?;
if !res.status.success() {
return Err(anyhow!("Failed to run dtc_static, res={res:?}"));
}
Ok(Self { dts: String::from_utf8(res.stdout)? })
}
/// Creates a device tree source from Fdt
pub fn from_fdt(fdt: &Fdt) -> Result<Self> {
let mut dtc = Command::new("./dtc_static")
.args(["-f", "-s", "-I", "dtb", "-O", "dts"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
{
let mut stdin = dtc.stdin.take().unwrap();
stdin.write_all(fdt.as_slice())?;
// Explicitly drop stdin to avoid indefinite blocking
}
let res = dtc.wait_with_output()?;
if !res.status.success() {
return Err(anyhow!("Failed to run dtc_static, res={res:?}"));
}
Ok(Self { dts: String::from_utf8(res.stdout)? })
}
}