-
Notifications
You must be signed in to change notification settings - Fork 11
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
[RSDK-6253] Update a device's image while retaining credentials data #204
[RSDK-6253] Update a device's image while retaining credentials data #204
Conversation
micro-rdk-installer/src/main.rs
Outdated
// let mut flasher = connect(&args.connect_args, &config, false, false).unwrap(); | ||
flasher | ||
.read_flash(nvs_offset, nvs_size, 0x1000, 64, nvs_path.clone()) | ||
.map_err(Error::EspFlashError)?; |
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.
stuck here for some reason. keep getting a (CorruptData(4096, 4039)
, where 4096
is the read block size, and 4039
is the size of the chunk that was read.
This step is for retrieving the actual NVS data and not just partition info.
Trying to read the full image at the start (before parsing the running partition table) fails with this error as well.
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.
Note: related?
espressif/esptool#823 (comment)
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.
is the stub properly loaded? https://docs.espressif.com/projects/esptool/en/latest/esp32/esptool/flasher-stub.html
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.
have not checked the stub. new changes made this part unnecessary
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.
LGTM, waiting for resolution of the two comments in this review and for me to give it a quick test
micro-rdk-installer/src/main.rs
Outdated
if old_ptable != new_ptable { | ||
log::error!("partition tables do not match!"); | ||
log::error!("rebuild and flash micro-rdk from scratch"); | ||
return Err(Error::BinaryEditError(64)); |
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.
why 64? I suspect this isn't an error regarding binary size specifically (although to be fair BinaryEditError
is not a good name for that error). If so, could you make a new variant in the error enum for this (and rename BinaryEditError
)?
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.
you're right, that's residual and was the closest thing I could find at the time. nice catch!
micro-rdk-installer/src/main.rs
Outdated
log::info!("Connecting..."); | ||
let mut flasher = connect( | ||
&args.monitor_args.connect_args, | ||
&monitor_args.clone().unwrap().connect_args, |
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.
I see we're assuming monitor_args
is always some flash_args.monitor
is true. Instead of assuming, could we check that we're in a valid state regarding these two settings (and return an error if we're not)?
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.
actually, it might not be necessary anymore for MonitorArgs
to be Option
. checking nowa
At the time when I was still determining the fields for AppImageArgs
, if two re-exported commands (FlashArgs
, WriteArgs
, MonitorArgs
, etc) had duplicate fields due to nesting, a runtime panic would happen.
This was a workaround for that, but is no longer necessary.
micro-rdk-installer/src/main.rs
Outdated
.map_err(Error::FileError)?; | ||
|
||
let file_len = app_file_new.metadata().map_err(Error::FileError)?.len(); | ||
if file_len < PARTITION_TABLE_SIZE.into() { |
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.
looks weird to me shouldn't it be PARTITION_TABLE_SIZE+PARTITION_TABLE_ADDR?
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.
you're right, changed.
1807f90
to
737a524
Compare
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.
LGTM
fn flash(args: WriteFlashArgs, config: &Config, app_path: PathBuf) -> Result<(), Error> { | ||
fn flash( | ||
flash_args: FlashArgs, | ||
monitor_args: MonitorArgs, |
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.
Why do we pass MonitorArgs now? what's the upside? how does the new invocation looks like?
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.
many of espflash
's method's, such as Flasher::connect
, take these structs as parameters. Sadly, because the structs are all annotated as non-exhaustive
, they can't just be initialized directly within our functions (ex let m_args = MonitorArgs{..}
).
This means that the only way we can create these input arguments is via clap.
cargo-espflash
highlights this in that it also passes all there structs directly or with a thin wrapper.
In addition, we have to be mindful about what espflash
Commands we wrap in our own because the flattened fields of all inner commands must be unique, which sadly isn't always the case. espflash
as a library isn't very ergonomic.
The new invocation is cargo r -p micro-rdk-installer -- update-app-image --bootloader target/xtensa-esp32-espidf/esp32-server.bin
, with the breaking change being the --bootloader
flag to specify the binary. Bumping espflash
to 3.0 was a breaking change so it seemed an opportune moment to also have breaking change for the installer.
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.
feels counterintuitive to use bootloader
to pass an app image via a bootloader flag we should add a bin
or app-bin
arg.
micro-rdk-installer/src/main.rs
Outdated
0x1000, | ||
64, |
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.
What is the origin of these values? Why are they correct? When, if ever, might they need to be updated? Let's add some comments or declare some named constants.
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.
they're default values used in espflash
. will add comments about it
micro-rdk-installer/src/main.rs
Outdated
.map_err(|e| Error::PartitionTableError(e.to_string()))?; | ||
|
||
log::info!("Retrieving new image"); | ||
let tmp_new = tempfile::Builder::new() |
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.
Similar question re why not just tempfile::tempfile
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.
similar to above, except it's how our download_micro_rdk_release
uses paths and not just something that takes Read
.
micro-rdk-installer/src/main.rs
Outdated
.prefix("micro-rdk-bin") | ||
.tempdir() | ||
.map_err(Error::FileError)?; | ||
let app_path_new = match &args.flash_args.bootloader { |
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.
Why bootloader
here? Not saying that it is wrong, just a little surprising.
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.
It's just how espflash's clap structs have things named. Not a huge fan of it
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.
renamed it to binary_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.
Code is looking pretty good, though I think there is a related temp file API that would let you avoid needing to come up with names of your own but still gives you paths.
I did note that it appears that the partition table offset can be adjusted via sdkconfig. I'm not sure what we ought to do about that. I'd be fine with the answer being "nothing" or "ticket it".
@@ -24,6 +26,14 @@ use secrecy::Secret; | |||
use serde::Deserialize; | |||
use tokio::runtime::Runtime; | |||
|
|||
const PARTITION_TABLE_ADDR: u32 = 0x8000; |
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.
Apparently though, this can be adjusted at build time: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/kconfig.html#config-partition-table-offset.
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.
An option would keep a list of possible values we use and iterate through it when trying to extract the partition table.
Currently, even espflash
hardcodes it.
A perfect solution would involve fetching/initializing the sdkconfig, parsing it, using that info when extracting; which may not match if the sdkconfig changed this default address between the old and new app images.
Either way, it's an optimization at best and new feature at worst. Better left to another ticket if we want to look closer at this. I vote leaving it as-is for now and make a ticket when it becomes necessary. This will error at that time.
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.
I'm fine with going forward with the hard-coded value give that espflash does the same.
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.
This LGTM though I share @npmenard's concerns about the use of the term bootloader
.
@@ -24,6 +26,14 @@ use secrecy::Secret; | |||
use serde::Deserialize; | |||
use tokio::runtime::Runtime; | |||
|
|||
const PARTITION_TABLE_ADDR: u32 = 0x8000; |
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.
I'm fine with going forward with the hard-coded value give that espflash does the same.
I can't invoke |
tested with local app image on running device:
cargo r -p micro-rdk-installer -- update-app-image --binary-path target/xtensa-esp32-espidf/esp32-server.bin
The
update-app-image
command does the following in sequence:Modifications are restricted to just the factory partition, leaving pre-existing NVS data intact.