Skip to content

Commit 4600865

Browse files
author
Danny Milosavljevic
committed
Check whether (processor generation, spi_mode_bulldozer, spi_mode_zen_naples, spi_mode_zen_rome) that was specified by the user is actually valid
Fixes <#141>.
1 parent e39c2d2 commit 4600865

File tree

2 files changed

+92
-5
lines changed

2 files changed

+92
-5
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ edition = "2018"
88

99
[dependencies]
1010
amd-apcb = { git = "https://github.com/oxidecomputer/amd-apcb.git", tag = "v0.1.5", features = ["std", "serde", "schemars"] }
11-
amd-efs = { git = "ssh://[email protected]/oxidecomputer/amd-efs.git", tag = "v0.3.0", features = ["std", "serde", "schemars"] }
11+
amd-efs = { path = "../amd-efs", features = ["std", "serde", "schemars"] }
1212
amd-flash = { git = "ssh://[email protected]/oxidecomputer/amd-flash.git", tag = "v0.2.1", features = ["std"] }
1313
goblin = { version = "0.4", features = ["elf64", "endian_fd"] }
1414
#serde = { version = "1.0", default-features = false, features = ["derive"] }

amd-host-image-builder-config/src/lib.rs

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ use amd_efs::{
1919
use amd_flash::Location;
2020

2121
#[derive(Debug)]
22+
#[derive(thiserror::Error)]
23+
#[non_exhaustive]
2224
pub enum Error {
25+
#[error("Efs {0}")]
2326
Efs(amd_efs::Error),
27+
#[error("incompatible executable")]
2428
IncompatibleExecutable,
29+
#[error("Io {0}")]
2530
Io(std::io::Error),
31+
#[error("image too big")]
2632
ImageTooBig,
2733
}
2834

@@ -283,21 +289,102 @@ pub enum SerdeBhdDirectoryVariant<'a> {
283289
#[derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
284290
#[serde(rename = "Config")]
285291
#[serde(deny_unknown_fields)]
286-
pub struct SerdeConfig<'a> {
292+
struct RawSerdeConfig<'a> {
287293
pub processor_generation: ProcessorGeneration,
288294
#[serde(default)]
289-
pub spi_mode_bulldozer: EfhBulldozerSpiMode,
295+
pub spi_mode_bulldozer: Option<EfhBulldozerSpiMode>,
290296
#[serde(default)]
291-
pub spi_mode_zen_naples: EfhNaplesSpiMode,
297+
pub spi_mode_zen_naples: Option<EfhNaplesSpiMode>,
292298
#[serde(default)]
293-
pub spi_mode_zen_rome: EfhRomeSpiMode,
299+
pub spi_mode_zen_rome: Option<EfhRomeSpiMode>,
294300
pub psp: SerdePspDirectoryVariant,
295301
#[serde(bound(
296302
deserialize = "SerdeBhdDirectoryVariant<'a>: Deserialize<'de>"
297303
))]
298304
pub bhd: SerdeBhdDirectoryVariant<'a>,
299305
}
300306

307+
// TODO: #[serde(bound(serialize = "T: MySerTrait", deserialize = "T: MyDeTrait"))]
308+
// TODO: impl serde::Serialize
309+
#[derive(serde::Serialize, serde::Deserialize)]
310+
#[serde(try_from = "RawSerdeConfig")]
311+
#[serde(into = "RawSerdeConfig")]
312+
pub struct SerdeConfig<'a> { // Note: same fields as above!
313+
pub processor_generation: ProcessorGeneration,
314+
pub spi_mode_bulldozer: Option<EfhBulldozerSpiMode>,
315+
pub spi_mode_zen_naples: Option<EfhNaplesSpiMode>,
316+
pub spi_mode_zen_rome: Option<EfhRomeSpiMode>,
317+
pub psp: SerdePspDirectoryVariant,
318+
pub bhd: SerdeBhdDirectoryVariant<'a>,
319+
}
320+
321+
impl<'a> schemars::JsonSchema for SerdeConfig<'a> {
322+
fn schema_name() -> std::string::String {
323+
RawSerdeConfig::schema_name()
324+
}
325+
fn json_schema(
326+
gen: &mut schemars::gen::SchemaGenerator,
327+
) -> schemars::schema::Schema {
328+
RawSerdeConfig::json_schema(gen)
329+
}
330+
fn is_referenceable() -> bool {
331+
RawSerdeConfig::is_referenceable()
332+
}
333+
}
334+
335+
impl<'a> From<SerdeConfig<'a>> for RawSerdeConfig<'a> {
336+
fn from(config: SerdeConfig<'a>) -> Self {
337+
Self {
338+
processor_generation: config.processor_generation,
339+
spi_mode_bulldozer: config.spi_mode_bulldozer,
340+
spi_mode_zen_naples: config.spi_mode_zen_naples,
341+
spi_mode_zen_rome: config.spi_mode_zen_rome,
342+
psp: config.psp,
343+
bhd: config.bhd,
344+
}
345+
}
346+
}
347+
348+
/// This validates whether the spi mode is compatible with the
349+
/// processor generation (used to validate after deserialization
350+
/// of a json5 config)
351+
impl<'a> core::convert::TryFrom<RawSerdeConfig<'a>> for SerdeConfig<'a> {
352+
type Error = Error;
353+
fn try_from(raw: RawSerdeConfig<'a>) -> core::result::Result<Self, Self::Error> {
354+
match raw.processor_generation {
355+
ProcessorGeneration::Naples => {
356+
if raw.spi_mode_bulldozer.is_none()
357+
&& raw.spi_mode_zen_naples.is_some()
358+
&& raw.spi_mode_zen_rome.is_none() {
359+
return Ok(SerdeConfig {
360+
processor_generation: raw.processor_generation,
361+
spi_mode_bulldozer: raw.spi_mode_bulldozer,
362+
spi_mode_zen_naples: raw.spi_mode_zen_naples,
363+
spi_mode_zen_rome: raw.spi_mode_zen_rome,
364+
psp: raw.psp,
365+
bhd: raw.bhd,
366+
});
367+
}
368+
}
369+
ProcessorGeneration::Rome | ProcessorGeneration::Milan => {
370+
if raw.spi_mode_bulldozer.is_none()
371+
&& raw.spi_mode_zen_naples.is_none()
372+
&& raw.spi_mode_zen_rome.is_some() {
373+
return Ok(SerdeConfig {
374+
processor_generation: raw.processor_generation,
375+
spi_mode_bulldozer: raw.spi_mode_bulldozer,
376+
spi_mode_zen_naples: raw.spi_mode_zen_naples,
377+
spi_mode_zen_rome: raw.spi_mode_zen_rome,
378+
psp: raw.psp,
379+
bhd: raw.bhd,
380+
});
381+
}
382+
}
383+
}
384+
Err(Error::Efs(amd_efs::Error::SpiModeMismatch))
385+
}
386+
}
387+
301388
#[cfg(test)]
302389
mod tests {
303390
#[test]

0 commit comments

Comments
 (0)