diff --git a/examples/osd/ota-update/README.rst b/examples/osd/ota-update/README.rst index ecc1c823d..a2cde4c7b 100644 --- a/examples/osd/ota-update/README.rst +++ b/examples/osd/ota-update/README.rst @@ -3,12 +3,114 @@ OTA Update ========== OTA stands for "Over the Air". OTA update is used to flash a new -firmware to a device over the air. This document (some of) the -requirements for OTA. +firmware to a device over the air. This documents (some of) the +requirements for OTA and how to use the current prototype +implementation. + +For the impatient +================= + +First see the Security note below. + +Then, if you've decided you want to try this: This is experimental code, +use at your own risk. + +OK, how to run this: +There is now a new make variable that determines which image (the one +for the upper or the one for the lower half of flash memory) is to be +built. Set :: + + BOOTLOADER_PARTITION=0 + +for building the first partition (the default) or set it to 1 for +building the second one. + +There are now two ELF files, ``ota.osd-merkur-256.0`` and +``ota.osd-merkur-256.1``. From each of these two .hex files can be +generated (we're describing only the files for the first image, the +filenames of the second image are determined by replacing '0' with '1' +in the following): + +- ota.osd-merkur-256.0.hex is the file used for OTA update +- ota.osd-merkur-256.0-combined.hex is the file used for uploading via + the bootloader. This file has an additional section that contains a + copy of the irq-vector table (see below for further details). This is + only necessary if you're using the latest bootloader. + +To upload an image via OTA: + +- Create the ``.hex`` file with:: + + make TARGET=osd-merkur-256 BOOTLOADER_PARTITION=1 ota.osd-merkur-256.0.hex + +- Generate the ``.bin`` file with:: + + ./ota_uploader.py x ota.osd-merkur-256.0.hex > ota.osd-merkur-256.0.bin + + Note that the ``ota_uploader.py`` tool is intended to turn into a + full-fledged upgrade tool. This is work in progress. The first + parameter will be the destination IP-Address in the future and is + currently ignored. + +- Upload this image to the ``/update`` resource, either via the firefox + copper plugin or via the commandline:: + + coap-client -t application/octet-stream -f ota.osd-merkur-256.1.bin + -m put -b 64 'coap://[2001:db8:c001:f00d:221:2eff:ff00:5dd4]/update' + + Be sure to specify the type ``application/octet-stream`` if you are + uploading via copper. Also make sure you replace the IP address above + with the IP address of your board to be upgraded. + +CoAP-Resources, Image Management +++++++++++++++++++++++++++++++++ + +The bootloader now keeps a directory of the images. In this directory we +keep the following information which can be retrieved or set via CoAP +resources: + +- partition-ok: A flag per partition that indicates if this partition + has ever been successfully booted. This flag can only be set for a + partition that is currently running. Via CoAP this is set via the + ``/part_ok`` URI. In addition to the URI, a query-parameter indicating + the partition has to be specified, e.g., ``/part_ok?part=1``. + Note that when a partition is flashed via the bootloader (and not via + OTA) this flag is *not* set. So if later a new partition is loaded via + OTA and the old partition never was marked OK, the old partition has + to be rebooted before it can be made the default partition again. + The part_ok resource can currently not be queried via a GET request. +- boot-default: The default boot partition, can be changed if the new + default partition has the partition-ok flag set. The CoAP resource is + ``/boot_default`` and it can be queried via a GET request and set via + a PUT request, the parameter to the PUT request is the partition + number. +- boot-next: A temporary flag that can be set on a partition to boot it + just the next time. If booting fails the system will automatically + boot the boot-default partition next time. This is automatically set + after uploading an image. The CoAP resource is ``boot_next``. It can + also be changed via the resource similar to ``/boot_default`` but + without any constraints. + +Additional CoAP resources exist to query the bootloader for parameters +that are not kept in the directory: + +- ``/part_count``: Currently always 2, in the future the bootloader may + support more than two partitions +- ``/part_size``: The size of one partition, all partitions are equal in + size. +- ``/part_start``: This resource needs an additional query-parameter + indicating the partition number, e.g., ``/part_start?part=1`` and + returns the partition start address in flash. +- ``active_part``: The partition that is currently booted. + Security ======== +This is experimental code. There is currently no security, everybody (!) +can update your node. So use this only in experimental setups for now +until client-side DTLS authentication is available. + Position Independent Code ========================= @@ -37,29 +139,33 @@ are accessed and the bootloader then only relocates the addresses in the jump-table. The first implementation will use two images (one for upper-, one for -lower half). +lower half). We may decide to add on-the-fly relocation or we may always +ship two images (e.g. in a .zip file) and create a flash tool that +determines the correct image from the system to be updated. Memory Layout ============= +The following table might have changed when you read this. See the +``stk500boot_atmega256rfr2`` bootloader on github, in particular the +file ``flash_layout.h`` for details. + +--------------------------------------+ | 3E000-3FFFF Bootloader | +--------------------------------------+ | 3DE00-3DFFF Flash image directory | +--------------------------------------+ - | 3DC00-3DDFF IRQVec copy upper image | + | 3D600-3DDFF IRQVec copy upper image | +--------------------------------------+ - | 1F100-3DBFF | - | Upper Image (w/o first two pages) | + | 1EF00-3D5FF | + | Upper Image | | | | | +--------------------------------------+ - | 1EF00-1F0FF IRQVec upper image | + | 1E700-1EEFF IRQVec copy lower image | +--------------------------------------+ - | 1ED00-1EEFF IRQVec copy lower image | - +--------------------------------------+ - | 00200-1ECFF | - | Lower Image (w/o first two pages) | + | 00000-1E6FF | + | Lower Image | | | | | +--------------------------------------+ @@ -68,14 +174,19 @@ Memory Layout We have two identical images. Each image contains the IRQ vectors (and some code after the vector table) in the lower two pages. A copy of -these two pages is kept in two pages after the image. The reason is that -the IRQ vectors are fixed at address 00000 in this processor -architecture. So for running an image we need to copy the irq-vectors to +these pages (currently 8 pages as of this writing) is kept after the +image. The reason is that the IRQ vectors are fixed at address 00000 in +this processor architecture. In addition the compiler creates jumptables +(so-called trampoline code) to reach functions everywhere in memory via +a near call. So for running an image we need to copy the irq-vectors to the fixed location (and therefore we keep a backup to be able to restore the original image at that location). + +We use the irq vectors in the bootloader to determine the +currently-running image: The first vector at position 0 is a jump to the +start of our program. From the address of this jump we can find out +which image is currently running. + Note that in the table above an image as generated by the compiler -consists of the IRQ vectors in the first two pages (00000-001FF for the -first and 1EF00-1F0FF for the second image) plus the rest of the code +consists of the IRQ vectors in the first pages plus the rest of the code for that image. - -