Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,7 @@ dependencies = [
"flowey_lib_common",
"igvmfilegen_config",
"log",
"opentmk_disk",
"paste",
"powershell_builder",
"serde",
Expand Down Expand Up @@ -5515,6 +5516,7 @@ dependencies = [
"memory_range",
"minimal_rt",
"nostd_spin_channel",
"opentmk_protocol",
"serde",
"serde_json",
"spin",
Expand All @@ -5524,6 +5526,30 @@ dependencies = [
"zerocopy",
]

[[package]]
name = "opentmk_disk"
version = "0.0.0"
dependencies = [
"anyhow",
"disk_vhd1",
"fatfs",
"fscommon",
"gptman",
"guid",
"opentmk_protocol",
"tempfile",
]

[[package]]
name = "opentmk_protocol"
version = "0.0.0"
dependencies = [
"serde",
"serde_json",
"thiserror 2.0.16",
"zerocopy",
]

[[package]]
name = "openvmm"
version = "0.0.0"
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ edition = "2024"
[workspace.dependencies]
xtask_fuzz = { path = "xtask/xtask_fuzz" }

# opentmk
opentmk_protocol = { path = "opentmk_protocol" }
opentmk_disk = { path = "opentmk/opentmk_disk" }

flowey = { path = "flowey/flowey" }
flowey_cli = { path = "flowey/flowey_cli" }
flowey_core = { path = "flowey/flowey_core" }
Expand Down
116 changes: 116 additions & 0 deletions flowey/flowey_hvlite/src/pipelines/build_opentmk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! See [`BuildOpentmkCli`]

use crate::pipelines::build_igvm::bail_if_running_in_ci;
use crate::pipelines_shared::cfg_common_params::CommonArchCli;
use flowey::node::prelude::ReadVar;
use flowey::pipeline::prelude::*;
use flowey_lib_hvlite::common::CommonArch;
use std::path::PathBuf;

/// Build OpenTMK and package it into a bootable VHD.
#[derive(clap::Args)]
pub struct BuildOpentmkCli {
/// Target architecture for the OpenTMK build. Defaults to x86-64.
#[clap(default_value = "x86-64")]
pub arch: CommonArchCli,

/// Custom name for the output `.efi`, `.vhd`, and `.pdb` (default `opentmk`).
#[clap(long)]
pub name: Option<String>,

/// Path to a JSON test-selection config to embed in the built VHD. If
/// omitted, the VHD boots the unconfigured `opentmk.efi`.
#[clap(long)]
pub config: Option<PathBuf>,
Comment thread
mayank-microsoft marked this conversation as resolved.

/// Build using release profile.
#[clap(long)]
pub release: bool,

/// Directory for the output artifacts.
#[clap(long, default_value = "flowey-out/build-opentmk")]
pub dir: PathBuf,

/// pass `--verbose` to cargo
#[clap(long)]
pub verbose: bool,

/// pass `--locked` to cargo
#[clap(long)]
pub locked: bool,

/// Automatically install any missing required dependencies.
#[clap(long)]
pub install_missing_deps: bool,
}

impl IntoPipeline for BuildOpentmkCli {
fn into_pipeline(self, backend_hint: PipelineBackendHint) -> anyhow::Result<Pipeline> {
if !matches!(backend_hint, PipelineBackendHint::Local) {
anyhow::bail!("build-opentmk is for local use only")
}

bail_if_running_in_ci()?;

let openvmm_repo = flowey_lib_common::git_checkout::RepoSource::ExistingClone(
ReadVar::from_static(crate::repo_root()),
);

let Self {
arch,
name,
config,
release,
dir,
verbose,
locked,
install_missing_deps,
} = self;

let arch: CommonArch = arch.into();

std::fs::create_dir_all(&dir)?;

let mut pipeline = Pipeline::new();

pipeline
.new_job(
FlowPlatform::host(backend_hint),
FlowArch::host(backend_hint),
"build-opentmk",
)
.dep_on(|_| flowey_lib_hvlite::_jobs::cfg_versions::Request::Init)
.dep_on(
|_| flowey_lib_hvlite::_jobs::cfg_hvlite_reposource::Params {
hvlite_repo_source: openvmm_repo,
},
)
.dep_on(|_| flowey_lib_hvlite::_jobs::cfg_common::Params {
local_only: Some(flowey_lib_hvlite::_jobs::cfg_common::LocalOnlyParams {
interactive: true,
auto_install: install_missing_deps,
ignore_rust_version: true,
}),
verbose: ReadVar::from_static(verbose),
locked,
deny_warnings: false,
no_incremental: false,
})
.dep_on(
|ctx| flowey_lib_hvlite::_jobs::local_build_opentmk::Params {
artifact_dir: ReadVar::from_static(dir),
done: ctx.new_done_handle(),
arch,
release,
name,
config,
},
)
.finish();

Ok(pipeline)
}
}
4 changes: 4 additions & 0 deletions flowey/flowey_hvlite/src/pipelines/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use vmm_tests_run::VmmTestsRunCli;

pub mod build_docs;
pub mod build_igvm;
pub mod build_opentmk;
pub mod build_reproducible;
pub mod cca_tests;
pub mod checkin_gates;
Expand All @@ -26,6 +27,8 @@ pub enum OpenvmmPipelines {
},

BuildIgvm(build_igvm::BuildIgvmCli),
/// Build OpenTMK and package it into a bootable VHD
BuildOpentmk(build_opentmk::BuildOpentmkCli),
Comment thread
mayank-microsoft marked this conversation as resolved.
BuildReproducible(build_reproducible::BuildReproducibleCli),
CustomVmfirmwareigvmDll(custom_vmfirmwareigvm_dll::CustomVmfirmwareigvmDllCli),

Expand Down Expand Up @@ -61,6 +64,7 @@ impl IntoPipeline for OpenvmmPipelines {
std::process::exit(status.code().unwrap_or(-1));
}
OpenvmmPipelines::BuildIgvm(cmd) => cmd.into_pipeline(pipeline_hint),
OpenvmmPipelines::BuildOpentmk(cmd) => cmd.into_pipeline(pipeline_hint),
OpenvmmPipelines::BuildReproducible(cmd) => cmd.into_pipeline(pipeline_hint),
OpenvmmPipelines::CustomVmfirmwareigvmDll(cmd) => cmd.into_pipeline(pipeline_hint),
OpenvmmPipelines::Ci(cmd) => match cmd {
Expand Down
1 change: 1 addition & 0 deletions flowey/flowey_lib_hvlite/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ flowey_lib_common.workspace = true

powershell_builder.workspace = true
igvmfilegen_config.workspace = true
opentmk_disk.workspace = true
vmm_test_images = { workspace = true, features = ["serde"] }

anyhow.workspace = true
Expand Down
102 changes: 102 additions & 0 deletions flowey/flowey_lib_hvlite/src/_jobs/local_build_opentmk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

//! A local-only job that supports the `cargo xflowey build-opentmk` CLI

use flowey::node::prelude::*;

flowey_request! {
pub struct Params {
pub artifact_dir: ReadVar<PathBuf>,
pub done: WriteVar<SideEffect>,

pub arch: crate::common::CommonArch,
pub release: bool,
/// Custom name for the output `.efi`, `.vhd`, and `.pdb`. Defaults to "opentmk".
pub name: Option<String>,
/// Optional JSON test-selection config to embed in the built VHD.
pub config: Option<PathBuf>,
}
}

new_simple_flow_node!(struct Node);

impl SimpleFlowNode for Node {
type Request = Params;

fn imports(ctx: &mut ImportCtx<'_>) {
ctx.import::<crate::build_opentmk::Node>();
}

fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
let Params {
artifact_dir,
done,
arch,
release,
name,
config,
} = request;

let profile = if release {
crate::common::CommonProfile::Release
} else {
crate::common::CommonProfile::Debug
};

let name = name.unwrap_or_else(|| "opentmk".to_string());

let opentmk_output = ctx.reqv(|v| crate::build_opentmk::Request {
arch,
profile,
out_name: Some(name.clone()),
opentmk: v,
});

ctx.emit_rust_step("package opentmk into VHD", |ctx| {
done.claim(ctx);
let artifact_dir = artifact_dir.claim(ctx);
let opentmk_output = opentmk_output.claim(ctx);
move |rt| {
let crate::build_opentmk::OpentmkOutput { efi, pdb } = rt.read(opentmk_output);

let output_dir = rt.read(artifact_dir);
let output_dir = output_dir.absolute()?;
fs_err::create_dir_all(&output_dir)?;

// Build the bootable VHD, patching in the test config if one was given.
let disk_arch = match arch {
crate::common::CommonArch::X86_64 => opentmk_disk::Arch::X86_64,
crate::common::CommonArch::Aarch64 => opentmk_disk::Arch::Aarch64,
};
let efi_bytes = fs_err::read(&efi)?;
let vhd_path = output_dir.join(format!("{name}.vhd"));
let image = if let Some(cfg_path) = &config {
let config_json = fs_err::read(cfg_path.absolute()?)?;
opentmk_disk::build_opentmk_vhd_with_config(
&efi_bytes,
disk_arch,
&config_json,
)?
} else {
opentmk_disk::build_opentmk_vhd(&efi_bytes, disk_arch)?
};
if vhd_path.exists() {
fs_err::remove_file(&vhd_path)?;
}
image.persist(&vhd_path)?;
Comment thread
mayank-microsoft marked this conversation as resolved.

fs_err::copy(&efi, output_dir.join(format!("{name}.efi")))?;
fs_err::copy(&pdb, output_dir.join(format!("{name}.pdb")))?;

log::info!("EFI: {}", output_dir.join(format!("{name}.efi")).display());
log::info!("VHD: {}", vhd_path.display());
log::info!("PDB: {}", output_dir.join(format!("{name}.pdb")).display());

Ok(())
}
});

Ok(())
}
}
1 change: 1 addition & 0 deletions flowey/flowey_lib_hvlite/src/_jobs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod consume_and_test_nextest_unit_tests_archive;
pub mod consume_and_test_nextest_vmm_tests_archive;
pub mod local_build_and_run_nextest_vmm_tests;
pub mod local_build_igvm;
pub mod local_build_opentmk;
pub mod local_check_cca_emu_prereq;
pub mod local_custom_vmfirmwareigvm_dll;
pub mod local_install_cca_emu;
Expand Down
Loading
Loading