-
Notifications
You must be signed in to change notification settings - Fork 687
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
[RFC] Tock Attributes #695
Comments
Given that the stated goal is to tie metadata to binaries, does it make sense for binaries to be able to edit their attributes? I think I would expect attributes to be exclusively read-only. Existing Implementations One of the listed advantages is parallelism about how attributes are stored. However, my reading of this section is that the bootloader and apps currently employ different on-disk storage of attributes? Is this a desired intention on an anachronism of current implementations? Bootloader implementation Currently, there is a whole page dedicated to relatively little information (the first page). Given that The space-saving becomes more relevant if we choose to use the same layout for attributes in all cases. Kernel attributes implementation I am inclined to lean towards option 1, or something akin to it. Tying correctness to the tool used to get bits on the board (a) perhaps ties Tock too strongly to tockloader, but more importantly (b) loses the property that all relevant implementation is stored in the binary image -- a kernel that runs correctly when flashed with some tockloader flags but then fails if a flag is forgotten by someone else feels dangerously fragile. Some specific thoughts for how to implement this, the cargo/rust build process could simply allocate an empty array in the kernel binary. The attribute location is by definition at a fixed offset and known size, so any tool could write bits to the right place in the binary image. This approach is somewhat analogous to an Concrete questions that I think inform the implementation: What attributes should/need to be attached to the kernel, and where is that information available?
|
I don't think that has to be the case. The apps location could move, an encryption key could change, the kernel location could move, etc. Tying to the binary is more of a spatial relationship than thinking of an application binary as immutable.
Well we stabilized app binaries so that is fixed. We could in theory use TLVs for the other attributes, but that would either mean specifying the format of a lot of attributes, or using a generic key-value TLV but with more overhead for the type field.
We could, but we should probably start with the reserved flash after the bootloader and before the kernel. Also we can't change apps now.
This is interesting. We currently have a basically unused feature in TABs where a TAB can specify compatible boards (where the board is identified by a bootloader attribute). Extending this idea to required syscall interfaces could be interested. Although we would get benefit immediately if we actually used the supported board feature (e.g. so you dont run the wrong BLE apps for your board). |
Fair points. The other thought I'd had is that in some cases one might imagine that attributes are written to immutable storage of some kind, so baking in an assumption that they could be writable felt dangerous. On the flip side, however baking in the restriction that they can't be written is probably a premature restriction. I think leaving them as possibly writable make sense. ✅ TLV vs Key-Value for bootloader/kernel attributes TLV
KV
Putting it after the kernel is fine, but I think we should collapse the page. The current scheme feels needlessly wasteful. Any of the extensibility we want from flags I think we can realize with attributes (or a much smaller number of flags)
Indeed. I've mixed up nrf52 vs hail BLE apps more than once :(. Think we're agreed here. Do we have other examples of things that make sense as kernel attributes? I'm trying to gauge if anything that we'd want to include as an attribute should push the implementation one way or another. |
[Meta-comment on RFC process]: I understand now why the Rust model is a PR with a text file with the body that's in Brad's top-level comment. As we start to reach consensus on some ideas, it'd be nice to update the document to realize a desired final form, but that feels a bit awkward if I just edit the top-level comment. |
The "pre-page" I purposefully left out because that was more of a hack than anything, and really is just there so that Tockloader knows if there is a bootloader or not. But even with that, it's only 6 pages of flash, or 3072 bytes, or 0.6% of the SAM4L flash. We allocate 128 pages of flash to the bootloader, but only use about 70 of them. I guess I just don't think that flash space matters in this case. Also we have to be needlessly wasteful to reserve space for future attributes. |
I think app location in particular is not a great motivating example since we're liking to change who loads applications and how in the future. Maybe better motivating example (which I think fits your model mostly) are things like the device address for, e.g., Bluetooth or 802.15.4. These are particular good examples because it makes sense to tie them to the kernel and it makes sense to let external tools modify them --- consider provisioning a fleet of devices by flashing the same kernel binary and also updating the address attribute with a unique address for each. |
RE: TLV vs Key-Value, a few points
|
Revisiting this, I'm in favor of going with:
Btw, it's perfectly reasonable to, for example, generate something like csv file when building the kernel with default values that tockloader can consume. |
If we have no intention of having the kernel setting its own attributes, then it doesn't seem to make sense to have the kernel have attributes. However, for boards without a bootloader, it can still be useful to have a section for attributes. So I propose:
This makes it easier on the tools which only need to look in one spot for all boards. Also, there are 16 key-value slots, and we are only using I think 5 at the most currently, so we should have enough space for all of the attributes a board could need. This is I think entirely consistent with what Amit proposed above. |
I think I'm broadly in agreement here, but I'm not quite sure how this should be handled by the tooling. If the attributes can be part of "either" flash, what tool is responsible for writing them (both?). How do the tools find the attributes to set? What happens if the bootloader's view of the attributes to write conflict with the kernel's? Should the attributes perhaps instead be part of neither flash, and written independently (possibly by tooling as one of the |
I don't think it matters what writes the attributes, just that they are always in the same spot on every board. I think it makes practical sense to have the board bootloader bake in attributes that are board specific, and then tockloader can write more if needed. |
Appending board attributes feels fine, my only concern was getting into a situation where the underspecification caused tools to inadvertently fight and overwrite attributes. I think we're at consensus here. Perhaps we should start |
Agree on consensus. |
Vision
High level goal: all binaries in a Tock system (bootloader, kernel, apps) have metadata stored at or near the beginning of their flash region. The metadata should be coupled with the binary it is relevant to.
Contents at each layer
bootloader: The bootloader metadata should contain two types of data:
kernel: The kernel metadata holds certain parameters of the kernel that could change over the lifetime of the device and that the kernel needs to know after a power cycle. In particular, this would include the address where apps are located in flash. We use
_sapps
now, but a future system may want to place new apps later in flash and change which apps are active while not losing an older copy of the apps. Another attribute may be the git commit hash or the version of the compiled kernel.apps: This is the content in the TBF header. It specifies the size of the app and where the first instruction is, among other things.
Advantages to this approach
Disadvantages to this approach
Implementations
We currently have implementations for the bootloader and apps.
Bootloader
All metadata is stored in two flash pages after the vector table for the bootloader. Attributes are stored as key-value pairs, where the key can be up to 8 bytes and the value can be up to 55 bytes (one byte is for the length of the value). There are up to 16 supported attributes.
The attributes are created by a special C struct hand-crafted in the bootloader source.
Apps
All metadata for apps is stored at the beginning of their flash blob. The header is composed of TLV elements, and more documentation is here.
The TBF header is generated by the
elf2tbf
tool after the app is compiled.Proposed Implementations
Kernel
The kernel would get attributes that match the attributes in the bootloader. Two pages of flash after the vector table would be set aside for attributes in the same key-value format. The linker would ensure those pages are available.
Implementation option 1
The attributes are created by the
build.rs
file as a part of the compilation step. This works by creating the structs that are hand crafted in the bootloader automatically and including the generated source file in the build. See this pull request for how that might look.Implementation option 2
The space for the attributes is reserved by the cargo build process in the kernel binary, but the actual population is done by tockloader. A new command is added to tockloader (maybe
flash-kernel
) that would populate the attributes as it flashes the kernel to the board.This is easier to implement, but doesn't quite work if a platform doesn't use tockloader.
Alternatives
We already have bootloader and app metadata structures. We just leave those, don't add kernel metadata, and figure out what to do on a case-by-case basis as things come up. For example, the imix kernel moved where apps go, and tockloader needs to know that. To address this, tockloader was run with the
--app-address
flag, and we have now added a bootloader attribute that specifies where the apps go that tockloader will use if it exists.The text was updated successfully, but these errors were encountered: