boot: Add support for the Apache NuttX RTOS

Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
diff --git a/boot/nuttx/include/flash_map_backend/flash_map_backend.h b/boot/nuttx/include/flash_map_backend/flash_map_backend.h
new file mode 100644
index 0000000..7d17a8b
--- /dev/null
+++ b/boot/nuttx/include/flash_map_backend/flash_map_backend.h
@@ -0,0 +1,422 @@
+/****************************************************************************
+ * boot/nuttx/include/flash_map_backend/flash_map_backend.h
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BOOT_NUTTX_INCLUDE_FLASH_MAP_BACKEND_FLASH_MAP_BACKEND_H
+#define __BOOT_NUTTX_INCLUDE_FLASH_MAP_BACKEND_FLASH_MAP_BACKEND_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <inttypes.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Structure describing a flash area. */
+
+struct flash_area
+{
+  /* MCUboot-API fields */
+
+  uint8_t     fa_id;         /* The slot/scratch ID */
+  uint8_t     fa_device_id;  /* The device ID (usually there's only one) */
+  uint16_t    pad16;         /* Padding */
+  uint32_t    fa_off;        /* The flash offset from the beginning */
+  uint32_t    fa_size;       /* The size of this sector */
+
+  /* NuttX implementation-specific fields */
+
+  const char *fa_mtd_path;   /* Path for the MTD partition */
+};
+
+/* Structure describing a sector within a flash area. */
+
+struct flash_sector
+{
+  /* Offset of this sector, from the start of its flash area (not device). */
+
+  uint32_t fs_off;
+
+  /* Size of this sector, in bytes. */
+
+  uint32_t fs_size;
+};
+
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: flash_area_get_id
+ *
+ * Description:
+ *   Obtain the ID of a given flash area.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   The ID of the requested flash area.
+ *
+ ****************************************************************************/
+
+static inline uint8_t flash_area_get_id(const struct flash_area *fa)
+{
+  return fa->fa_id;
+}
+
+/****************************************************************************
+ * Name: flash_area_get_device_id
+ *
+ * Description:
+ *   Obtain the ID of the device in which a given flash area resides on.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   The device ID of the requested flash area.
+ *
+ ****************************************************************************/
+
+static inline uint8_t flash_area_get_device_id(const struct flash_area *fa)
+{
+  return fa->fa_device_id;
+}
+
+/****************************************************************************
+ * Name: flash_area_get_off
+ *
+ * Description:
+ *   Obtain the offset, from the beginning of a device, where a given flash
+ *   area starts at.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   The offset value of the requested flash area.
+ *
+ ****************************************************************************/
+
+static inline uint32_t flash_area_get_off(const struct flash_area *fa)
+{
+  return fa->fa_off;
+}
+
+/****************************************************************************
+ * Name: flash_area_get_size
+ *
+ * Description:
+ *   Obtain the size, from the offset, of a given flash area.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   The size value of the requested flash area.
+ *
+ ****************************************************************************/
+
+static inline uint32_t flash_area_get_size(const struct flash_area *fa)
+{
+  return fa->fa_size;
+}
+
+/****************************************************************************
+ * Name: flash_sector_get_off
+ *
+ * Description:
+ *   Obtain the offset, from the beginning of its flash area, where a given
+ *   flash sector starts at.
+ *
+ * Input Parameters:
+ *   fs - Flash sector.
+ *
+ * Returned Value:
+ *   The offset value of the requested flash sector.
+ *
+ ****************************************************************************/
+
+static inline uint32_t flash_sector_get_off(const struct flash_sector *fs)
+{
+    return fs->fs_off;
+}
+
+/****************************************************************************
+ * Name: flash_sector_get_size
+ *
+ * Description:
+ *   Obtain the size, from the offset, of a given flash sector.
+ *
+ * Input Parameters:
+ *   fs - Flash sector.
+ *
+ * Returned Value:
+ *   The size in bytes of the requested flash sector.
+ *
+ ****************************************************************************/
+
+static inline uint32_t flash_sector_get_size(const struct flash_sector *fs)
+{
+    return fs->fs_size;
+}
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: flash_area_open
+ *
+ * Description:
+ *   Retrieve flash area from the flash map for a given partition.
+ *
+ * Input Parameters:
+ *   fa_id - ID of the flash partition.
+ *
+ * Output Parameters:
+ *   fa    - Pointer which will contain the reference to flash_area.
+ *           If ID is unknown, it will be NULL on output.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_open(uint8_t id, const struct flash_area **fa);
+
+/****************************************************************************
+ * Name: flash_area_close
+ *
+ * Description:
+ *   Close a given flash area.
+ *
+ * Input Parameters:
+ *   fa - Flash area to be closed.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void flash_area_close(const struct flash_area *fa);
+
+/****************************************************************************
+ * Name: flash_area_read
+ *
+ * Description:
+ *   Read data from flash area.
+ *   Area readout boundaries are asserted before read request. API has the
+ *   same limitation regarding read-block alignment and size as the
+ *   underlying flash driver.
+ *
+ * Input Parameters:
+ *   fa  - Flash area to be read.
+ *   off - Offset relative from beginning of flash area to be read.
+ *   len - Number of bytes to read.
+ *
+ * Output Parameters:
+ *   dst - Buffer to store read data.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_read(const struct flash_area *fa, uint32_t off,
+                    void *dst, uint32_t len);
+
+/****************************************************************************
+ * Name: flash_area_write
+ *
+ * Description:
+ *   Write data to flash area.
+ *   Area write boundaries are asserted before write request. API has the
+ *   same limitation regarding write-block alignment and size as the
+ *   underlying flash driver.
+ *
+ * Input Parameters:
+ *   fa  - Flash area to be written.
+ *   off - Offset relative from beginning of flash area to be written.
+ *   src - Buffer with data to be written.
+ *   len - Number of bytes to write.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_write(const struct flash_area *fa, uint32_t off,
+                     const void *src, uint32_t len);
+
+/****************************************************************************
+ * Name: flash_area_erase
+ *
+ * Description:
+ *   Erase a given flash area range.
+ *   Area boundaries are asserted before erase request. API has the same
+ *   limitation regarding erase-block alignment and size as the underlying
+ *   flash driver.
+ *
+ * Input Parameters:
+ *   fa  - Flash area to be erased.
+ *   off - Offset relative from beginning of flash area to be erased.
+ *   len - Number of bytes to be erase.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_erase(const struct flash_area *fa, uint32_t off,
+                     uint32_t len);
+
+/****************************************************************************
+ * Name: flash_area_align
+ *
+ * Description:
+ *   Get write block size of the flash area.
+ *   Write block size might be treated as read block size, although most
+ *   drivers support unaligned readout.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   Alignment restriction for flash writes in the given flash area.
+ *
+ ****************************************************************************/
+
+uint8_t flash_area_align(const struct flash_area *fa);
+
+/****************************************************************************
+ * Name: flash_area_erased_val
+ *
+ * Description:
+ *   Get the value expected to be read when accessing any erased flash byte.
+ *   This API is compatible with the MCUboot's porting layer.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   Byte value of erased memory.
+ *
+ ****************************************************************************/
+
+uint8_t flash_area_erased_val(const struct flash_area *fa);
+
+/****************************************************************************
+ * Name: flash_area_get_sectors
+ *
+ * Description:
+ *   Retrieve info about sectors within the area.
+ *
+ * Input Parameters:
+ *   fa_id   - ID of the flash area whose info will be retrieved.
+ *   count   - On input, represents the capacity of the sectors buffer.
+ *
+ * Output Parameters:
+ *   count   - On output, it shall contain the number of retrieved sectors.
+ *   sectors - Buffer for sectors data.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_get_sectors(int fa_id, uint32_t *count,
+                           struct flash_sector *sectors);
+
+/****************************************************************************
+ * Name: flash_area_id_from_multi_image_slot
+ *
+ * Description:
+ *   Return the flash area ID for a given slot and a given image index
+ *   (in case of a multi-image setup).
+ *
+ * Input Parameters:
+ *   image_index - Index of the image.
+ *   slot        - Image slot, which may be 0 (primary) or 1 (secondary).
+ *
+ * Returned Value:
+ *   Flash area ID (0 or 1), or negative value in case the requested slot
+ *   is invalid.
+ *
+ ****************************************************************************/
+
+int flash_area_id_from_multi_image_slot(int image_index, int slot);
+
+/****************************************************************************
+ * Name: flash_area_id_from_image_slot
+ *
+ * Description:
+ *   Return the flash area ID for a given slot.
+ *
+ * Input Parameters:
+ *   slot - Image slot, which may be 0 (primary) or 1 (secondary).
+ *
+ * Returned Value:
+ *   Flash area ID (0 or 1), or negative value in case the requested slot
+ *   is invalid.
+ *
+ ****************************************************************************/
+
+int flash_area_id_from_image_slot(int slot);
+
+/****************************************************************************
+ * Name: flash_area_id_to_multi_image_slot
+ *
+ * Description:
+ *   Convert the specified flash area ID and image index (in case of a
+ *   multi-image setup) to an image slot index.
+ *
+ * Input Parameters:
+ *   image_index - Index of the image.
+ *   fa_id       - Image slot, which may be 0 (primary) or 1 (secondary).
+ *
+ * Returned Value:
+ *   Image slot index (0 or 1), or negative value in case ID doesn't
+ *   correspond to an image slot.
+ *
+ ****************************************************************************/
+
+int flash_area_id_to_multi_image_slot(int image_index, int fa_id);
+
+/****************************************************************************
+ * Name: flash_area_id_from_image_offset
+ *
+ * Description:
+ *   Return the flash area ID for a given image offset.
+ *
+ * Input Parameters:
+ *   offset - Image offset.
+ *
+ * Returned Value:
+ *   Flash area ID (0 or 1), or negative value in case the requested slot
+ *   is invalid.
+ *
+ ****************************************************************************/
+
+int flash_area_id_from_image_offset(uint32_t offset);
+
+#endif /* __BOOT_NUTTX_INCLUDE_FLASH_MAP_BACKEND_FLASH_MAP_BACKEND_H */
diff --git a/boot/nuttx/include/mcuboot_config/mcuboot_config.h b/boot/nuttx/include/mcuboot_config/mcuboot_config.h
new file mode 100644
index 0000000..e405ffa
--- /dev/null
+++ b/boot/nuttx/include/mcuboot_config/mcuboot_config.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+ * boot/nuttx/include/mcuboot_config/mcuboot_config.h
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BOOT_NUTTX_INCLUDE_MCUBOOT_CONFIG_MCUBOOT_CONFIG_H
+#define __BOOT_NUTTX_INCLUDE_MCUBOOT_CONFIG_MCUBOOT_CONFIG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#ifdef CONFIG_MCUBOOT_WATCHDOG
+#include "watchdog/watchdog.h"
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Signature types
+ *
+ * You must choose exactly one signature type.
+ */
+
+/* Uncomment for RSA signature support */
+
+/* #define MCUBOOT_SIGN_RSA */
+
+/* Uncomment for ECDSA signatures using curve P-256. */
+
+/* #define MCUBOOT_SIGN_EC256 */
+
+/* Upgrade mode
+ *
+ * The default is to support A/B image swapping with rollback.  Other modes
+ * with simpler code path, which only supports overwriting the existing image
+ * with the update image or running the newest image directly from its flash
+ * partition, are also available.
+ *
+ * You can enable only one mode at a time from the list below to override
+ * the default upgrade mode.
+ */
+
+/* Uncomment to enable the overwrite-only code path. */
+
+/* #define MCUBOOT_OVERWRITE_ONLY */
+
+#ifdef MCUBOOT_OVERWRITE_ONLY
+
+/* Uncomment to only erase and overwrite those primary slot sectors needed
+ * to install the new image, rather than the entire image slot.
+ */
+
+/* #define MCUBOOT_OVERWRITE_ONLY_FAST */
+
+#endif
+
+/* Uncomment to enable the direct-xip code path. */
+
+/* #define MCUBOOT_DIRECT_XIP */
+
+/* Uncomment to enable the ram-load code path. */
+
+/* #define MCUBOOT_RAM_LOAD */
+
+/* Cryptographic settings
+ *
+ * You must choose between mbedTLS and Tinycrypt as source of
+ * cryptographic primitives. Other cryptographic settings are also
+ * available.
+ */
+
+/* Uncomment to use ARM's mbedTLS cryptographic primitives */
+
+#define MCUBOOT_USE_MBED_TLS
+
+/* Uncomment to use Tinycrypt's. */
+
+/* #define MCUBOOT_USE_TINYCRYPT */
+
+/* Always check the signature of the image in the primary slot before
+ * booting, even if no upgrade was performed. This is recommended if the boot
+ * time penalty is acceptable.
+ */
+
+#define MCUBOOT_VALIDATE_PRIMARY_SLOT
+
+/* Flash abstraction */
+
+/* Uncomment if your flash map API supports flash_area_get_sectors().
+ * See the flash APIs for more details.
+ */
+
+#define MCUBOOT_USE_FLASH_AREA_GET_SECTORS
+
+/* Default maximum number of flash sectors per image slot; change
+ * as desirable.
+ */
+
+#define MCUBOOT_MAX_IMG_SECTORS 512
+
+/* Default number of separately updateable images; change in case of
+ * multiple images.
+ */
+
+#define MCUBOOT_IMAGE_NUMBER 1
+
+/* Logging */
+
+/* If logging is enabled the following functions must be defined by the
+ * platform:
+ *
+ *    MCUBOOT_LOG_MODULE_REGISTER(domain)
+ *      Register a new log module and add the current C file to it.
+ *
+ *    MCUBOOT_LOG_MODULE_DECLARE(domain)
+ *      Add the current C file to an existing log module.
+ *
+ *    MCUBOOT_LOG_ERR(...)
+ *    MCUBOOT_LOG_WRN(...)
+ *    MCUBOOT_LOG_INF(...)
+ *    MCUBOOT_LOG_DBG(...)
+ *
+ * The function priority is:
+ *
+ *    MCUBOOT_LOG_ERR > MCUBOOT_LOG_WRN > MCUBOOT_LOG_INF > MCUBOOT_LOG_DBG
+ */
+
+#ifdef CONFIG_MCUBOOT_ENABLE_LOGGING
+#  define MCUBOOT_HAVE_LOGGING
+#endif
+
+/* Assertions */
+
+/* Uncomment if your platform has its own mcuboot_config/mcuboot_assert.h.
+ * If so, it must provide an ASSERT macro for use by bootutil. Otherwise,
+ * "assert" is used.
+ */
+
+/* #define MCUBOOT_HAVE_ASSERT_H 1 */
+
+/* Watchdog feeding */
+
+/* This macro might be implemented if the OS / HW watchdog is enabled while
+ * doing a swap upgrade and the time it takes for a swapping is long enough
+ * to cause an unwanted reset. If implementing this, the OS main.c must also
+ * enable the watchdog (if required)!
+ */
+
+#ifdef CONFIG_MCUBOOT_WATCHDOG
+#  define MCUBOOT_WATCHDOG_FEED()       do                           \
+                                          {                          \
+                                            mcuboot_watchdog_feed(); \
+                                          }                          \
+                                        while (0)
+
+#else
+#  define MCUBOOT_WATCHDOG_FEED()       do                           \
+                                          {                          \
+                                          }                          \
+                                        while (0)
+#endif
+
+#endif /* __BOOT_NUTTX_INCLUDE_MCUBOOT_CONFIG_MCUBOOT_CONFIG_H */
diff --git a/boot/nuttx/include/mcuboot_config/mcuboot_logging.h b/boot/nuttx/include/mcuboot_config/mcuboot_logging.h
new file mode 100644
index 0000000..6853fff
--- /dev/null
+++ b/boot/nuttx/include/mcuboot_config/mcuboot_logging.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+ * boot/nuttx/include/mcuboot_config/mcuboot_logging.h
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BOOT_NUTTX_INCLUDE_MCUBOOT_CONFIG_MCUBOOT_LOGGING_H
+#define __BOOT_NUTTX_INCLUDE_MCUBOOT_CONFIG_MCUBOOT_LOGGING_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <syslog.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define MCUBOOT_LOG_ERR(format, ...) \
+    syslog(LOG_ERR, "%s: " format "\n", __FUNCTION__, ##__VA_ARGS__)
+
+#define MCUBOOT_LOG_WRN(format, ...) \
+    syslog(LOG_WARNING, "%s: " format "\n", __FUNCTION__, ##__VA_ARGS__)
+
+#define MCUBOOT_LOG_INF(format, ...) \
+    syslog(LOG_INFO, "%s: " format "\n", __FUNCTION__, ##__VA_ARGS__)
+
+#define MCUBOOT_LOG_DBG(format, ...) \
+    syslog(LOG_DEBUG, "%s: " format "\n", __FUNCTION__, ##__VA_ARGS__)
+
+#endif /* __BOOT_NUTTX_INCLUDE_MCUBOOT_CONFIG_MCUBOOT_LOGGING_H */
diff --git a/boot/nuttx/include/os/os_malloc.h b/boot/nuttx/include/os/os_malloc.h
new file mode 100644
index 0000000..1fbefad
--- /dev/null
+++ b/boot/nuttx/include/os/os_malloc.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+ * boot/nuttx/include/os/os_malloc.h
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BOOT_NUTTX_INCLUDE_OS_OS_MALLOC_H
+#define __BOOT_NUTTX_INCLUDE_OS_OS_MALLOC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdlib.h>
+
+#endif /* __BOOT_NUTTX_INCLUDE_OS_OS_MALLOC_H */
diff --git a/boot/nuttx/include/sysflash/sysflash.h b/boot/nuttx/include/sysflash/sysflash.h
new file mode 100644
index 0000000..2faff88
--- /dev/null
+++ b/boot/nuttx/include/sysflash/sysflash.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+ * boot/nuttx/include/sysflash/sysflash.h
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BOOT_NUTTX_INCLUDE_SYSFLASH_SYSFLASH_H
+#define __BOOT_NUTTX_INCLUDE_SYSFLASH_SYSFLASH_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define PRIMARY_ID      0
+#define SECONDARY_ID    1
+#define SCRATCH_ID      2
+
+#define FLASH_AREA_IMAGE_PRIMARY(x)    PRIMARY_ID
+#define FLASH_AREA_IMAGE_SECONDARY(x)  SECONDARY_ID
+#define FLASH_AREA_IMAGE_SCRATCH       SCRATCH_ID
+
+#endif /* __BOOT_NUTTX_INCLUDE_SYSFLASH_SYSFLASH_H */
diff --git a/boot/nuttx/include/watchdog/watchdog.h b/boot/nuttx/include/watchdog/watchdog.h
new file mode 100644
index 0000000..01cf31d
--- /dev/null
+++ b/boot/nuttx/include/watchdog/watchdog.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+ * boot/nuttx/include/watchdog/watchdog.h
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BOOT_NUTTX_INCLUDE_WATCHDOG_WATCHDOG_H
+#define __BOOT_NUTTX_INCLUDE_WATCHDOG_WATCHDOG_H
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mcuboot_watchdog_feed
+ *
+ * Description:
+ *   Reset the watchdog timer to the current timeout value, preventing any
+ *   imminent watchdog timeouts.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void mcuboot_watchdog_feed(void);
+
+#endif /* __BOOT_NUTTX_INCLUDE_WATCHDOG_WATCHDOG_H */
diff --git a/boot/nuttx/main.c b/boot/nuttx/main.c
new file mode 100644
index 0000000..1b229c0
--- /dev/null
+++ b/boot/nuttx/main.c
@@ -0,0 +1,95 @@
+/****************************************************************************
+ * boot/nuttx/main.c
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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 <sys/boardctl.h>
+
+#include <bootutil/bootutil.h>
+#include <bootutil/image.h>
+
+#include "flash_map_backend/flash_map_backend.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * do_boot
+ ****************************************************************************/
+
+static void do_boot(struct boot_rsp *rsp)
+{
+  struct flash_area *flash_area;
+  struct boardioc_boot_info_s info;
+  int area_id;
+  int ret;
+
+  area_id = flash_area_id_from_image_offset(rsp->br_image_off);
+
+  ret = flash_area_open(area_id, &flash_area);
+  assert(ret == OK);
+
+  printf("Booting from %s...\n", flash_area->fa_mtd_path);
+
+  info.path        = flash_area->fa_mtd_path;
+  info.header_size = rsp->br_hdr->ih_hdr_size;
+
+  flash_area_close(flash_area);
+
+  if (boardctl(BOARDIOC_BOOT_IMAGE, &info) != OK)
+    {
+      fprintf(stderr, "Failed to load application image!\n");
+      FIH_PANIC;
+    }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * main
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  struct boot_rsp rsp;
+  fih_int fih_rc = FIH_FAILURE;
+
+  printf("*** Booting MCUboot build %s ***\n", CONFIG_MCUBOOT_VERSION);
+
+  FIH_CALL(boot_go, fih_rc, &rsp);
+
+  if (fih_not_eq(fih_rc, FIH_SUCCESS))
+    {
+      fprintf(stderr, "Unable to find bootable image\n");
+      FIH_PANIC;
+    }
+
+  do_boot(&rsp);
+
+  while (1);
+}
diff --git a/boot/nuttx/src/flash_map_backend/flash_map_backend.c b/boot/nuttx/src/flash_map_backend/flash_map_backend.c
new file mode 100644
index 0000000..3aa53fb
--- /dev/null
+++ b/boot/nuttx/src/flash_map_backend/flash_map_backend.c
@@ -0,0 +1,805 @@
+/****************************************************************************
+ * boot/nuttx/src/flash_map_backend/flash_map_backend.c
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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 <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/mtd/mtd.h>
+
+#include <bootutil/bootutil_log.h>
+
+#include "flash_map_backend/flash_map_backend.h"
+#include "os/os_malloc.h"
+#include "sysflash/sysflash.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ARRAYSIZE(x)                (sizeof((x)) / sizeof((x)[0]))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct flash_device_s
+{
+  /* Reference to the flash area configuration parameters */
+
+  struct flash_area *fa_cfg;
+
+  /* Geometry characteristics of the underlying MTD device */
+
+  struct mtd_geometry_s mtdgeo;
+
+  /* Partition information */
+
+  struct partition_info_s partinfo;
+
+  int     fd;          /* File descriptor for an open flash area */
+  int32_t refs;        /* Reference counter */
+  uint8_t erase_state; /* Byte value of the flash erased state */
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct flash_area g_primary_img0 =
+{
+  .fa_id = FLASH_AREA_IMAGE_PRIMARY(0),
+  .fa_device_id = 0,
+  .fa_off = 0,
+  .fa_size = 0,
+  .fa_mtd_path = CONFIG_MCUBOOT_PRIMARY_SLOT_PATH
+};
+
+static struct flash_device_s g_primary_priv =
+{
+  .fa_cfg = &g_primary_img0,
+  .mtdgeo =
+            {
+              0
+            },
+  .partinfo =
+              {
+                0
+              },
+  .fd = -1,
+  .refs = 0,
+  .erase_state = CONFIG_MCUBOOT_DEFAULT_FLASH_ERASE_STATE
+};
+
+static struct flash_area g_secondary_img0 =
+{
+  .fa_id = FLASH_AREA_IMAGE_SECONDARY(0),
+  .fa_device_id = 0,
+  .fa_off = 0,
+  .fa_size = 0,
+  .fa_mtd_path = CONFIG_MCUBOOT_SECONDARY_SLOT_PATH
+};
+
+static struct flash_device_s g_secondary_priv =
+{
+  .fa_cfg = &g_secondary_img0,
+  .mtdgeo =
+            {
+              0
+            },
+  .partinfo =
+              {
+                0
+              },
+  .fd = -1,
+  .refs = 0,
+  .erase_state = CONFIG_MCUBOOT_DEFAULT_FLASH_ERASE_STATE
+};
+
+static struct flash_area g_scratch_img0 =
+{
+  .fa_id = FLASH_AREA_IMAGE_SCRATCH,
+  .fa_device_id = 0,
+  .fa_off = 0,
+  .fa_size = 0,
+  .fa_mtd_path = CONFIG_MCUBOOT_SCRATCH_PATH
+};
+
+static struct flash_device_s g_scratch_priv =
+{
+  .fa_cfg = &g_scratch_img0,
+  .mtdgeo =
+            {
+              0
+            },
+  .partinfo =
+              {
+                0
+              },
+  .fd = -1,
+  .refs = 0,
+  .erase_state = CONFIG_MCUBOOT_DEFAULT_FLASH_ERASE_STATE
+};
+
+static struct flash_device_s *g_flash_devices[] =
+{
+  &g_primary_priv,
+  &g_secondary_priv,
+  &g_scratch_priv,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lookup_flash_device_by_id
+ *
+ * Description:
+ *   Retrieve flash device from a given flash area ID.
+ *
+ * Input Parameters:
+ *   fa_id - ID of the flash area.
+ *
+ * Returned Value:
+ *   Reference to the found flash device, or NULL in case it does not exist.
+ *
+ ****************************************************************************/
+
+static struct flash_device_s *lookup_flash_device_by_id(uint8_t fa_id)
+{
+  size_t i;
+
+  for (i = 0; i < ARRAYSIZE(g_flash_devices); i++)
+    {
+      struct flash_device_s *dev = g_flash_devices[i];
+
+      if (fa_id == dev->fa_cfg->fa_id)
+        {
+          return dev;
+        }
+    }
+
+  return NULL;
+}
+
+/****************************************************************************
+ * Name: lookup_flash_device_by_offset
+ *
+ * Description:
+ *   Retrieve flash device from a given flash area offset.
+ *
+ * Input Parameters:
+ *   offset - Offset of the flash area.
+ *
+ * Returned Value:
+ *   Reference to the found flash device, or NULL in case it does not exist.
+ *
+ ****************************************************************************/
+
+static struct flash_device_s *lookup_flash_device_by_offset(uint32_t offset)
+{
+  size_t i;
+
+  for (i = 0; i < ARRAYSIZE(g_flash_devices); i++)
+    {
+      struct flash_device_s *dev = g_flash_devices[i];
+
+      if (offset == dev->fa_cfg->fa_off)
+        {
+          return dev;
+        }
+    }
+
+  return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: flash_area_open
+ *
+ * Description:
+ *   Retrieve flash area from the flash map for a given ID.
+ *
+ * Input Parameters:
+ *   fa_id - ID of the flash area.
+ *
+ * Output Parameters:
+ *   fa    - Pointer which will contain the reference to flash_area.
+ *           If ID is unknown, it will be NULL on output.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_open(uint8_t id, const struct flash_area **fa)
+{
+  struct flash_device_s *dev;
+  int fd;
+  int ret;
+
+  BOOT_LOG_INF("ID:%" PRIu8, id);
+
+  dev = lookup_flash_device_by_id(id);
+  if (dev == NULL)
+    {
+      BOOT_LOG_ERR("Undefined flash area: %d", id);
+
+      return ERROR;
+    }
+
+  *fa = dev->fa_cfg;
+
+  if (dev->refs++ > 0)
+    {
+      BOOT_LOG_INF("Flash area ID %d already open, count: %d (+)",
+                   id, dev->refs);
+
+      return OK;
+    }
+
+  fd = open(dev->fa_cfg->fa_mtd_path, O_RDWR);
+  if (fd < 0)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Error opening MTD device: %d", errcode);
+
+      goto errout;
+    }
+
+  ret = ioctl(fd, MTDIOC_GEOMETRY, (unsigned long)((uintptr_t)&dev->mtdgeo));
+  if (ret < 0)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Error retrieving MTD device geometry: %d", errcode);
+
+      goto errout_with_fd;
+    }
+
+  ret = ioctl(fd, BIOC_PARTINFO, (unsigned long)((uintptr_t)&dev->partinfo));
+  if (ret < 0)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Error retrieving MTD partition info: %d", errcode);
+
+      goto errout_with_fd;
+    }
+
+  ret = ioctl(fd, MTDIOC_ERASESTATE,
+              (unsigned long)((uintptr_t)&dev->erase_state));
+  if (ret < 0)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Error retrieving MTD device erase state: %d", errcode);
+
+      goto errout_with_fd;
+    }
+
+  dev->fa_cfg->fa_off = dev->partinfo.startsector * dev->partinfo.sectorsize;
+  dev->fa_cfg->fa_size = dev->partinfo.numsectors * dev->partinfo.sectorsize;
+
+  BOOT_LOG_INF("Flash area offset: 0x%" PRIx32, dev->fa_cfg->fa_off);
+  BOOT_LOG_INF("Flash area size: %" PRIu32, dev->fa_cfg->fa_size);
+  BOOT_LOG_INF("MTD erase state: 0x%" PRIx8, dev->erase_state);
+
+  dev->fd = fd;
+
+  BOOT_LOG_INF("Flash area %d open, count: %d (+)", id, dev->refs);
+
+  return OK;
+
+errout_with_fd:
+  close(fd);
+
+errout:
+  --dev->refs;
+
+  return ERROR;
+}
+
+/****************************************************************************
+ * Name: flash_area_close
+ *
+ * Description:
+ *   Close a given flash area.
+ *
+ * Input Parameters:
+ *   fa - Flash area to be closed.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void flash_area_close(const struct flash_area *fa)
+{
+  BOOT_LOG_INF("ID:%" PRIu8, fa->fa_id);
+
+  struct flash_device_s *dev = lookup_flash_device_by_id(fa->fa_id);
+
+  DEBUGASSERT(dev != NULL);
+
+  if (dev->refs == 0)
+    {
+      /* No need to close an unopened flash area, avoid an overflow of the
+       * counter.
+       */
+
+      return;
+    }
+
+  BOOT_LOG_INF("Close request for flash area %" PRIu8 ", count: %d (-)",
+               fa->fa_id, dev->refs);
+
+  if (--dev->refs == 0)
+    {
+      close(dev->fd);
+      dev->fd = -1;
+
+      BOOT_LOG_INF("Flash area %" PRIu8 " closed", fa->fa_id);
+    }
+}
+
+/****************************************************************************
+ * Name: flash_area_read
+ *
+ * Description:
+ *   Read data from flash area.
+ *   Area readout boundaries are asserted before read request. API has the
+ *   same limitation regarding read-block alignment and size as the
+ *   underlying flash driver.
+ *
+ * Input Parameters:
+ *   fa  - Flash area to be read.
+ *   off - Offset relative from beginning of flash area to be read.
+ *   len - Number of bytes to read.
+ *
+ * Output Parameters:
+ *   dst - Buffer to store read data.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_read(const struct flash_area *fa, uint32_t off,
+                    void *dst, uint32_t len)
+{
+  struct flash_device_s *dev;
+  off_t seekpos;
+  ssize_t nbytes;
+
+  BOOT_LOG_INF("ID:%" PRIu8 " offset:%" PRIu32 " length:%" PRIu32,
+               fa->fa_id, off, len);
+
+  dev = lookup_flash_device_by_id(fa->fa_id);
+
+  DEBUGASSERT(dev != NULL);
+
+  if (off + len > fa->fa_size)
+    {
+      BOOT_LOG_ERR("Attempt to read out of flash area bounds");
+
+      return ERROR;
+    }
+
+  /* Reposition the file offset from the beginning of the flash area */
+
+  seekpos = lseek(dev->fd, (off_t)off, SEEK_SET);
+  if (seekpos != off)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Seek to offset %" PRIu32 " failed: %d", off, errcode);
+
+      return ERROR;
+    }
+
+  /* Read the flash block into memory */
+
+  nbytes = read(dev->fd, dst, len);
+  if (nbytes < 0)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Read from %s failed: %d", fa->fa_mtd_path, errcode);
+
+      return ERROR;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: flash_area_write
+ *
+ * Description:
+ *   Write data to flash area.
+ *   Area write boundaries are asserted before write request. API has the
+ *   same limitation regarding write-block alignment and size as the
+ *   underlying flash driver.
+ *
+ * Input Parameters:
+ *   fa  - Flash area to be written.
+ *   off - Offset relative from beginning of flash area to be written.
+ *   src - Buffer with data to be written.
+ *   len - Number of bytes to write.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_write(const struct flash_area *fa, uint32_t off,
+                     const void *src, uint32_t len)
+{
+  struct flash_device_s *dev;
+  off_t seekpos;
+  ssize_t nbytes;
+
+  BOOT_LOG_INF("ID:%" PRIu8 " offset:%" PRIu32 " length:%" PRIu32,
+               fa->fa_id, off, len);
+
+  dev = lookup_flash_device_by_id(fa->fa_id);
+
+  DEBUGASSERT(dev != NULL);
+
+  if (off + len > fa->fa_size)
+    {
+      BOOT_LOG_ERR("Attempt to write out of flash area bounds");
+
+      return ERROR;
+    }
+
+  /* Reposition the file offset from the beginning of the flash area */
+
+  seekpos = lseek(dev->fd, (off_t)off, SEEK_SET);
+  if (seekpos != off)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Seek to offset %" PRIu32 " failed: %d", off, errcode);
+
+      return ERROR;
+    }
+
+  /* Write the buffer to the flash block */
+
+  nbytes = write(dev->fd, src, len);
+  if (nbytes < 0)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Write to %s failed: %d", fa->fa_mtd_path, errcode);
+
+      return ERROR;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: flash_area_erase
+ *
+ * Description:
+ *   Erase a given flash area range.
+ *   Area boundaries are asserted before erase request. API has the same
+ *   limitation regarding erase-block alignment and size as the underlying
+ *   flash driver.
+ *
+ * Input Parameters:
+ *   fa  - Flash area to be erased.
+ *   off - Offset relative from beginning of flash area to be erased.
+ *   len - Number of bytes to be erase.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_erase(const struct flash_area *fa, uint32_t off, uint32_t len)
+{
+  int ret;
+  void *buffer;
+  size_t i;
+  struct flash_device_s *dev = lookup_flash_device_by_id(fa->fa_id);
+  const size_t sector_size = dev->mtdgeo.erasesize;
+  const uint8_t erase_val = dev->erase_state;
+
+  BOOT_LOG_INF("ID:%" PRIu8 " offset:%" PRIu32 " length:%" PRIu32,
+               fa->fa_id, off, len);
+
+  buffer = malloc(sector_size);
+  if (buffer == NULL)
+    {
+      BOOT_LOG_ERR("Failed to allocate erase buffer");
+
+      return ERROR;
+    }
+
+  memset(buffer, erase_val, sizeof(buffer));
+
+  i = 0;
+
+  do
+    {
+      BOOT_LOG_DBG("Erasing %zu bytes at offset %" PRIu32,
+                   sector_size, off + i);
+
+      ret = flash_area_write(fa, off + i, buffer, sector_size);
+      i += sector_size;
+    }
+  while (ret == OK && i < (len - sector_size));
+
+  if (ret == OK)
+    {
+      BOOT_LOG_DBG("Erasing %zu bytes at offset %" PRIu32,
+                   len - i, off + i);
+
+      ret = flash_area_write(fa, off + i, buffer, len - i);
+    }
+
+  free(buffer);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: flash_area_align
+ *
+ * Description:
+ *   Get write block size of the flash area.
+ *   Write block size might be treated as read block size, although most
+ *   drivers support unaligned readout.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   Alignment restriction for flash writes in the given flash area.
+ *
+ ****************************************************************************/
+
+uint8_t flash_area_align(const struct flash_area *fa)
+{
+  /* MTD access alignment is handled by the character and block device
+   * drivers.
+   */
+
+  const uint8_t minimum_write_length = 1;
+
+  BOOT_LOG_INF("ID:%" PRIu8 " align:%" PRIu8,
+               fa->fa_id, minimum_write_length);
+
+  return minimum_write_length;
+}
+
+/****************************************************************************
+ * Name: flash_area_erased_val
+ *
+ * Description:
+ *   Get the value expected to be read when accessing any erased flash byte.
+ *   This API is compatible with the MCUboot's porting layer.
+ *
+ * Input Parameters:
+ *   fa - Flash area.
+ *
+ * Returned Value:
+ *   Byte value of erased memory.
+ *
+ ****************************************************************************/
+
+uint8_t flash_area_erased_val(const struct flash_area *fa)
+{
+  struct flash_device_s *dev;
+  uint8_t erased_val;
+
+  dev = lookup_flash_device_by_id(fa->fa_id);
+
+  DEBUGASSERT(dev != NULL);
+
+  erased_val = dev->erase_state;
+
+  BOOT_LOG_INF("ID:%" PRIu8 " erased_val:0x%" PRIx8, fa->fa_id, erased_val);
+
+  return erased_val;
+}
+
+/****************************************************************************
+ * Name: flash_area_get_sectors
+ *
+ * Description:
+ *   Retrieve info about sectors within the area.
+ *
+ * Input Parameters:
+ *   fa_id   - ID of the flash area whose info will be retrieved.
+ *   count   - On input, represents the capacity of the sectors buffer.
+ *
+ * Output Parameters:
+ *   count   - On output, it shall contain the number of retrieved sectors.
+ *   sectors - Buffer for sectors data.
+ *
+ * Returned Value:
+ *   Zero on success, or negative value in case of error.
+ *
+ ****************************************************************************/
+
+int flash_area_get_sectors(int fa_id, uint32_t *count,
+                           struct flash_sector *sectors)
+{
+  size_t off;
+  uint32_t total_count = 0;
+  struct flash_device_s *dev = lookup_flash_device_by_id(fa_id);
+  const size_t sector_size = dev->mtdgeo.erasesize;
+  const struct flash_area *fa = fa = dev->fa_cfg;
+
+  for (off = 0; off < fa->fa_size; off += sector_size)
+    {
+      /* Note: Offset here is relative to flash area, not device */
+
+      sectors[total_count].fs_off = off;
+      sectors[total_count].fs_size = sector_size;
+      total_count++;
+    }
+
+  *count = total_count;
+
+  DEBUGASSERT(total_count == dev->mtdgeo.neraseblocks);
+
+  BOOT_LOG_INF("ID:%d count:%" PRIu32, fa_id, *count);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: flash_area_id_from_multi_image_slot
+ *
+ * Description:
+ *   Return the flash area ID for a given slot and a given image index
+ *   (in case of a multi-image setup).
+ *
+ * Input Parameters:
+ *   image_index - Index of the image.
+ *   slot        - Image slot, which may be 0 (primary) or 1 (secondary).
+ *
+ * Returned Value:
+ *   Flash area ID (0 or 1), or negative value in case the requested slot
+ *   is invalid.
+ *
+ ****************************************************************************/
+
+int flash_area_id_from_multi_image_slot(int image_index, int slot)
+{
+  BOOT_LOG_INF("image_index:%d slot:%d", image_index, slot);
+
+  switch (slot)
+    {
+      case 0:
+        return FLASH_AREA_IMAGE_PRIMARY(image_index);
+      case 1:
+        return FLASH_AREA_IMAGE_SECONDARY(image_index);
+    }
+
+  BOOT_LOG_ERR("Unexpected Request: image_index:%d, slot:%d",
+               image_index, slot);
+
+  return ERROR; /* flash_area_open will fail on that */
+}
+
+/****************************************************************************
+ * Name: flash_area_id_from_image_slot
+ *
+ * Description:
+ *   Return the flash area ID for a given slot.
+ *
+ * Input Parameters:
+ *   slot - Image slot, which may be 0 (primary) or 1 (secondary).
+ *
+ * Returned Value:
+ *   Flash area ID (0 or 1), or negative value in case the requested slot
+ *   is invalid.
+ *
+ ****************************************************************************/
+
+int flash_area_id_from_image_slot(int slot)
+{
+  BOOT_LOG_INF("slot:%d", slot);
+
+  return flash_area_id_from_multi_image_slot(0, slot);
+}
+
+/****************************************************************************
+ * Name: flash_area_id_to_multi_image_slot
+ *
+ * Description:
+ *   Convert the specified flash area ID and image index (in case of a
+ *   multi-image setup) to an image slot index.
+ *
+ * Input Parameters:
+ *   image_index - Index of the image.
+ *   fa_id       - Image slot, which may be 0 (primary) or 1 (secondary).
+ *
+ * Returned Value:
+ *   Image slot index (0 or 1), or negative value in case ID doesn't
+ *   correspond to an image slot.
+ *
+ ****************************************************************************/
+
+int flash_area_id_to_multi_image_slot(int image_index, int fa_id)
+{
+  BOOT_LOG_INF("image_index:%d fa_id:%d", image_index, fa_id);
+
+  if (fa_id == FLASH_AREA_IMAGE_PRIMARY(image_index))
+    {
+      return 0;
+    }
+
+  if (fa_id == FLASH_AREA_IMAGE_SECONDARY(image_index))
+    {
+      return 1;
+    }
+
+  BOOT_LOG_ERR("Unexpected Request: image_index:%d, fa_id:%d",
+               image_index, fa_id);
+
+  return ERROR; /* flash_area_open will fail on that */
+}
+
+/****************************************************************************
+ * Name: flash_area_id_from_image_offset
+ *
+ * Description:
+ *   Return the flash area ID for a given image offset.
+ *
+ * Input Parameters:
+ *   offset - Image offset.
+ *
+ * Returned Value:
+ *   Flash area ID (0 or 1), or negative value in case the requested slot
+ *   is invalid.
+ *
+ ****************************************************************************/
+
+int flash_area_id_from_image_offset(uint32_t offset)
+{
+  struct flash_device_s *dev = lookup_flash_device_by_offset(offset);
+
+  BOOT_LOG_INF("offset:%" PRIu32, offset);
+
+  return dev->fa_cfg->fa_id;
+}
diff --git a/boot/nuttx/src/watchdog/watchdog.c b/boot/nuttx/src/watchdog/watchdog.c
new file mode 100644
index 0000000..12f2aee
--- /dev/null
+++ b/boot/nuttx/src/watchdog/watchdog.c
@@ -0,0 +1,76 @@
+/****************************************************************************
+ * boot/nuttx/src/watchdog/watchdog.c
+ *
+ * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
+ *
+ * Licensed 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 "watchdog/watchdog.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#include <nuttx/timers/watchdog.h>
+
+#include <bootutil/bootutil_log.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: mcuboot_watchdog_feed
+ *
+ * Description:
+ *   Reset the watchdog timer to the current timeout value, preventing any
+ *   imminent watchdog timeouts.
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void mcuboot_watchdog_feed(void)
+{
+  int fd;
+  int ret;
+
+  fd = open(CONFIG_MCUBOOT_WATCHDOG_DEVPATH, O_RDONLY);
+  if (fd < 0)
+    {
+      BOOT_LOG_ERR("Failed to open %s", CONFIG_MCUBOOT_WATCHDOG_DEVPATH);
+
+      return;
+    }
+
+  ret = ioctl(fd, WDIOC_KEEPALIVE, 0);
+  if (ret < 0)
+    {
+      int errcode = errno;
+
+      BOOT_LOG_ERR("Failed to ping watchdog device: %d", errcode);
+    }
+
+  close(fd);
+}