PINE64
common bootloader? - Printable Version

+- PINE64 (https://forum.pine64.org)
+-- Forum: PineTime (https://forum.pine64.org/forumdisplay.php?fid=134)
+--- Forum: Development Discussion on PineTime (https://forum.pine64.org/forumdisplay.php?fid=136)
+--- Thread: common bootloader? (/showthread.php?tid=8496)

Pages: 1 2


RE: common bootloader? - danielt - 05-04-2020

(05-02-2020, 03:45 AM)JF002 Wrote: For now, I'm doing some researches on another options : The application is responsible for the download of the new firmware image and for storing it in the memory. Then, the bootloader (which does not embed the ble stack) can detect that a new image is available, swap it with the current one and provide a way to rollback the update if it fails.
The advantage is that the firmware is free to use the BLE stack of its choice, but of course, it is still possible to 'brick' the watch if you flash a firmware that does not allow to OTA another firmware...

A bootloader that doesn't embedded a BT stack doesn't necessarily have to brick on bad updates.

In addition to the relatively small internal flash there is the much larger SPI flash. This allows a bootloader to have three boot slots: main slot in internal flash and two slots in external flash for upgrade image (to replace internal flash) and recovery (simple BLE application that can download a new image and write it into the upgrade slot).

Roughly speaking the upgrade image allows progression from tested image to tested image whilst being robust (and allowing rollback) if the upgrade is broken. The recovery slot is primarily to guard against bricking if both main and upgrade slot have become damaged (e.g. 50 day bugs).


common bootloader? - lupyuen - 05-07-2020

Yep I'll be supporting External SPI Flash for storing the Standby Firmware Image... But first I will have to make MCUBoot work with Internal Flash :-)

MCUBoot currently supports only 2 Firmware Images: Active and Standby. The new firmware image is downloaded directly into the Standby slot. After downloading the new firmware, MCUBoot swaps the Active and Standby images. The swap also happens when rolling back to the previous firmware.

Is this good enough? Or do we need 3 images?

BTW my article has been updated with details of the NimBLE Bluetooth stack: https://lupyuen.github.io/pinetime-rust-mynewt/articles/dfu

Sent from my Pixel 4 XL using Tapatalk


RE: common bootloader? - danielt - 05-07-2020

(05-07-2020, 09:35 AM)lupyuen Wrote: Yep I'll be supporting External SPI Flash for storing the Standby Firmware Image... But first I will have to make MCUBoot work with Internal Flash :-)

MCUBoot currently supports only 2 Firmware Images: Active and Standby. The new firmware image is downloaded directly into the Standby slot. After downloading the new firmware, MCUBoot swaps the Active and Standby images.  The swap also happens when rolling back to the previous firmware.

Is this good enough? Or do we need 3 images?
Both? Big Grin
I definitely don't think any quibbles about the recovery partition should be allowed to slow down any kind of proof-of-concept development. The only thing I think that should be done at the proof-of-concept stage is to reserve the space for it in the default SPI flash layout: repartitioning flash devices always results in more pain than you think it will... so better to reserve the space early.

Nevertheless I do think it will be needed in the long term. mcuboot is based around active/standby images but they did have to accept reality and also offer a UART based loader system (the BOOT SERIAL mode) to cope with emergencies such as both images being inoperable (e.g. a bug that prevents boot but has been dormant until after the point it exists in both images). The PineTime cannot implement BOOT SERIAL mode so I think a third boot slot is useful to handle emergencies. The code should be very simple because it will nothing except copy the recovery image to the application slot overwriting whatever is there. No slot exchange, no backing up slot 0, just a couple of files from nrfx and maybe 150 lines of C. 

PS If you are getting to grips with how to write to flash then take a look at the tool I use for OTA updates to wasp-bootloader since it ends up as an example of how easy using nrfx is. Some of the nrfx drivers can't be used from a bootloader but the nrfx driver for the NVM has a liberal software license, minimal dependencies and doesn't use interrupts makes into super easy to integrate:
https://github.com/daniel-thompson/wasp-reloader/blob/5e9a1c85509130af123735aa550ef36b53f772b7/src/flash.c#L31

Oh yes... and if you want to reuse anything from wasp-os (the code to put up a splash screen in the bootloader for example) then let me know. I'm happy both to clean it up for reuse and to relicense if needed.


common bootloader? - lupyuen - 05-08-2020

Cool thanks, that will be very helpful when I'm testing DFU :-)

Sent from my Pixel 4 XL using Tapatalk


common bootloader? - lupyuen - 05-09-2020

Now that I have written up most of our proposed plan for flashing PineTime over Bluetooth (a.k.a. DFU)...

https://lupyuen.github.io/pinetime-rust-mynewt/articles/dfu

...I realise that DFU may be difficult to implement across all PineTime firmwares.

(1) For Mynewt, Zephyr, RIOT and FreeRTOS: DFU seems easier to implement because they are already supported by NimBLE and MCUBoot.

(2) For other firmwares: Porting NimBLE and MCUBoot may be a challenge. Especially unusual ones like Rust Embedded and Tock OS.

Can we support DFU for (2)? Possibly...

(a) We shall support Firmware Rollback (according to the proposed design). And assume that we shall store the Standby Firmware in External SPI Flash (instead of hogging up precious Internal Flash).

(b) We shall also allow the user to initiate a Firmware Rollback manually. Say, by pressing and holding the watch button for 5 seconds when the watch boots up. (MCUBoot will wait 5 seconds before starting the watch firmware)

© Assume that PineTime will be shipped with a firmware that supports the standard DFU described in my article. Could be Mynewt, Zephyr, RIOT, FreeRTOS, ...

(d) If the user wishes to install another firmware, say, Tock OS, just do it with DFU. PineTime already supports DFU out of the box.

(e) What if the user decides to upgrade Tock OS? Or switch to another firmware? Solution: The user manually initiates Firmware Rollback: Press and hold the watch button for 5 seconds while it reboots.

(f) MCUBoot recovers the factory-installed firmware (because of the rollback). PineTime now supports DFU again, ready to be flashed via Bluetooth.

Yes this scheme sounds cumbersome, but it means we can support some kind of DFU for ANY firmware without having to port NimBLE. As long as the firmware satisfies these conditions...

(1) The firmware must occupy ROM address 0x8000 onwards (It shouldn't use addresses below 0x8000)

(2) The firmware must not modify the Standby Firmware Image in External SPI Flash

(3) The firmware should contain a 32-byte Image Header (described in my article). So that MCUBoot knows how to swap the firmware with the factory-shipped one.

Should we do this? Is there a better way? Please lemme know thanks [emoji3]

Sent from my Pixel 4 XL using Tapatalk


RE: common bootloader? - danielt - 05-11-2020

Most of the feedback is stuff I've mentioned before in other thread (but lets get is all in one place):

Ideally the active slot would start at 0x00001000 in order to permit SoftDevice firmware to run. This implies linking mcuboot at the end of FLASH (rather than the beginning) and providing a simple binary to load in the first 4k of FLASH. The initial version of this simple binary really can be *very* simple... just setup the vector table to point to mcuboot and jump to the mcuboot reset vector. It might eventually need a couple of extra tweaks but for early development it is all that is required.

Additionally when you talk about "support for DFU" I think there really are *two* use-cases hiding behind that:

1. An application that, when operating normally, that permits DFU by providing BLE interfaces that allow the standby slot to be modified (alongside its other duties running the watch). This is the normal case for production devices and works well when the images are reasonably well controlled (e.g. tested prior to update, etc) and where updates are secure (signed, no promiscous pairing, etc).
2. A recovery mode, triggered by some special action by the user of the device, which is used when the active application is no longer capable of booting to the point that DFU works.

In the last post you describe a recovery mode that works by swapping the active and standby apps. This assumes that the DFU definitely works in the standby app and I remain worried that that. Given the standby app in this case is a real smartwatch app that performs duties beyond offering OTA DFU there is too much risk that other changes on the system could render it inoperable (maybe it has a but where it crashes at boot when it tries to decode a corrupted or missing image from the external FLASH). It is for these reasons that I advocate implementing recovery mode as a special case that is fully independent of the active/standby swapping code.

How the recovery code works is secondary... I have proposed the recovery slot idea but what really matters is the use-case. In other words I don't think it is sufficient to rely on two closely related smartwatch images (e.g. two slightly different versions of a same zephyr app) *not* to contain the same latent bug that will brick the watch if it is ever triggered.