loader: added hooks for override mcuboot image access operation

Added hook for read image header.

Added hook which is for inject an image check implementation which can
be used instead of boot_image_check() internal implementation on a primary
slot.
This is usefully especially when primary has to be checked by other entity
on MCUboot's demand.

Added hook which allow to implement image update process
differently.

Signed-off-by: Andrzej Puzdrowski <andrzej.puzdrowski@nordicsemi.no>
diff --git a/boot/bootutil/include/bootutil/boot_hooks.h b/boot/bootutil/include/bootutil/boot_hooks.h
new file mode 100644
index 0000000..a94c5de
--- /dev/null
+++ b/boot/bootutil/include/bootutil/boot_hooks.h
@@ -0,0 +1,122 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Copyright (c) 2021 Nordic Semiconductor ASA
+ *
+ * Original license:
+ *
+ * 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.
+ */
+
+/**
+ * @file
+ * @brief Hooks definition implementation API
+ *
+ * This file contains API interface definition for hooks which can be
+ * implemented to overide or to amend some of MCUboot's native routines.
+ */
+
+#ifndef H_BOOTUTIL_HOOKS
+#define H_BOOTUTIL_HOOKS
+
+#ifdef MCUBOOT_IMAGE_ACCESS_HOOKS
+
+#define BOOT_HOOK_CALL(f, ret_default, ...) f(__VA_ARGS__)
+
+#define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \
+    do { \
+        FIH_CALL(f, fih_rc, __VA_ARGS__); \
+    } while(0);
+
+#else
+
+#define BOOT_HOOK_CALL(f, ret_default, ...) ret_default
+
+#define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \
+    do { \
+        fih_rc = fih_ret_default; \
+    } while(0);
+
+#endif
+
+/** Hook for provide image header data.
+ *
+ * This Hook may be used to overide image header read implementation or doing
+ * a custom action before.
+ *
+ * @param img_index the index of the image pair
+ * @param slot slot number
+ * @param img_head image header structure to be populated
+ *
+ * @retval 0: header was read/populated, skip direct header data read
+ *         BOOT_HOOK_REGULAR: follow the normal execution path,
+ *         otherwise an error-code value.
+ */
+int boot_read_image_header_hook(int img_index, int slot,
+                                struct image_header *img_head);
+
+/** Hook for Validate image hash/signature
+ *
+ * This Hook may be used to overide image validation procedure or doing
+ * a custom action before.
+ *
+ * @param img_index the index of the image pair
+ * @param slot slot number
+ * 
+ * @retval FIH_SUCCESS: image is valid, skip direct validation
+ *         FIH_FAILURE: image is invalid, skip direct validation
+ *         fih encoded BOOT_HOOK_REGULAR: follow the normal execution path.
+ */
+fih_int boot_image_check_hook(int img_index, int slot);
+
+/** Hook for implement image update
+ *
+ * This hook is for for implementing an alternative mechanism of image update or
+ * doing a custom action before.
+ *
+ * @param img_index the index of the image pair
+ * @param img_head the image header of the secondary image
+ * @param area the flash area of the secondary image.
+ *
+ * @retval 0: update was done, skip performing the update
+ *         BOOT_HOOK_REGULAR: follow the normal execution path,
+ *         otherwise an error-code value.
+ */
+int boot_perform_update_hook(int img_index, struct image_header *img_head,
+                             const struct flash_area *area);
+
+/** Hook for implement image's post copying action
+ *
+ * This hook is for implement action which might be done right after image was
+ * copied to the primary slot. This hook is called in MCUBOOT_OVERWRITE_ONLY
+ * mode only.
+ *
+ * @param img_index the index of the image pair
+ * @param area the flash area of the primary image.
+ * @param size size of copied image.
+ *
+ * @retval 0: success, mcuboot will follow normal code execution flow after
+ *            execution of this call.
+ *         non-zero: an error, mcuboot will return from
+ *         boot_copy_image() with error.
+ *         Update will be undone so might be resume on the next boot.
+ */
+int boot_copy_region_post_hook(int img_index, const struct flash_area *area,
+                               size_t size);
+
+#endif /*H_BOOTUTIL_HOOKS*/
diff --git a/boot/bootutil/include/bootutil/bootutil_public.h b/boot/bootutil/include/bootutil/bootutil_public.h
index 60aeef0..3a0e38a 100644
--- a/boot/bootutil/include/bootutil/bootutil_public.h
+++ b/boot/bootutil/include/bootutil/bootutil_public.h
@@ -99,6 +99,7 @@
 #define BOOT_EBADVERSION 8
 #define BOOT_EFLASH_SEC  9
 
+#define BOOT_HOOK_REGULAR 1
 /*
  * Extract the swap type and image number from image trailers's swap_info
  * filed.
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index e977d65..8816d63 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -44,6 +44,7 @@
 #include "bootutil/boot_record.h"
 #include "bootutil/fault_injection_hardening.h"
 #include "bootutil/ramload.h"
+#include "bootutil/boot_hooks.h"
 
 #ifdef MCUBOOT_ENC_IMAGES
 #include "bootutil/enc_key.h"
@@ -102,7 +103,12 @@
     int i;
 
     for (i = 0; i < BOOT_NUM_SLOTS; i++) {
-        rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs);
+        rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR,
+                            BOOT_CURR_IMG(state), i, boot_img_hdr(state, i));
+        if (rc == BOOT_HOOK_REGULAR)
+        {
+            rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs);
+        }
         if (rc != 0) {
             /* If `require_all` is set, fail on any single fail, otherwise
              * if at least the first slot's header was read successfully,
@@ -759,8 +765,12 @@
         }
     }
 #endif
-
-    FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs);
+    BOOT_HOOK_CALL_FIH(boot_image_check_hook, fih_int_encode(BOOT_HOOK_REGULAR),
+                       fih_rc, BOOT_CURR_IMG(state), slot);
+    if (fih_eq(fih_rc, BOOT_HOOK_REGULAR))
+    {
+        FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs);
+    }
     if (!boot_is_header_valid(hdr, fap) || fih_not_eq(fih_rc, FIH_SUCCESS)) {
         if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) {
             flash_area_erase(fap, 0, flash_area_get_size(fap));
@@ -1107,6 +1117,12 @@
     }
 #endif
 
+    rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state),
+                        BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size);
+    if (rc != 0) {
+        return rc;
+    }
+
 #ifdef MCUBOOT_HW_ROLLBACK_PROT
     /* Update the stored security counter with the new image's security counter
      * value. Both slots hold the new image at this point, but the secondary
@@ -1964,7 +1980,13 @@
         case BOOT_SWAP_TYPE_TEST:          /* fallthrough */
         case BOOT_SWAP_TYPE_PERM:          /* fallthrough */
         case BOOT_SWAP_TYPE_REVERT:
-            rc = boot_perform_update(state, &bs);
+            rc = BOOT_HOOK_CALL(boot_perform_update_hook, BOOT_HOOK_REGULAR,
+                                BOOT_CURR_IMG(state), &(BOOT_IMG(state, 1).hdr),
+                                BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT));
+            if (rc == BOOT_HOOK_REGULAR)
+            {
+                rc = boot_perform_update(state, &bs);
+            }
             assert(rc == 0);
             break;