-
Notifications
You must be signed in to change notification settings - Fork 1
Validate EEPROM after writing it #316
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1526,6 +1526,24 @@ impl CrosEc { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return_val | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pub fn validate_gpu_descriptor(&self, reference_desc: &[u8]) -> EcResult<bool> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let current_desc = self.read_gpu_descriptor()?; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let max_len = core::cmp::max(current_desc.len(), reference_desc.len()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let mut valid = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i in 0..max_len { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let expected = reference_desc.get(i); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let actual = current_desc.get(i); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if expected != actual { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| println!( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| " Offset 0x{:04X}: expected {:02X?}, got {:02X?}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| i, expected, actual | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| valid = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Ok(valid) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1530
to
+1544
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let current_desc = self.read_gpu_descriptor()?; | |
| let max_len = core::cmp::max(current_desc.len(), reference_desc.len()); | |
| let mut valid = true; | |
| for i in 0..max_len { | |
| let expected = reference_desc.get(i); | |
| let actual = current_desc.get(i); | |
| if expected != actual { | |
| println!( | |
| " Offset 0x{:04X}: expected {:02X?}, got {:02X?}", | |
| i, expected, actual | |
| ); | |
| valid = false; | |
| } | |
| } | |
| Ok(valid) | |
| let gpu_power_enabled = self.get_gpio("gpu_3v_5v_en")?; | |
| let force_power = !gpu_power_enabled; | |
| if force_power { | |
| self.set_gpio("gpu_3v_5v_en", true)?; | |
| } | |
| let return_val = (|| -> EcResult<bool> { | |
| let current_desc = self.read_gpu_descriptor()?; | |
| let max_len = core::cmp::max(current_desc.len(), reference_desc.len()); | |
| let mut valid = true; | |
| for i in 0..max_len { | |
| let expected = reference_desc.get(i); | |
| let actual = current_desc.get(i); | |
| if expected != actual { | |
| println!( | |
| " Offset 0x{:04X}: expected {:02X?}, got {:02X?}", | |
| i, expected, actual | |
| ); | |
| valid = false; | |
| } | |
| } | |
| Ok(valid) | |
| })(); | |
| if force_power { | |
| let res = self.set_gpio("gpu_3v_5v_en", false); | |
| if let Err(err) = res { | |
| error!("Failed to set ALW power to GPU off {:?}", err); | |
| return if return_val.is_err() { | |
| return_val | |
| } else { | |
| Err(err) | |
| }; | |
| } | |
| } | |
| return_val |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -309,6 +309,10 @@ struct ClapCli { | |
| #[arg(long)] | ||
| dump_gpu_descriptor_file: Option<std::path::PathBuf>, | ||
|
|
||
| /// File to validate the gpu EEPROM against | ||
| #[arg(long)] | ||
| validate_gpu_descriptor_file: Option<std::path::PathBuf>, | ||
|
|
||
| /// Show NVIDIA GPU information (Framework 16 only) | ||
| #[arg(long)] | ||
| nvidia: bool, | ||
|
|
@@ -564,6 +568,9 @@ pub fn parse(args: &[String]) -> Cli { | |
| dump_gpu_descriptor_file: args | ||
| .dump_gpu_descriptor_file | ||
| .map(|x| x.into_os_string().into_string().unwrap()), | ||
| validate_gpu_descriptor_file: args | ||
| .validate_gpu_descriptor_file | ||
| .map(|x| x.into_os_string().into_string().unwrap()), | ||
|
Comment on lines
+571
to
+573
|
||
| nvidia: args.nvidia, | ||
| host_command, | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -227,6 +227,7 @@ pub struct Cli { | |||||||||||||||||||||||||||||||||||||||
| pub flash_gpu_descriptor: Option<(u8, String)>, | ||||||||||||||||||||||||||||||||||||||||
| pub flash_gpu_descriptor_file: Option<String>, | ||||||||||||||||||||||||||||||||||||||||
| pub dump_gpu_descriptor_file: Option<String>, | ||||||||||||||||||||||||||||||||||||||||
| pub validate_gpu_descriptor_file: Option<String>, | ||||||||||||||||||||||||||||||||||||||||
| pub nvidia: bool, | ||||||||||||||||||||||||||||||||||||||||
| // UEFI only | ||||||||||||||||||||||||||||||||||||||||
| pub allupdate: bool, | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1807,7 +1808,15 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { | |||||||||||||||||||||||||||||||||||||||
| println!(" Size: {:>20} KB", data.len() / 1024); | ||||||||||||||||||||||||||||||||||||||||
| let res = ec.set_gpu_descriptor(&data, args.dry_run); | ||||||||||||||||||||||||||||||||||||||||
| match res { | ||||||||||||||||||||||||||||||||||||||||
| Ok(()) => println!("GPU Descriptor successfully written"), | ||||||||||||||||||||||||||||||||||||||||
| Ok(()) => { | ||||||||||||||||||||||||||||||||||||||||
| println!("GPU Descriptor successfully written"); | ||||||||||||||||||||||||||||||||||||||||
| println!("Validating GPU Descriptor..."); | ||||||||||||||||||||||||||||||||||||||||
| match ec.validate_gpu_descriptor(&data) { | ||||||||||||||||||||||||||||||||||||||||
| Ok(true) => println!(" Validation passed"), | ||||||||||||||||||||||||||||||||||||||||
| Ok(false) => println!(" Validation FAILED: read-back mismatch"), | ||||||||||||||||||||||||||||||||||||||||
| Err(err) => println!(" Validation error: {:?}", err), | ||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1812
to
+1817
|
||||||||||||||||||||||||||||||||||||||||
| println!("GPU Descriptor successfully written"); | |
| println!("Validating GPU Descriptor..."); | |
| match ec.validate_gpu_descriptor(&data) { | |
| Ok(true) => println!(" Validation passed"), | |
| Ok(false) => println!(" Validation FAILED: read-back mismatch"), | |
| Err(err) => println!(" Validation error: {:?}", err), | |
| if args.dry_run { | |
| println!( | |
| "GPU Descriptor dry run successful; skipping validation because no changes were written" | |
| ); | |
| } else { | |
| println!("GPU Descriptor successfully written"); | |
| println!("Validating GPU Descriptor..."); | |
| match ec.validate_gpu_descriptor(&data) { | |
| Ok(true) => println!(" Validation passed"), | |
| Ok(false) => println!(" Validation FAILED: read-back mismatch"), | |
| Err(err) => println!(" Validation error: {:?}", err), | |
| } |
Copilot
AI
Apr 15, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Validation is triggered after set_gpu_descriptor returns, but set_gpu_descriptor may temporarily enable gpu_3v_5v_en and then disable it again before returning. In that case validate_gpu_descriptor() will try to read the EEPROM with power off and likely fail. Consider moving validation into set_gpu_descriptor (before power is toggled off), or ensure validation also handles the same power-enable/disable flow.
| println!("Validating GPU Descriptor..."); | |
| match ec.validate_gpu_descriptor(&data) { | |
| Ok(true) => println!(" Validation passed"), | |
| Ok(false) => println!(" Validation FAILED: read-back mismatch"), | |
| Err(err) => println!(" Validation error: {:?}", err), | |
| } | |
| println!( | |
| "Skipping immediate validation after write because the EEPROM may have been powered down before set_gpu_descriptor returned" | |
| ); |
Copilot
AI
Apr 15, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--validate-gpu-descriptor-file prints pass/fail but run_with_args still exits with status 0 either way, which makes it hard to use in scripts/CI. Consider returning a non-zero exit code when validation fails or errors (similar to how compare_version() returns 1 on mismatch).
| Ok(true) => println!(" Validation passed"), | |
| Ok(false) => println!(" Validation FAILED: read-back mismatch"), | |
| Err(err) => println!(" Validation error: {:?}", err), | |
| } | |
| Ok(true) => { | |
| println!(" Validation passed"); | |
| return 0; | |
| } | |
| Ok(false) => { | |
| println!(" Validation FAILED: read-back mismatch"); | |
| return 1; | |
| } | |
| Err(err) => { | |
| println!(" Validation error: {:?}", err); | |
| return 1; | |
| } | |
| } | |
| } else { | |
| return 1; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -101,6 +101,7 @@ pub fn parse(args: &[String]) -> Cli { | |||||
| flash_gpu_descriptor: None, | ||||||
| flash_gpu_descriptor_file: None, | ||||||
| dump_gpu_descriptor_file: None, | ||||||
| validate_gpu_descriptor_file: None, | ||||||
| allupdate: false, | ||||||
| info: false, | ||||||
| meinfo: None, | ||||||
|
|
@@ -859,6 +860,14 @@ pub fn parse(args: &[String]) -> Cli { | |||||
| None | ||||||
| }; | ||||||
| found_an_option = true; | ||||||
| } else if arg == "--validate-gpu-descriptor-file" { | ||||||
| cli.validate_gpu_descriptor_file = if args.len() > i + 1 { | ||||||
| Some(args[i + 1].clone()) | ||||||
| } else { | ||||||
| println!("Need to provide a value for --validate_gpu_descriptor_file. PATH"); | ||||||
|
||||||
| println!("Need to provide a value for --validate_gpu_descriptor_file. PATH"); | |
| println!("Need to provide a value for --validate-gpu-descriptor-file. PATH"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As written, validation reads
header.descriptor_lengthbytes and compares them toreference_desc. If the reference buffer length differs from the length encoded in the header (e.g., extra trailing bytes in the file), this will always reportfalseeven when the EEPROM content matches what the header says is valid. Consider assertingreference_desc.len() == header.descriptor_length as usize(and erroring if not) or otherwise defining which length should be compared.