You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/02/02 09:38:36 UTC

[incubator-nuttx-apps] branch master updated: examples: Add mcuboot Swap Test example

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new 836cd05  examples: Add mcuboot Swap Test example
836cd05 is described below

commit 836cd0552681580cea004d9096a98a25665c7b43
Author: Gerson Fernando Budke <na...@gmail.com>
AuthorDate: Wed Dec 15 22:02:29 2021 -0300

    examples: Add mcuboot Swap Test example
    
    This example demonstrate swap between two valid images. Instructions
    are available at readme.md file inside project directory.
    
    Signed-off-by: Gerson Fernando Budke <na...@gmail.com>
---
 examples/mcuboot/.gitignore               |   1 +
 examples/mcuboot/Make.defs                |  21 +++++
 examples/mcuboot/Makefile                 |  23 +++++
 examples/mcuboot/swap_test/Kconfig        |  13 +++
 examples/mcuboot/swap_test/Make.defs      |  23 +++++
 examples/mcuboot/swap_test/Makefile       |  29 +++++++
 examples/mcuboot/swap_test/README.md      | 138 ++++++++++++++++++++++++++++++
 examples/mcuboot/swap_test/confirm_main.c |  46 ++++++++++
 examples/mcuboot/swap_test/set_img_main.c |  55 ++++++++++++
 examples/mcuboot/swap_test/version_main.c | 127 +++++++++++++++++++++++++++
 10 files changed, 476 insertions(+)

diff --git a/examples/mcuboot/.gitignore b/examples/mcuboot/.gitignore
new file mode 100644
index 0000000..9e1d259
--- /dev/null
+++ b/examples/mcuboot/.gitignore
@@ -0,0 +1 @@
+/Kconfig
diff --git a/examples/mcuboot/Make.defs b/examples/mcuboot/Make.defs
new file mode 100644
index 0000000..fea6548
--- /dev/null
+++ b/examples/mcuboot/Make.defs
@@ -0,0 +1,21 @@
+############################################################################
+# apps/examples/mcuboot/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(wildcard $(APPDIR)/examples/mcuboot/*/Make.defs)
diff --git a/examples/mcuboot/Makefile b/examples/mcuboot/Makefile
new file mode 100644
index 0000000..3bd6703
--- /dev/null
+++ b/examples/mcuboot/Makefile
@@ -0,0 +1,23 @@
+############################################################################
+# apps/examples/mcuboot/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+MENUDESC = "MCUboot Examples"
+
+include $(APPDIR)/Directory.mk
diff --git a/examples/mcuboot/swap_test/Kconfig b/examples/mcuboot/swap_test/Kconfig
new file mode 100644
index 0000000..2d0a791
--- /dev/null
+++ b/examples/mcuboot/swap_test/Kconfig
@@ -0,0 +1,13 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config EXAMPLES_MCUBOOT_SWAP_TEST
+	tristate "MCUboot SWAP Test image example"
+	default n
+	select BOOT_MCUBOOT
+	---help---
+		Example application to demonstrate the firmware image swap
+		and the image rollback processes of MCUboot using the boot
+		swap and test method.
diff --git a/examples/mcuboot/swap_test/Make.defs b/examples/mcuboot/swap_test/Make.defs
new file mode 100644
index 0000000..e4d0155
--- /dev/null
+++ b/examples/mcuboot/swap_test/Make.defs
@@ -0,0 +1,23 @@
+############################################################################
+# apps/examples/mcuboot/swap_test/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_EXAMPLES_MCUBOOT_SWAP_TEST),)
+CONFIGURED_APPS += $(APPDIR)/examples/mcuboot/swap_test
+endif
diff --git a/examples/mcuboot/swap_test/Makefile b/examples/mcuboot/swap_test/Makefile
new file mode 100644
index 0000000..ad91a88
--- /dev/null
+++ b/examples/mcuboot/swap_test/Makefile
@@ -0,0 +1,29 @@
+############################################################################
+# apps/examples/mcuboot/swap_test/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+MAINSRC   += confirm_main.c set_img_main.c version_main.c
+
+PROGNAME  += mcuboot_confirm mcuboot_set_img mcuboot_version
+PRIORITY  += SCHED_PRIORITY_DEFAULT
+STACKSIZE += $(CONFIG_DEFAULT_TASK_STACKSIZE)
+
+include $(APPDIR)/Application.mk
diff --git a/examples/mcuboot/swap_test/README.md b/examples/mcuboot/swap_test/README.md
new file mode 100644
index 0000000..6a43a06
--- /dev/null
+++ b/examples/mcuboot/swap_test/README.md
@@ -0,0 +1,138 @@
+# Examples / MCUboot / `swap_test`
+
+## Description
+
+MCUboot Swap Image is an application to demostrate firmware upgrade using
+internal flash memory. It simulate MCUboot API steps to switch between two
+valid images.
+
+This application add 3 Builtin Apps to NuttX NSH: version, set_img and confirm.
+After application is build and `nuttx.bin` be generated, the binary must be
+signed. Consult your board README file to get instructions how to do it.
+
+## How to build and flash
+
+First step is build your board configuraton using `mcuboot-loader` as target.
+That create the bootloader itself. The `nuttx.bin` must be flash as usual.
+
+After that, clean up environment and set `mcuboot-swap-test` as target. The
+build output will generate the `nuttx.bin` file. You should execute the MCUboot
+script called `imgtool.py` and sign the binary file two times.
+
+The first time you will use `--version 1.0.0` and `signedv1.bin` as output file.
+Then, the second sign you need change to `--version 2.0.0` and `signedv2.bin`
+as output file.
+
+The `signedv1.bin` file must be at MCUboot Slot-0 partition and `signedv2.bin`
+at Slot-1.
+
+More instructions about how to sign and flash can be found at board README file.
+
+## Running swap image test
+
+Open you terminal and reboot your board. You can see a similar output as below.
+You can check builtin apps using command `?`.
+
+```bash
+*** Booting MCUboot build 7c890f4b075aed73e4c825ccf875b2fb9ebf2ded ***
+NuttShell (NSH) NuttX-10.2.0
+nsh> ?
+help usage:  help [-v] [<cmd>]
+
+  .         cd        echo      hexdump   mv        rmdir     true      xd        
+  [         cp        exec      kill      printf    set       truncate  
+  ?         cmp       exit      ls        ps        sleep     uname     
+  basename  dirname   false     mkdir     pwd       source    umount    
+  break     dd        free      mkrd      reboot    test      unset     
+  cat       df        help      mount     rm        time      usleep    
+
+Builtin Apps:
+  mcuboot_set_img  mcuboot_confirm  sh               
+  mcuboot_version  ramtest          nsh              
+nsh>
+```
+
+First step (check version):
+
+```bash
+nsh> mcuboot_version
+Image version 1.0.0.0
+nsh>
+```
+
+Second step (mark image as good because it is running). This is an optional
+step that must be executed if you ran `imgtool.py` without optional parameter
+`--confirm`.
+
+```bash
+nsh> mcuboot_confirm
+Application Image successfully confirmed!
+nsh>
+```
+
+Third step (let's reboot and see whats happen):
+
+```bash
+nsh> reboot
+*** Booting MCUboot build 7c890f4b075aed73e4c825ccf875b2fb9ebf2ded ***
+NuttShell (NSH) NuttX-10.2.0
+nsh> mcuboot_version
+Image version 1.0.0.0
+nsh>
+```
+
+Fourth step (let's switch image):
+
+```bash
+nsh> mcuboot_set_img
+Requested update for next boot. Restarting...
+*** Booting MCUboot build 7c890f4b075aed73e4c825ccf875b2fb9ebf2ded ***
+NuttShell (NSH) NuttX-10.2.0
+nsh> mcuboot_version
+Image version 2.0.0.0
+nsh>
+```
+
+Now, we switched from image version 1.0.0 to image 2.0.0. However, we intentionaly
+will not run `mcuboot_confirm` app.
+
+```bash
+nsh> reboot
+*** Booting MCUboot build 7c890f4b075aed73e4c825ccf875b2fb9ebf2ded ***
+NuttShell (NSH) NuttX-10.2.0
+nsh> mcuboot_version
+Image version 1.0.0.0
+nsh>
+```
+
+This means that if for any reason App reboot, have a malfunctioning or not boot,
+MCUboot will switch back to old `good` image! Remember that we executed
+`mcuboot_confirm` at step two.
+
+Fifth step (switch to image version 2 and mark as permanent):
+
+```bash
+nsh> mcuboot_set_img
+Requested update for next boot. Restarting...
+*** Booting MCUboot build 7c890f4b075aed73e4c825ccf875b2fb9ebf2ded ***
+NuttShell (NSH) NuttX-10.2.0
+nsh> mcuboot_confirm
+Application Image successfully confirmed!
+nsh> mcuboot_version
+Image version 2.0.0.0
+nsh>
+```
+
+Sixth step (Reboot and confirm V2 image):
+
+```bash
+nsh> reboot
+*** Booting MCUboot build 7c890f4b075aed73e4c825ccf875b2fb9ebf2ded ***
+NuttShell (NSH) NuttX-10.2.0
+nsh> mcuboot_version
+Image version 2.0.0.0
+nsh>
+```
+
+Conclusion, once we boot a newer image and confirm it MCUboot always run that
+image, unless you instruct it to swap again!
diff --git a/examples/mcuboot/swap_test/confirm_main.c b/examples/mcuboot/swap_test/confirm_main.c
new file mode 100644
index 0000000..c8a29c1
--- /dev/null
+++ b/examples/mcuboot/swap_test/confirm_main.c
@@ -0,0 +1,46 @@
+/****************************************************************************
+ * apps/examples/mcuboot/swap_test/confirm_main.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+
+#include <bootutil/bootutil_public.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * mcuboot_confirm_main
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  boot_set_confirmed_multi(0);
+
+  printf("Application Image successfully confirmed!\n");
+
+  return 0;
+}
diff --git a/examples/mcuboot/swap_test/set_img_main.c b/examples/mcuboot/swap_test/set_img_main.c
new file mode 100644
index 0000000..7c6d7c2
--- /dev/null
+++ b/examples/mcuboot/swap_test/set_img_main.c
@@ -0,0 +1,55 @@
+/****************************************************************************
+ * apps/examples/mcuboot/swap_test/set_img_main.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/boardctl.h>
+
+#include <bootutil/bootutil_public.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * mcuboot_set_img_main
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  boot_set_pending_multi(0, 0);
+
+  printf("Requested update for next boot. Restarting...\n");
+
+  fflush(stdout);
+  fflush(stderr);
+
+  usleep(1000);
+
+  boardctl(BOARDIOC_RESET, 0);
+
+  return 0;
+}
diff --git a/examples/mcuboot/swap_test/version_main.c b/examples/mcuboot/swap_test/version_main.c
new file mode 100644
index 0000000..9321124
--- /dev/null
+++ b/examples/mcuboot/swap_test/version_main.c
@@ -0,0 +1,127 @@
+/****************************************************************************
+ * apps/examples/mcuboot/swap_test/version_main.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <endian.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <bootutil/bootutil_public.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define BOOT_HEADER_MAGIC_V1 0x96f3b83d
+#define BOOT_HEADER_SIZE_V1  32
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+begin_packed_struct struct mcuboot_raw_version_v1_s
+{
+    uint8_t  major;
+    uint8_t  minor;
+    uint16_t revision;
+    uint32_t build_num;
+} end_packed_struct;
+
+begin_packed_struct struct mcuboot_raw_header_v1_s
+{
+  uint32_t header_magic;
+  uint32_t image_load_address;
+  uint16_t header_size;
+  uint16_t pad;
+  uint32_t image_size;
+  uint32_t image_flags;
+  struct mcuboot_raw_version_v1_s version;
+  uint32_t pad2;
+} end_packed_struct;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int boot_read_v1_header(uint8_t area_id,
+                               struct mcuboot_raw_header_v1_s *raw_header)
+{
+  const struct flash_area *fa;
+  int rc;
+
+  rc = flash_area_open(area_id, &fa);
+  if (rc)
+    {
+      return rc;
+    }
+
+  rc = flash_area_read(fa, 0, raw_header,
+                       sizeof(struct mcuboot_raw_header_v1_s));
+  flash_area_close(fa);
+  if (rc)
+    {
+      return rc;
+    }
+
+  raw_header->header_magic       = le32toh(raw_header->header_magic);
+  raw_header->image_load_address = le32toh(raw_header->image_load_address);
+  raw_header->header_size        = le16toh(raw_header->header_size);
+  raw_header->image_size         = le32toh(raw_header->image_size);
+  raw_header->image_flags        = le32toh(raw_header->image_flags);
+  raw_header->version.revision   = le16toh(raw_header->version.revision);
+  raw_header->version.build_num  = le32toh(raw_header->version.build_num);
+
+  if ((raw_header->header_magic != BOOT_HEADER_MAGIC_V1)
+  ||  (raw_header->header_size   < BOOT_HEADER_SIZE_V1))
+    {
+      return -EIO;
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * mcuboot_version_main
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  int rc;
+  struct mcuboot_raw_header_v1_s raw_header;
+
+  rc = boot_read_v1_header(0, &raw_header);
+  if (rc)
+    {
+      printf("Only header version 1 can be read. Abort!\n");
+      return rc;
+    }
+
+  printf("Image version %d.%d.%d.%ld\n", raw_header.version.major,
+                                         raw_header.version.minor,
+                                         raw_header.version.revision,
+                                         raw_header.version.build_num);
+
+  return 0;
+}