Paul - that’s great. It sounds like this will work nicely, and we’ll get a bunch of extra code space on the Nordic.

I think it’s going to be important to very clearly call out to people that when using OS tasks with split image designs, the stacks need to be malloc’d. I’m not sure — maybe the nimble folks can chime in, in libraries where we create tasks, I assume we take a pointer to the stacks by default, and we don’t place them in .bss ourselves?

Sterling

On 20 Jul 2016, at 14:27, [email protected] wrote:

Update.

This effort is ongoing on a private branch so no need to worry about
changes yet . . .

I finished the recipe below and was able to create and run a split image.
I followed the steps below with some minor mods…

1) I did not build a temporary library.  Instead I just removed the
symbols from the .a’s in the app (actually renamed them so we could trace
back if this ever fails to work).  Then I link the app against its
libraries and also with a the .elf from the loader using
--just-symbols=loader.elf. This allows the symbols to properly resolve. 2) Instead of copying loader.elf and removing the symbols that were unused in the shared link, I renamed them with a _loader suffix. This probably
needs a bit more work, as I should probably copy the loader.
3) I didn’t merge any symbols from apps/app and apps/loader.  See
ramifications on stack usage below.

For a simple test I build two versions of blinky to run as a split
application: blinky runs as the loader app which blinks at 1Hz and blinky2
runs as the split app that blinks at 2 Hz. (NOTE: I have not added the
ability for the loader to validate and run the app yet, so I do this
manually through the debugger).

I get the following for image sizes.

Pauls-MacBook-Pro-4:src paulfdietrich$ newt size app
Size of Application Image: app
...
objsize
   text    data     bss     dec     hex filename
    896       4    4884    5784 
1698    /Users/paulfdietrich/dev/new_boot/bin/targets/app/app/apps/blinky2/bli
nky2.elf
Size of Loader Image: loader
...
objsize
   text    data     bss     dec     hex filename
   7684    1172    2376   11232 
2be0    /Users/paulfdietrich/dev/new_boot/bin/targets/app/loader/apps/blinky/b
linky.elf


You can see that most of the code (since most except startup etc are
duplicates) is in the loader app (7.6 k).  A small amount (896 bytes)
lives in the app. If I boot the system, it runs blinky just fine. If I
boot, set a breakpoint to main in blinky and set the PC to the reset
vector of the second image and continue, it runs the blinky2 just fine.
The debugger shows that code running os stuff from the first image
partition.  Success!!

When I did the same for two bluetooth apps (I used two identical copies of
bletiny), I could see that the loader was about 100k  and the app was
about 1k. Great news!! As this means we will have tons of app space for
bluetooth apps even with the whole stack present.

There was also an unpleasant surprise — RAM usage was bad for the app!!! I think this is because we put the loader stacks in BSS that we define in app/main.c. There is no way when linking the app against the loader to know that the BSS data from the loader is stack and re-use it— it could be global data that is uninitialized and used by the loader code when running as part of the app. There’s a simple fix, malloc stacks for the loader in
main.c instead of statically allocating them.

There’s still a lot to do to make this production ready, but this was the
highest risk part that I wasn’t sure would work.

The one tricky piece remaining is how to better compare a symbol to
determine its identical. Right now I use the name, and size, but compiler defines that are different between the two builds could cause this to fail (imagine a #define FOO 1 or #define FOO 2 inside some ifdef that is based upon a feature). So I am not sure what to do with this. I’ve almost convinced myself this won’t happen, but want to try to add something to
the code to validate — even if it just produces an error at the end.

That’s all for now. I still expect to be at this for a while to get newt
put back together, sort out how to debug this kind of thing, and most
importantly, write an real “loader app” that can download split images via
bluetooth and net_mgr.

Paul

On 6/27/16, 2:37 PM, "[email protected]" <[email protected]> wrote:

Im on to how to implement this in newt. Here are my thoughts for review.

I am not that familiar with Go or with Newt code, so I’m thinking the most
important thing is to get this to work and then figure out how to
re-architect this in newt to be “nice”. Here are roughly the steps I will
take.

Design
0) Modify the target.go to contain a
loader=<@apache-mynewt-core/apps/loader> or something that specifies an
app to run as the loader. Unless there is objections I will name this
‘loader’ or ‘split-loader'
1) Modify struct Builder Build.go. Factor out the following into a app
class since the split app target has two apps:    Packages, Features,
APIs, and BuildPackage into an app class. Put this into apps.go in some apps package. Then re-use this package to build dependencies and features
for the loader and app separately.
2) Modify Build.go to allow compile and link in two separate steps so we
can compile the app without having to link it right away.
3) Modify Build.go Builder to contain two apps (loader and app) instead of
1.  If the loader app was nil, that is OK.
4) Modify build to build the loader first if it exists (build and link). 5) Modify build to compile the app after the loader excluding linking. 6) Create a list of common packages. This would be done by comparing the two package lists in the two apps. If the two apps have the same package name, compare the .a files to make sure they are appropriately identical (since features and cflags can wreak havoc). Build a temporary library
split.a that combines all the packages.
7) Extract the symbols from loader.elf.
8) For each symbol in loader.elf. If the symbols in in split.A, remove it from split.a, else remove it from loader.elf. I’ll probably slurp in both
symbol files into maps so I don’t repeatedly call nm.
9) Link app.elf.


Please comment.  This feels like a lot of magic to me.

Paul

On 6/24/16, 3:47 PM, "aditi hilbert" <[email protected]> wrote:

That’s generally the practice for units in field where security is a
concern (e.g. industrial IoT devices).

aditi
On Jun 24, 2016, at 3:18 PM, will sanfilippo <[email protected]> wrote:

My expectation would be that the bootloaders would be locked down and
thus not upgradeable in the field…

Will
On Jun 24, 2016, at 2:04 PM, [email protected] wrote:

Thanks for the comments. I think there may be some nomenclature issues
here related to the bootloader.

In my design the bootloader is the fixed bit at 0x0 containing the
reset
vectors and the code swap and run PIR images.

In the Nordic docs (since we are sometimes focused on the NRF chips)
they
call this the MBR. The bootloader in NRF-speak is another app that can
be
loaded that can replace the soft device (but I don¹t think it replaces
the
MBR)

Paul

On 6/24/16, 1:43 PM, "marko kiiskila" <[email protected]> wrote:

Hi all,

On Jun 24, 2016, at 1:16 PM, David G. Simmons <[email protected]>
wrote:


On Jun 24, 2016, at 12:55 PM, [email protected]
<mailto:[email protected]>
wrote:

I think your main concern was about boatload upgradability.  My
assumption
was that in the field you would NOT upgrade it. From what I have
heard,
most folks lock the flash sectors of the boot loader before
shipping.
This is a larger question for the group. How do others feel about
boot
loader upgrade. Regarding your upgrade procedure below, if a boot
loader
upgrade fails in step B, the thing would become a brick.

You¹re right that this is probably a larger discussion regarding the
filed-upgradability of a bootloader.

That being said, I¹m not sure how a failure in step B yields a
brick.

This would be power outage/system reset when BIR is erased, and new bootloader has not been copied in yet. MCU always starts executing
whatever
is in BIR at reset.
Because of this time window, I would not update boot loader.

Here¹s a scenario for an upgradeable bootloader:

1) Bootloader is signed with a SHA or PKI from a host computer
only
bootloaders signed with this key will be accepted except over
direct
serial/jtag connection. If you have physical access to the device,
you
win. This also allows a new host to Œtake over¹ responsibility for
delivering bootloaders to devices by providing a new bootloader
with a
new SHA/PKI key.
2) new bootloader image is sent to the device and stored in SAR ‹
could
be stored in SIR
a) new bootloader key is checked against current bootloader key.
If
keys don¹t match, new bootloader image is erased otherwise continue
                b) Keys match, so new bootlaoder is written to PIR and device
reboots
to new bootloader
                c) if boot to new bootlaoder in PIR succeeds, PIR region is
written
to BIR and reboots ‹ we have successfully updated the bootloader
                d) if boot to new bootloader in PIR fails, reboots to old
bootloader,
and PIR is erased.

This has the advantage ‹ by first loading the bootloader into SAR
for
key
validation ‹ of ensuring that a rogue bootloader does not wipe out
an
existing AIIC/ADIC pair. It required 3 reboots to field-upgrade a bootloader, but it maintains system integrity. Using this method, bootloaders could be updated over bluetooth as well, as long as the
keys
match, making filed upgrades of bootloaders possible.


In step B, the new bootloader is in PIR while the old bootloader
remains in BIR. System reboots to PIR. If that fails, meaning the
new
bootloader is bad, it simply reboots our of BIR (the old bootloader,
and
erases the bad bootloader in PIR. If it succeeds, meaning the new bootloader is good, it copies itself to BIR and reboots from BIR,
then
erases PIR and is ready for an application to be sent.


Bootloader code is not position independent. Maybe it¹s possible to
do with the later versions of gcc, but it was not the last time I
tried.
I was not able to figure out how to keep .data/.bss at fixed offset,
while
allowing .text to float. The bootloader at mynewt does place quite a few things at .data/.bss, so some rewrite would be needed (assuming
gcc does not have this feature for our target CPUs).







Reply via email to