-
Notifications
You must be signed in to change notification settings - Fork 137
Add (some level of) SDM support #832
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
0f16f28
9d1fa54
edaab44
5428d4b
b49bc8e
7957199
8b7c4bc
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 |
---|---|---|
|
@@ -124,6 +124,7 @@ pub struct Connection { | |
decoder: SlipDecoder, | ||
after_operation: ResetAfterOperation, | ||
before_operation: ResetBeforeOperation, | ||
pub(crate) secure_download_mode: bool, | ||
} | ||
|
||
impl Connection { | ||
|
@@ -139,6 +140,7 @@ impl Connection { | |
decoder: SlipDecoder::new(), | ||
after_operation, | ||
before_operation, | ||
secure_download_mode: false, | ||
} | ||
} | ||
|
||
|
@@ -449,11 +451,13 @@ impl Connection { | |
// - https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html?highlight=md5#response-packet | ||
// - https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html?highlight=md5#status-bytes | ||
// - https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html?highlight=md5#verifying-uploaded-data | ||
let status_len = if response.len() == 10 || response.len() == 26 { | ||
2 | ||
} else { | ||
4 | ||
}; | ||
|
||
let status_len = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could benefit from some comments, and perhaps a permalink to either the esptool impl, or the docs explaining this return data from the ROM bootloader. |
||
if response.len() == 10 || response.len() == 26 { | ||
2 | ||
} else { | ||
4 | ||
}; | ||
|
||
let value = match response.len() { | ||
10 | 12 => CommandResponseValue::ValueU32(u32::from_le_bytes( | ||
|
@@ -483,8 +487,8 @@ impl Connection { | |
return_op: response[1], | ||
return_length: u16::from_le_bytes(response[2..][..2].try_into().unwrap()), | ||
value, | ||
error: response[response.len() - status_len], | ||
status: response[response.len() - status_len + 1], | ||
error: response[response.len() - status_len + 1], | ||
status: response[response.len() - status_len], | ||
}; | ||
|
||
Ok(Some(header)) | ||
|
@@ -524,11 +528,10 @@ impl Connection { | |
pub fn command(&mut self, command: Command<'_>) -> Result<CommandResponseValue, Error> { | ||
let ty = command.command_type(); | ||
self.write_command(command).for_command(ty)?; | ||
|
||
for _ in 0..100 { | ||
match self.read_response().for_command(ty)? { | ||
Some(response) if response.return_op == ty as u8 => { | ||
return if response.error != 0 { | ||
return if response.status != 0 { | ||
let _error = self.flush(); | ||
Err(Error::RomError(RomError::new( | ||
command.command_type(), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -631,7 +631,7 @@ pub struct DeviceInfo { | |
/// Device features | ||
pub features: Vec<String>, | ||
/// MAC address | ||
pub mac_address: String, | ||
pub mac_address: Option<String>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The ROM bootloader doesn't send MAC in SDM? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, the MAC is read from efuse, but in SDM you can't read efuses, so that's the reason. I should probably add a comment to clarify this though, thanks! |
||
} | ||
|
||
/// Connect to and flash a target device | ||
|
@@ -674,6 +674,8 @@ impl Flasher { | |
connection.begin()?; | ||
connection.set_timeout(DEFAULT_TIMEOUT)?; | ||
|
||
let sdm = detect_sdm(&mut connection)?; | ||
|
||
let detected_chip = if before_operation != ResetBeforeOperation::NoResetNoSync { | ||
// Detect which chip we are connected to. | ||
let detected_chip = detect_chip(&mut connection, use_stub)?; | ||
|
@@ -709,11 +711,18 @@ impl Flasher { | |
|
||
// Load flash stub if enabled | ||
if use_stub { | ||
info!("Using flash stub"); | ||
flasher.load_stub()?; | ||
if !sdm { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you bring the |
||
info!("Using flash stub"); | ||
flasher.load_stub()?; | ||
} else { | ||
warn!("Stub is not supported in Secure Download Mode, setting --no-stub"); | ||
flasher.use_stub = !use_stub; | ||
} | ||
} | ||
|
||
flasher.spi_autodetect()?; | ||
if !sdm { | ||
flasher.spi_autodetect()?; | ||
} | ||
|
||
// Now that we have established a connection and detected the chip and flash | ||
// size, we can set the baud rate of the connection to the configured value. | ||
|
@@ -982,14 +991,25 @@ impl Flasher { | |
let chip = self.chip(); | ||
let target = chip.into_target(); | ||
|
||
let revision = Some(target.chip_revision(self.connection())?); | ||
// chip_revision reads from efuse, which is not possible in Secure Download Mode | ||
let revision = if !self.connection.secure_download_mode { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use https://doc.rust-lang.org/std/primitive.bool.html#method.then_some to remove the need for the if statements. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MabezDev Instead, me might want to use something like
|
||
Some(target.chip_revision(self.connection())?) | ||
} else { | ||
None | ||
}; | ||
|
||
let crystal_frequency = target.crystal_freq(self.connection())?; | ||
let features = target | ||
.chip_features(self.connection())? | ||
.iter() | ||
.map(|s| s.to_string()) | ||
.collect::<Vec<_>>(); | ||
let mac_address = target.mac_address(self.connection())?; | ||
|
||
let mac_address = if !self.connection.secure_download_mode { | ||
Some(target.mac_address(self.connection())?) | ||
} else { | ||
None | ||
}; | ||
|
||
let info = DeviceInfo { | ||
chip, | ||
|
@@ -1099,10 +1119,17 @@ impl Flasher { | |
let mut target = self | ||
.chip | ||
.flash_target(self.spi_params, self.use_stub, false, false); | ||
|
||
target.begin(&mut self.connection).flashing()?; | ||
|
||
for segment in segments { | ||
target.write_segment(&mut self.connection, segment.borrow(), &mut progress)?; | ||
if self.connection.secure_download_mode { | ||
target.write_segment_sdm(&mut self.connection, segment.borrow(), &mut progress)?; | ||
} else { | ||
target.write_segment(&mut self.connection, segment.borrow(), &mut progress)?; | ||
} | ||
} | ||
|
||
target.finish(&mut self.connection, true).flashing()?; | ||
|
||
Ok(()) | ||
|
@@ -1382,3 +1409,14 @@ fn detect_chip(connection: &mut Connection, use_stub: bool) -> Result<Chip, Erro | |
} | ||
} | ||
} | ||
|
||
fn detect_sdm(connection: &mut Connection) -> Result<bool, Error> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we detect sd mode in the normal detection routine, instead of doing it twice? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I.e, inside |
||
match connection.read_reg(CHIP_DETECT_MAGIC_REG_ADDR) { | ||
Ok(_) => return Ok(false), | ||
Err(_) => { | ||
log::warn!("Secure Download Mode is enabled on this chip"); | ||
connection.secure_download_mode = true; | ||
return Ok(true); | ||
} | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,15 @@ impl FlashTarget for RamTarget { | |
Ok(()) | ||
} | ||
|
||
fn write_segment_sdm( | ||
&mut self, | ||
_connection: &mut Connection, | ||
_segment: Segment<'_>, | ||
_progress: &mut Option<&mut dyn ProgressCallbacks>, | ||
) -> Result<(), Error> { | ||
todo!() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we can't implement this, this should return a nice error, not panic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If it can be implemented at some point, please also add a TODO with a relevant issue. |
||
} | ||
|
||
fn write_segment( | ||
&mut self, | ||
connection: &mut Connection, | ||
|
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.
Would be nice to have some details here, not really sure what this means TBH.