igvmfilegen/platform_mask.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Helpers for resolving `IgvmPlatformType` <-> compatibility-mask
5//! mappings declared in an IGVM file's platform headers, and for
6//! deriving human-readable / file-name-safe short names for each
7//! supported platform.
8
9use igvm::IgvmPlatformHeader;
10use igvm_defs::IgvmPlatformType;
11
12/// Short lowercase name for a measurable platform, suitable for file
13/// names and CLI suffixes (e.g. `"snp"`, `"tdx"`, `"vbs"`).
14///
15/// Returns `None` for platform variants that don't have a canonical
16/// short name in this tool (e.g. `Native`).
17pub fn isolation_short_name(platform: IgvmPlatformType) -> Option<&'static str> {
18 match platform {
19 IgvmPlatformType::SEV_SNP => Some("snp"),
20 IgvmPlatformType::TDX => Some("tdx"),
21 IgvmPlatformType::VSM_ISOLATION => Some("vbs"),
22 _ => None,
23 }
24}
25
26/// Always-safe label for a platform, used to generate sibling file
27/// names and human-readable platform tags. Falls back to
28/// `platform_<Debug>` for variants without a canonical short name,
29/// ensuring two distinct platforms never collide on the same label.
30pub fn isolation_label(platform: IgvmPlatformType) -> String {
31 match isolation_short_name(platform) {
32 Some(name) => name.to_string(),
33 None => format!("platform_{platform:?}"),
34 }
35}
36
37/// Look up the compatibility mask for a given platform type by reading the
38/// platform headers from the IGVM file.
39///
40/// Each IGVM file declares its own platform-to-mask mapping via
41/// `IGVM_VHS_SUPPORTED_PLATFORM` headers.
42///
43/// Returns an error if the requested platform type is not present in the
44/// file's platform headers.
45pub fn lookup_compatibility_mask(
46 platforms: &[IgvmPlatformHeader],
47 platform: IgvmPlatformType,
48) -> anyhow::Result<u32> {
49 for header in platforms {
50 match header {
51 IgvmPlatformHeader::SupportedPlatform(info) => {
52 if info.platform_type == platform {
53 return Ok(info.compatibility_mask);
54 }
55 }
56 }
57 }
58
59 anyhow::bail!(
60 "Platform type {platform:?} not found in IGVM file platform headers. \
61 Available platforms: {}",
62 platforms
63 .iter()
64 .map(|h| match h {
65 IgvmPlatformHeader::SupportedPlatform(info) => {
66 format!(
67 "{:?} (mask=0x{:X})",
68 info.platform_type, info.compatibility_mask
69 )
70 }
71 })
72 .collect::<Vec<_>>()
73 .join(", ")
74 )
75}
76
77/// Format a compatibility mask as a human-readable platform list using
78/// the platform headers from the IGVM file.
79pub fn format_platform_mask(platforms: &[IgvmPlatformHeader], mask: u32) -> String {
80 let mut names = Vec::new();
81 for header in platforms {
82 match header {
83 IgvmPlatformHeader::SupportedPlatform(info) => {
84 if mask & info.compatibility_mask != 0 {
85 names.push(format!("{:?}", info.platform_type));
86 }
87 }
88 }
89 }
90 if names.is_empty() {
91 "Unknown".to_string()
92 } else {
93 names.join(", ")
94 }
95}
96
97/// Map a compatibility mask to a lowercase platform name suitable for use in
98/// file names. Returns the platform's canonical short name (`"vbs"`, `"snp"`,
99/// `"tdx"`) when the mask matches a known platform header; otherwise
100/// `platform_<Debug>` for a matching header whose platform type has no
101/// canonical short name, or `mask_0x<hex>` if the mask matches no platform
102/// header at all.
103pub fn platform_name_for_mask(platforms: &[IgvmPlatformHeader], mask: u32) -> String {
104 for header in platforms {
105 match header {
106 IgvmPlatformHeader::SupportedPlatform(info) => {
107 if info.compatibility_mask == mask {
108 return isolation_label(info.platform_type);
109 }
110 }
111 }
112 }
113 format!("mask_0x{mask:x}")
114}