1 /* 2 * SPDX-License-Identifier: Apache-2.0 3 * 4 * Copyright (c) 2021 Nordic Semiconductor ASA 5 * 6 * Original license: 7 * 8 * Licensed to the Apache Software Foundation (ASF) under one 9 * or more contributor license agreements. See the NOTICE file 10 * distributed with this work for additional information 11 * regarding copyright ownership. The ASF licenses this file 12 * to you under the Apache License, Version 2.0 (the 13 * "License"); you may not use this file except in compliance 14 * with the License. You may obtain a copy of the License at 15 * 16 * http://www.apache.org/licenses/LICENSE-2.0 17 * 18 * Unless required by applicable law or agreed to in writing, 19 * software distributed under the License is distributed on an 20 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 * KIND, either express or implied. See the License for the 22 * specific language governing permissions and limitations 23 * under the License. 24 */ 25 26 /** 27 * @file 28 * @brief Hooks definition implementation API 29 * 30 * This file contains API interface definition for hooks which can be 31 * implemented to overide or to amend some of MCUboot's native routines. 32 */ 33 34 #ifndef H_BOOTUTIL_HOOKS 35 #define H_BOOTUTIL_HOOKS 36 37 #include "bootutil/bootutil.h" 38 #include "bootutil/fault_injection_hardening.h" 39 40 #define DO_HOOK_CALL(f, ret_default, ...) \ 41 f(__VA_ARGS__) 42 43 #define DO_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \ 44 do { \ 45 FIH_CALL(f, fih_rc, __VA_ARGS__); \ 46 } while(0); 47 48 #define HOOK_CALL_NOP(f, ret_default, ...) ret_default 49 50 #define HOOK_CALL_FIH_NOP(f, fih_ret_default, fih_rc, ...) \ 51 do { \ 52 fih_rc = fih_ret_default; \ 53 } while(0); 54 55 #ifdef MCUBOOT_IMAGE_ACCESS_HOOKS 56 57 #define BOOT_HOOK_CALL(f, ret_default, ...) \ 58 DO_HOOK_CALL(f, ret_default, __VA_ARGS__) 59 60 #define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \ 61 DO_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, __VA_ARGS__) 62 63 #else 64 65 #define BOOT_HOOK_CALL(f, ret_default, ...) \ 66 HOOK_CALL_NOP(f, ret_default, __VA_ARGS__) 67 68 #define BOOT_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, ...) \ 69 HOOK_CALL_FIH_NOP(f, fih_ret_default, fih_rc, __VA_ARGS__) 70 71 #endif /* MCUBOOT_IMAGE_ACCESS_HOOKS */ 72 73 #ifdef MCUBOOT_BOOT_GO_HOOKS 74 75 #define BOOT_HOOK_GO_CALL_FIH(f, fih_ret_default, fih_rc, ...) \ 76 DO_HOOK_CALL_FIH(f, fih_ret_default, fih_rc, __VA_ARGS__); 77 78 #else 79 80 #define BOOT_HOOK_GO_CALL_FIH(f, fih_ret_default, fih_rc, ...) \ 81 HOOK_CALL_FIH_NOP(f, fih_ret_default, fih_rc, __VA_ARGS__) 82 83 #endif /* MCUBOOT_BOOT_GO_HOOKS */ 84 85 #ifdef MCUBOOT_FLASH_AREA_HOOKS 86 87 #define BOOT_HOOK_FLASH_AREA_CALL(f, ret_default, ...) \ 88 DO_HOOK_CALL(f, ret_default, __VA_ARGS__) 89 90 #else 91 92 #define BOOT_HOOK_FLASH_AREA_CALL(f, ret_default, ...) \ 93 HOOK_CALL_NOP(f, ret_default, __VA_ARGS__) 94 95 #endif /* MCUBOOT_FLASH_AREA_ID_HOOKS */ 96 97 /** Hook for provide image header data. 98 * 99 * This Hook may be used to overide image header read implementation or doing 100 * a custom action before. 101 * 102 * @param img_index the index of the image pair 103 * @param slot slot number 104 * @param img_head image header structure to be populated 105 * 106 * @retval 0: header was read/populated, skip direct header data read 107 * BOOT_HOOK_REGULAR: follow the normal execution path, 108 * otherwise an error-code value. 109 */ 110 int boot_read_image_header_hook(int img_index, int slot, 111 struct image_header *img_head); 112 113 /** Hook for Validate image hash/signature 114 * 115 * This Hook may be used to overide image validation procedure or doing 116 * a custom action before. 117 * 118 * @param img_index the index of the image pair 119 * @param slot slot number 120 * 121 * @retval FIH_SUCCESS: image is valid, skip direct validation 122 * FIH_FAILURE: image is invalid, skip direct validation 123 * FIH_BOOT_HOOK_REGULAR: follow the normal execution path. 124 */ 125 fih_ret boot_image_check_hook(int img_index, int slot); 126 127 /** Hook for implement image update 128 * 129 * This hook is for for implementing an alternative mechanism of image update or 130 * doing a custom action before. 131 * 132 * @param img_index the index of the image pair 133 * @param img_head the image header of the secondary image 134 * @param area the flash area of the secondary image. 135 * 136 * @retval 0: update was done, skip performing the update 137 * BOOT_HOOK_REGULAR: follow the normal execution path, 138 * otherwise an error-code value. 139 */ 140 int boot_perform_update_hook(int img_index, struct image_header *img_head, 141 const struct flash_area *area); 142 143 /** Hook for implement image's post copying action 144 * 145 * This hook is for implement action which might be done right after image was 146 * copied to the primary slot. This hook is called in MCUBOOT_OVERWRITE_ONLY 147 * mode only. 148 * 149 * @param img_index the index of the image pair 150 * @param area the flash area of the primary image. 151 * @param size size of copied image. 152 * 153 * @retval 0: success, mcuboot will follow normal code execution flow after 154 * execution of this call. 155 * non-zero: an error, mcuboot will return from 156 * boot_copy_image() with error. 157 * Update will be undone so might be resume on the next boot. 158 */ 159 int boot_copy_region_post_hook(int img_index, const struct flash_area *area, 160 size_t size); 161 162 /** Hook for implement image's post recovery upload action 163 * 164 * This hook is for implement action which might be done right after image was 165 * copied to the primary slot. This hook is called in serial recovery upload 166 * operation. 167 * 168 * @param img_index the index of the image pair 169 * @param area the flash area of the primary image. 170 * @param size size of copied image. 171 * 172 * @retval 0: success, mcuboot will follow normal code execution flow after 173 * execution of this call. 174 * non-zero: an error, will be transferred as part of comand response 175 * as "rc" entry. 176 */ 177 int boot_serial_uploaded_hook(int img_index, const struct flash_area *area, 178 size_t size); 179 180 /** Hook for implement the image's slot installation status fetch operation for 181 * the MGMT custom command. 182 * 183 * The image's slot installation status is custom property. It's detailed 184 * definition depends on user implementation. It is only defined that the status 185 * will be set to 0 if this hook not provides another value. 186 * 187 * @param img_index the index of the image pair 188 * @param slot slot number 189 * @param img_install_stat the image installation status to be populated 190 * 191 * @retval 0: the installaton status was fetched successfully, 192 * BOOT_HOOK_REGULAR: follow the normal execution path, status will be 193 * set to 0 194 * otherwise an error-code value. Error-code is ignored, but it is up to 195 * the implementation to reflect this error in img_install_stat. 196 */ 197 int boot_img_install_stat_hook(int image_index, int slot, 198 int *img_install_stat); 199 200 /** Hook will be invoked when boot_serial requests device reset. 201 * The hook may be used to prevent device reset. 202 * 203 * @param force set to true when request tries to force reset. 204 * 205 * @retval 0 when reset should be performed; 206 * BOOT_RESET_REQUEST_HOOK_BUSY when some processing is still in 207 * progress; 208 * BOOT_RESET_REQUEST_HOOK_TIMEOUT internal process timed out; 209 * BOOT_RESET_REQUEST_HOOK_CHECK_FAILED internal code failed to 210 * obtian status; 211 * BOOT_RESET_REQUEST_HOOK_INTERNAL_ERROR unspecified internal 212 * error while checking status. 213 */ 214 int boot_reset_request_hook(bool force); 215 216 /** 217 * Hook to implement custom action before boot_go() function. 218 * 219 * @param rsp boot response structure. 220 * 221 * @retval FIH_SUCCESS: boot_go() should be skipped, boot response is already 222 * filled. 223 * FIH_FAILURE: boot_go() should be skipped, boot response is already 224 * filled with error. 225 * FIH_BOOT_HOOK_REGULAR: follow the normal execution path. 226 */ 227 fih_ret boot_go_hook(struct boot_rsp *rsp); 228 229 /** 230 * Hook to implement custom action before retrieving flash area ID. 231 * 232 * @param image_index the index of the image pair 233 * @param slot slot number 234 * @param area_id the flash area ID to be populated 235 * 236 * @retval 0 the flash area ID was fetched successfully; 237 * BOOT_HOOK_REGULAR follow the normal execution path to get the flash 238 * area ID; 239 * otherwise an error-code value. 240 */ 241 int flash_area_id_from_multi_image_slot_hook(int image_index, int slot, 242 int *area_id); 243 244 /** 245 * Hook to implement custom action before retrieving flash area device ID. 246 * 247 * @param fa the flash area structure 248 * @param device_id the device ID to be populated 249 * 250 * @retval 0 the device ID was fetched successfully; 251 * BOOT_HOOK_REGULAR follow the normal execution path to get the device 252 * ID; 253 * otherwise an error-code value. 254 */ 255 int flash_area_get_device_id_hook(const struct flash_area *fa, 256 uint8_t *device_id); 257 258 #define BOOT_RESET_REQUEST_HOOK_BUSY 1 259 #define BOOT_RESET_REQUEST_HOOK_TIMEOUT 2 260 #define BOOT_RESET_REQUEST_HOOK_CHECK_FAILED 3 261 #define BOOT_RESET_REQUEST_HOOK_INTERNAL_ERROR 4 262 263 #endif /*H_BOOTUTIL_HOOKS*/ 264