-
Notifications
You must be signed in to change notification settings - Fork 2k
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
cpu: add flash_writable section to linker script #17436
Conversation
The nrf52840dongle bootloader mechanism has an option PARTICLE_MONOFIRMWARE_CHECKSUMLIMIT that makes it checksum just the header, so this is not strictly necessary. It may well make sense to do this, especially if we decide that it's legitimate for bootloader to verify the image's integrity, and conversely necessary for any flash writer to declare the flash region. I suggest that As we define that region we may also want to consider whether in that region it's legitimate to execute code from. I don't know if any of the MPUs around support that, but setting that section non-executable may be a good idea. (That should not be acted on in this PR, but a note on the documentation of that new region could say something like
). |
Are you sure that the Open USB bootloader of the I will rename the section as you suggested. |
It's not a feature of the bootloader but of how RIOT uses it: when the checksum is built, the checksummed area is just set to a shorter length
|
8e1af62
to
efa2b4b
Compare
@chrysn I updated the section name to be |
from a quick look (currently on the road): any idea where this section could be documented? if not, i'd like to instigate some documentation on the linker scripts and sections (which would then take over documenting this).
i can do a full implementation review later (incl tests), but would appreciate a high-level review ("is having a dedicated section for any writable parts of flash the way to go?") by someone who knows which trickery is hidden in our linker scripts.
|
No me neither. I think documenting RIOT specific linker scripts and sections is a good idea. This would have helped me on multiple occasions.
That would be great ! Do you know anyone I could ping for the high-level review ? |
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.
Running the test on native segfaulted -- not much of a surprise, and "it's out of scope" is an acceptable approach, but I'd like to see this fail somewhat cleanly. I don't have a clue yet how to best do that -- could be a feature of the board that's checked before offering the test (the feature would indicate that this works, and might be unset eg. when a board's bootloader rules out flash modifications inside the firmware-updated area), might be a runtime success check or might be something else.
I've also cleared this for CI runs; looking good so far.
@@ -236,4 +236,8 @@ SECTIONS | |||
.end_fw (NOLOAD) : ALIGN(4) { |
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.
In particular (from looking at occurrences of end_fw
), this puts it in conflict with flashpage_first_free
-- as flashpage_first_free
looks at end_fw
, pages used in flash_writable
would also show up in flashpage_first_free
. I see this as a successor to flashpage_first_free
anyway, but they should still not conflict. If end_fw
is not used anywhere else, it might suffice to swap them around so that flash_writable is before end_fw.
(My impression from git praise
is that end_fw
is exclusively used for flashpage_first_free
-- if not, additional questions would be raised as to whether statically initialized content does actually get flashed.)
43f5a18
to
e2041cf
Compare
Since the section is not part of the firmware I can not statically
initialize the memory.
Is it not? What makes it not? AFAIK, none of the bootloaders or
programmers look at "end_fw" or other markers, they just put everything
that is in ROM onto the chip. (Statics without initial value are
probably zero-initialized.)
|
This is due to the section being defined as |
Many use cases can benefit from this data section. We saw the need in previous flashage discussions (related to FIDO2). More generically, all sorts of non-volatile key- or configuration storages would make use of it.
To me, that is a totally legitimate assumption (what does RIOTBOOT do?). The ARM PSA specification, for example, requires a root of trust which includes the trusted system startup.
+1 |
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 would be nice to extend the automated test script with the new command introduced in tests/periph_flashpage
. This way there's a simple way to automatically test this feature on various boards.
tests/periph_flashpage/main.c
Outdated
@@ -643,6 +688,7 @@ static const shell_command_t shell_commands[] = { | |||
{ "edit", "Write bytes to the local page buffer", cmd_edit }, | |||
{ "test", "Write and verify test pattern", cmd_test }, | |||
{ "test_last_pagewise", "Write and verify test pattern on last page available", cmd_test_last }, | |||
{ "test_res_pagewise", "Write and verify short write on reserved page", cmd_test_res}, |
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.
The name of this command is confusing: res
can be confused with result
. Better be explicit and call it test_reserved_pagewise
or something the 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.
Fixed and I also added the command to periph_flashpage/tests
e2041cf
to
1b046de
Compare
Frankly I don't see what On platforms that do have (some of their, at least the part in flash_writable) flash memory address-mapped, this should be the preferred mechanism. On others, users will need to make usable page numbers appear out of thin air, but then these platforms (and I think it's just native) hopefully have a means to do that. (One might even consider playing with the linker script of native, and make the flashpage implementation of native map the file in with mmap, strongly asserting (backed by the linker script's configuration) that the kernel will indeed map the backing file into the right location), [edit] but that's out of scope for here. |
So, I had a chat with @bergzand about the Based on this I think that the feature introduced with this PR should be dependent This will exclude platforms that don't have a constant page size from this @chrysn I would really like to move on with this. Can you please look at the changes and tell me what is missing ? |
I can't do a comprehensive review right now, but I can add a few questions:
I'll give this a final review once those two are answered and/or addressed [edit: but don't see anything showstopper-wise left]. |
Good question. I think I added this ALIGN before adding the Anyways, I removed the usage of
Done ! |
@chrysn could you please look at the latest changes and make a final review if possible ? |
OK, so for tests I've performed:
Test on particle-xenon in riotboot partition 1Flashing command:
Output (help output removed):
Modifications and outputdiff --git a/tests/periph_flashpage/main.c b/tests/periph_flashpage/main.c
index cff25750ab..5bfbd16280 100644
--- a/tests/periph_flashpage/main.c
+++ b/tests/periph_flashpage/main.c
@@ -64 +64 @@ static uint8_t page_mem[FLASHPAGE_SIZE] ALIGNMENT_ATTR;
-FLASH_WRITABLE_INIT(_backing_memory, 0x1);
+FLASH_WRITABLE_INIT(_backing_memory, 59);
@@ -69 +69 @@ FLASH_WRITABLE_INIT(_backing_memory, 0x1);
-FLASH_WRITABLE_INIT(_abacking_memory, 0x1);
+FLASH_WRITABLE_INIT(_abacking_memory, 59); Output (help output removed):
By the way, this shows a flaw in the last_pagewise test: It writes to the "last free page" (255) even though the first free page (256) indicates that there are simply no free pages at all -- thus destroying "data" in the area set aside by one of the new reserved pages. Given that that API is becoming deprecated and it's just a flaw in the test (albeit one that a user might create themselves as well), that's likely not too bad -- just please be sure to follow up with that deprecation.
So content-wise I'm happy; please adjust the commit and message, and then this can pass. |
(Also, with my recent forays through MTD, I think this might be great to combine with an add-on routine that sets up the mtd_flashpage and mtd_mapper to make the flash-writable area available to flash file systems, but that's a different PR.) |
Thanks for testing !
Yes I am planning to deprecate the
Done :) I split up the commits into three commits. One for the feature, one for the macro and one for the changed tests. |
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.
Thank you, and ACK.
CI is complaining about discrepancies between feature names. Looks like an easy name mismatch (one name has an |
... Sorry for that. Yes I meant to use |
Contribution description
This PR adds an
.flash_writable
section to all CPUs implementing the flashpage API.This section enables modules to reserve flash memory at build time. This ensures that
different modules don't corrupt each others data by accidentally writing to each others flash pages.
Furthermore this approach will throw and error at build time if not enough flash memory is available.
To reserve flash memory one has to simple declare an array that is properly aligned and stored in the section e.g.:
static const uint8_t _backing_memory[FLASHPAGE_SIZE] __attribute__((aligned(FLASHPAGE_SIZE))) __attribute__((section(".flash_writable")));
The section is not necessary in most cases. The only case I know of where it is needed is for the
nrf52840dongle
.There, reserving flash memory with a const buffer (
static const uint8_t _backing_memory[FLASHPAGE_SIZE] __attribute__((aligned(FLASHPAGE_SIZE)));)
is not enough since this buffer will be put in the.rodata
section which is write protected by the default USB bootloader. Writing to this flash region will cause the dongle to go back into bootloader mode. Declaring an explicit section in flash memory fixes this problem because the buffer will no longer be stored as part of the.rodata
section.Even if the
.flash_writable
section is only necessary in one case I still think it is reasonable to explicitly declare a section in flash memory where applications can store persistent data. This also allows for giving the section an explicit size.Testing procedure
To test the functionality I added the
test_res_pagewise
command totests/periph_flashpage
.Issues/PRs references