usbarmory.rs icon indicating copy to clipboard operation
usbarmory.rs copied to clipboard

Flash persistence / strategy

Open tarcieri opened this issue 6 years ago • 3 comments

We need to persist small blobs of data to the eMMC and/or SNVS flash, where small is ~1kB or (much) less.

In practice these blobs will be ciphertexts of configuration data and cryptographic keys encrypted by our hypothetical RTFM application or the DCP/CAAM for SNVS. I imagine we'll probably want to end up using both, e.g. SNVS for configuration and eMMC for other objects, but if we can even get just eMMC going that'd be great.

I can see a couple different ways of approaching this:

  • A traditional PIV-like "slot" identifier, i.e. an integer offset which identifies a fixed-size (e.g. 1kB) region in eMMC containing an (encrypted) object
  • Something more like a traditional filesystem. I'm curious about something like littlefs2 or a traditional FAT filesystem for this purpose (and definitely open to other suggestions)

If we can get some sort of filesystem solution going, provided it's robust I think it'd be preferred and much more flexible.

tarcieri avatar Jan 30 '20 17:01 tarcieri

After investigating littlefs2, it seems like its reference implementation is fundamentally limited to filesystems of a size of <4 GiB. This is due to the use of uint32_t in its API, I think the on-disk format could work with storage of up to 2^32 blocks, which is 2 TiB. Looking at the spec it seems like there are some operations that are linear in the size of the filesystem though (which seems odd), so maybe it's not meant to be put on bigger storage than 4 GB?

This leaves us with a few options:

  • Just use 4 GiB of the big partition with littlefs2 for now, "unlock" the rest later (by whatever means)
  • Create multiple 4 GiB partitions on the 16 GB eMMC, use littlefs2 on all of them and somehow make them work together
  • Write a patch to remove the limit (this would make littlefs2 more costly on 32-bit processors; the code might make some more assumptions, so this doesn't seem trivial; I'm also not good with C)
  • RIIR and remove the limit
  • Use a different filesystem that supports bigger volumes (exFAT comes to mind, but it seems much less reliable than littlefs2, and I don't think there's a Rust impl or good bindings to an impl)
  • Don't use a filesystem at all and go for the PIV-like disk format

Any thoughts? Did I miss any alternatives?

jonas-schievink avatar Mar 10 '20 13:03 jonas-schievink

littlefs is small enough (~4klocs of C) that rewriting it in Rust (possibly with a mechanical translation via c2rust or corrode) seems rather tempting. One of our selling points for Armistice is "pure Rust" so if we can avoid C it's a nice-to-have.

I should probably note that what we're really after is probably closer to an embedded database that's optimized for Flash/SSD (i.e. has wear leveling). Something like sled would be great but it appears to have a lot of std/OS dependencies at the moment.

Regardless, I plan on writing a storage adapter trait for Armistice so we can play with different options here. I thought a filesystem would be the easiest way to get started, but we can potentially look at other options.

tarcieri avatar Mar 10 '20 14:03 tarcieri

That sounds good. I'll finish the littlefs2 integration (with fs size limited to 4 GiB) since it's almost done anyways.

If you want to go pure-Rust, then it sounds like we might want to be going for option 2 in https://github.com/iqlusioninc/usbarmory.rs/issues/42 as well (ditch U-Boot and boot straight into the Rust firmware).

jonas-schievink avatar Mar 10 '20 14:03 jonas-schievink