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