Skip to content

Commit 5f9cc71

Browse files
committed
Improve dump subcommand.
Fixes <#160>.
1 parent c919b79 commit 5f9cc71

File tree

2 files changed

+100
-21
lines changed

2 files changed

+100
-21
lines changed

Cargo.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.rs

Lines changed: 96 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use amd_apcb::{Apcb, ApcbIoOptions};
22
use amd_efs::{
33
AddressMode, BhdDirectory, BhdDirectoryEntry, BhdDirectoryEntryType,
4-
DirectoryEntry, Efs, ProcessorGeneration, PspDirectory, PspDirectoryEntry,
4+
DirectoryEntry, EfhBulldozerSpiMode, EfhNaplesSpiMode, EfhRomeSpiMode, Efs,
5+
ProcessorGeneration, PspDirectory, PspDirectoryEntry,
56
PspDirectoryEntryType, ValueOrLocation,
67
};
78
use amd_host_image_builder_config::{
@@ -19,6 +20,7 @@ use std::cmp::min;
1920
use std::collections::HashSet;
2021
use std::fs;
2122
use std::fs::File;
23+
use std::io::stdout;
2224
use std::io::BufReader;
2325
use std::io::Read;
2426
use std::io::Seek;
@@ -634,6 +636,29 @@ fn serde_from_bhd_entry(
634636
}
635637
}
636638

639+
/// Try to return RESULT?.
640+
/// If that doesn't work, print RESULT_TEXT and then return FALLBACK instead.
641+
/// This is useful because some images don't have SPI mode set. As far as
642+
/// we can tell, the SPI mode is mandatory. In order not to fail the entire
643+
/// dump just because of the SPI mode, we just make one up here.
644+
fn spi_mode_fallback_on_error<T, E: std::fmt::Display>(
645+
result: std::result::Result<T, E>,
646+
fallback: T,
647+
result_text: &str,
648+
) -> T {
649+
match result {
650+
Ok(x) => x,
651+
Err(e) => {
652+
eprintln!(
653+
"{} was invalid: {}. Falling back to default.",
654+
result_text, e
655+
);
656+
// TODO: Maybe set program error status somehow
657+
fallback
658+
}
659+
}
660+
}
661+
637662
fn dump_bhd_directory<'a, T: FlashRead + FlashWrite>(
638663
storage: &T,
639664
bhd_directory: &BhdDirectory,
@@ -653,6 +678,11 @@ fn dump_bhd_directory<'a, T: FlashRead + FlashWrite>(
653678
.map_while(|entry| {
654679
let entry = entry.clone();
655680
if let Ok(typ) = entry.typ_or_err() {
681+
if typ == BhdDirectoryEntryType::Apob {
682+
// Since this is a runtime value we cannot read it
683+
// from the image.
684+
return None;
685+
}
656686
let payload_beginning =
657687
bhd_directory.payload_beginning(&entry).unwrap();
658688
let size = entry.size().unwrap() as usize;
@@ -727,6 +757,7 @@ fn dump_bhd_directory<'a, T: FlashRead + FlashWrite>(
727757
fn dump(
728758
image_filename: &Path,
729759
blob_dump_dirname: Option<PathBuf>,
760+
output_config_file: &mut impl std::io::Write,
730761
) -> std::io::Result<()> {
731762
let filename = image_filename;
732763
let storage = FlashImage::load(filename)?;
@@ -735,25 +766,48 @@ fn dump(
735766
if filesize <= 0x100_0000 { Some(filesize as u32) } else { None };
736767
let efs = Efs::load(&storage, None, amd_physical_mode_mmio_size).unwrap();
737768
if !efs.compatible_with_processor_generation(ProcessorGeneration::Milan) {
738-
panic!("only Milan is supported for dumping right now");
769+
if !efs.compatible_with_processor_generation(ProcessorGeneration::Rome)
770+
{
771+
panic!("only Milan or Rome is supported for dumping right now");
772+
}
739773
}
740774
let mut apcb_buffer = [0xFFu8; Apcb::MAX_SIZE];
741775
let mut apcb_buffer_option = Some(&mut apcb_buffer[..]);
776+
let processor_generation = if efs
777+
.compatible_with_processor_generation(ProcessorGeneration::Milan)
778+
{
779+
ProcessorGeneration::Milan
780+
} else {
781+
ProcessorGeneration::Rome
782+
};
742783
let config = SerdeConfig {
743-
processor_generation: ProcessorGeneration::Milan, // FIXME could be ambiguous
744-
spi_mode_bulldozer: efs.spi_mode_bulldozer().unwrap(),
745-
spi_mode_zen_naples: efs.spi_mode_zen_naples().unwrap(),
746-
spi_mode_zen_rome: efs.spi_mode_zen_rome().unwrap(),
784+
processor_generation,
785+
spi_mode_bulldozer: spi_mode_fallback_on_error(
786+
efs.spi_mode_bulldozer(),
787+
EfhBulldozerSpiMode::default(),
788+
"Bulldozer SPI Mode",
789+
),
790+
spi_mode_zen_naples: spi_mode_fallback_on_error(
791+
efs.spi_mode_zen_naples(),
792+
EfhNaplesSpiMode::default(),
793+
"Naples SPI Mode",
794+
),
795+
spi_mode_zen_rome: spi_mode_fallback_on_error(
796+
efs.spi_mode_zen_rome(),
797+
EfhRomeSpiMode::default(),
798+
"Rome SPI Mode",
799+
),
747800
// TODO: psp_directory or psp_combo_directory
748801
psp: dump_psp_directory(
749802
&storage,
750-
&efs.psp_directory().unwrap(),
803+
&efs.psp_directory().expect("PSP directory"),
751804
&blob_dump_dirname,
752805
),
753806
// TODO: bhd_directory or bhd_combo_directory
754807
bhd: dump_bhd_directory(
755808
&storage,
756-
&efs.bhd_directory(None).unwrap(),
809+
&efs.bhd_directory(Some(processor_generation))
810+
.expect("BHD directory"),
757811
&mut apcb_buffer_option,
758812
&blob_dump_dirname,
759813
),
@@ -766,7 +820,11 @@ fn dump(
766820
let mut file = File::create(&path).expect("creation failed");
767821
writeln!(file, "{}", json5::to_string(&config).unwrap())?;
768822
} else {
769-
println!("{}", serde_json::to_string_pretty(&config)?);
823+
writeln!(
824+
output_config_file,
825+
"{}",
826+
serde_json::to_string_pretty(&config)?
827+
)?;
770828
}
771829
Ok(())
772830
}
@@ -1155,21 +1213,42 @@ fn run() -> std::io::Result<()> {
11551213
};
11561214
match opts {
11571215
Opts::Dump { input_filename, blob_dump_dirname } => {
1158-
dump(&input_filename, blob_dump_dirname)
1216+
dump(&input_filename, blob_dump_dirname, &mut stdout().lock())
11591217
}
11601218
Opts::Generate {
11611219
output_filename,
11621220
efs_configuration_filename,
11631221
reset_image_filename,
11641222
blobdirs,
11651223
verbose,
1166-
} => generate(
1167-
&output_filename,
1168-
&efs_configuration_filename,
1169-
&reset_image_filename,
1170-
blobdirs,
1171-
verbose,
1172-
),
1224+
} => {
1225+
let x = generate(
1226+
&output_filename,
1227+
&efs_configuration_filename,
1228+
&reset_image_filename,
1229+
blobdirs,
1230+
verbose,
1231+
);
1232+
1233+
// In order to make sure that we can dump it back out, try it.
1234+
struct DummyOutput {}
1235+
impl std::io::Write for DummyOutput {
1236+
fn write(
1237+
&mut self,
1238+
buf: &[u8],
1239+
) -> std::result::Result<usize, std::io::Error>
1240+
{
1241+
Ok(buf.len())
1242+
}
1243+
fn flush(&mut self) -> std::result::Result<(), std::io::Error> {
1244+
Ok(())
1245+
}
1246+
}
1247+
let mut dummy_output = DummyOutput {};
1248+
dump(&output_filename, None, &mut dummy_output)
1249+
.expect("read it back out from the image");
1250+
x
1251+
}
11731252
}
11741253
}
11751254

0 commit comments

Comments
 (0)