1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2022, Linaro Limited
4  */
5 
6 #include <dm.h>
7 #include <efi.h>
8 #include <efi_loader.h>
9 #include <efi_variable.h>
10 #include <event.h>
11 #include <fwu.h>
12 #include <fwu_mdata.h>
13 #include <log.h>
14 #include <malloc.h>
15 
16 #include <linux/errno.h>
17 #include <linux/types.h>
18 
19 #include <u-boot/crc.h>
20 
21 struct fwu_data g_fwu_data;
22 static struct udevice *g_dev;
23 static u8 in_trial;
24 static u8 boottime_check;
25 
26 enum {
27 	IMAGE_ACCEPT_SET = 1,
28 	IMAGE_ACCEPT_CLEAR,
29 };
30 
31 /**
32  * fwu_bank_accepted() - Has the bank been accepted
33  * @data: Version agnostic FWU metadata information
34  * @bank: Update bank to check
35  *
36  * Check in the given bank if all the images have been accepted.
37  *
38  * Return: true if all images accepted, false otherwise
39  */
fwu_bank_accepted(struct fwu_data * data,uint32_t bank)40 bool fwu_bank_accepted(struct fwu_data *data, uint32_t bank)
41 {
42 	u32 i;
43 	struct fwu_image_entry *img_entry;
44 	struct fwu_image_bank_info *img_bank_info;
45 
46 	img_entry = &data->fwu_images[0];
47 	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
48 		img_bank_info = &img_entry[i].img_bank_info[bank];
49 		if (!img_bank_info->accepted)
50 			return false;
51 	}
52 
53 	return true;
54 }
55 
trial_counter_update(u16 * trial_state_ctr)56 static int trial_counter_update(u16 *trial_state_ctr)
57 {
58 	bool delete;
59 	u32 var_attr;
60 	efi_status_t status;
61 	efi_uintn_t var_size;
62 
63 	delete = !trial_state_ctr ? true : false;
64 	var_size = !trial_state_ctr ? 0 : (efi_uintn_t)sizeof(*trial_state_ctr);
65 	var_attr = !trial_state_ctr ? 0 : EFI_VARIABLE_NON_VOLATILE |
66 		EFI_VARIABLE_BOOTSERVICE_ACCESS;
67 	status = efi_set_variable_int(u"TrialStateCtr",
68 				      &efi_global_variable_guid,
69 				      var_attr,
70 				      var_size, trial_state_ctr, false);
71 
72 	if ((delete && (status != EFI_NOT_FOUND &&
73 			status != EFI_SUCCESS)) ||
74 	    (!delete && status != EFI_SUCCESS))
75 		return -1;
76 
77 	return 0;
78 }
79 
trial_counter_read(u16 * trial_state_ctr)80 static int trial_counter_read(u16 *trial_state_ctr)
81 {
82 	efi_status_t status;
83 	efi_uintn_t var_size;
84 
85 	var_size = (efi_uintn_t)sizeof(trial_state_ctr);
86 	status = efi_get_variable_int(u"TrialStateCtr",
87 				      &efi_global_variable_guid,
88 				      NULL,
89 				      &var_size, trial_state_ctr,
90 				      NULL);
91 	if (status != EFI_SUCCESS) {
92 		log_err("Unable to read TrialStateCtr variable\n");
93 		return -1;
94 	}
95 
96 	return 0;
97 }
98 
fwu_trial_count_update(void)99 static int fwu_trial_count_update(void)
100 {
101 	int ret;
102 	u16 trial_state_ctr;
103 
104 	ret = trial_counter_read(&trial_state_ctr);
105 	if (ret) {
106 		log_debug("Unable to read trial_state_ctr\n");
107 		goto out;
108 	}
109 
110 	++trial_state_ctr;
111 	if (trial_state_ctr > CONFIG_FWU_TRIAL_STATE_CNT) {
112 		log_info("Trial State count exceeded. Revert back to previous_active_index\n");
113 		ret = fwu_revert_boot_index();
114 		if (ret)
115 			log_err("Unable to revert active_index\n");
116 
117 		trial_counter_update(NULL);
118 		ret = 1;
119 	} else {
120 		log_info("Trial State count: attempt %d out of %d\n",
121 			 trial_state_ctr, CONFIG_FWU_TRIAL_STATE_CNT);
122 		ret = trial_counter_update(&trial_state_ctr);
123 		if (ret)
124 			log_err("Unable to increment TrialStateCtr variable\n");
125 	}
126 
127 out:
128 	return ret;
129 }
130 
in_trial_state(void)131 static u32 in_trial_state(void)
132 {
133 	return g_fwu_data.trial_state;
134 }
135 
fwu_get_image_type_id(u8 image_index,efi_guid_t * image_type_id)136 static int fwu_get_image_type_id(u8 image_index, efi_guid_t *image_type_id)
137 {
138 	int i;
139 	struct efi_fw_image *image;
140 
141 	image = update_info.images;
142 	for (i = 0; i < update_info.num_images; i++) {
143 		if (image_index == image[i].image_index) {
144 			guidcpy(image_type_id, &image[i].image_type_id);
145 			return 0;
146 		}
147 	}
148 
149 	return -ENOENT;
150 }
151 
mdata_crc_check(struct fwu_mdata * mdata)152 static int mdata_crc_check(struct fwu_mdata *mdata)
153 {
154 	int ret;
155 	u32 calc_crc32;
156 	uint32_t mdata_size;
157 	void *buf = &mdata->version;
158 
159 	ret = fwu_get_mdata_size(&mdata_size);
160 	if (ret)
161 		return ret;
162 
163 	calc_crc32 = crc32(0, buf, mdata_size - sizeof(u32));
164 	return calc_crc32 == mdata->crc32 ? 0 : -EINVAL;
165 }
166 
fwu_data_crc_update(uint32_t crc32)167 static void fwu_data_crc_update(uint32_t crc32)
168 {
169 	g_fwu_data.crc32 = crc32;
170 }
171 
172 /**
173  * fwu_get_data() - Return the version agnostic FWU structure
174  *
175  * Return the pointer to the version agnostic FWU structure.
176  *
177  * Return: Pointer to the FWU data structure
178  */
fwu_get_data(void)179 struct fwu_data *fwu_get_data(void)
180 {
181 	return &g_fwu_data;
182 }
183 
fwu_populate_mdata_bank_index(struct fwu_data * fwu_data)184 static void fwu_populate_mdata_bank_index(struct fwu_data *fwu_data)
185 {
186 	struct fwu_mdata *mdata = fwu_data->fwu_mdata;
187 
188 	mdata->active_index = fwu_data->active_index;
189 	mdata->previous_active_index = fwu_data->previous_active_index;
190 }
191 
192 /**
193  * fwu_get_dev() - Return the FWU metadata device
194  *
195  * Return the pointer to the FWU metadata device.
196  *
197  * Return: Pointer to the FWU metadata dev
198  */
fwu_get_dev(void)199 struct udevice *fwu_get_dev(void)
200 {
201 	return g_dev;
202 }
203 
204 /**
205  * fwu_sync_mdata() - Update given meta-data partition(s) with the copy provided
206  * @data: FWU Data structure
207  * @part: Bitmask of FWU metadata partitions to be written to
208  *
209  * Return: 0 if OK, -ve on error
210  */
fwu_sync_mdata(struct fwu_mdata * mdata,int part)211 int fwu_sync_mdata(struct fwu_mdata *mdata, int part)
212 {
213 	int err;
214 	uint mdata_size;
215 	void *buf = &mdata->version;
216 
217 	if (part == BOTH_PARTS) {
218 		err = fwu_sync_mdata(mdata, SECONDARY_PART);
219 		if (err)
220 			return err;
221 		part = PRIMARY_PART;
222 	}
223 
224 	err = fwu_get_mdata_size(&mdata_size);
225 	if (err)
226 		return err;
227 
228 	/*
229 	 * Calculate the crc32 for the updated FWU metadata
230 	 * and put the updated value in the FWU metadata crc32
231 	 * field
232 	 */
233 	mdata->crc32 = crc32(0, buf, mdata_size - sizeof(u32));
234 	fwu_data_crc_update(mdata->crc32);
235 
236 	err = fwu_write_mdata(g_dev, mdata, part == PRIMARY_PART, mdata_size);
237 	if (err) {
238 		log_err("Unable to write %s mdata\n",
239 			part == PRIMARY_PART ?  "primary" : "secondary");
240 		return err;
241 	}
242 
243 	return 0;
244 }
245 
246 /**
247  * fwu_mdata_copies_allocate() - Allocate memory for metadata
248  * @mdata_size: Size of the metadata structure
249  *
250  * Allocate memory for storing both the copies of the FWU metadata. The
251  * copies are then used as a cache for storing FWU metadata contents.
252  *
253  * Return: 0 if OK, -ve on error
254  */
fwu_mdata_copies_allocate(u32 mdata_size)255 int fwu_mdata_copies_allocate(u32 mdata_size)
256 {
257 	if (g_fwu_data.fwu_mdata)
258 		return 0;
259 
260 	/*
261 	 * Allocate the total memory that would be needed for both
262 	 * the copies.
263 	 */
264 	g_fwu_data.fwu_mdata = calloc(2, mdata_size);
265 	if (!g_fwu_data.fwu_mdata) {
266 		log_err("Unable to allocate space for FWU metadata\n");
267 		return -ENOMEM;
268 	}
269 
270 	return 0;
271 }
272 
273 /**
274  * fwu_get_mdata() - Read, verify and return the FWU metadata
275  * @mdata: Output FWU metadata read or NULL
276  *
277  * Read both the metadata copies from the storage media, verify their checksum,
278  * and ascertain that both copies match. If one of the copies has gone bad,
279  * restore it from the good copy.
280  *
281  * Return: 0 if OK, -ve on error
282  */
fwu_get_mdata(struct fwu_mdata * mdata)283 int fwu_get_mdata(struct fwu_mdata *mdata)
284 {
285 	int err;
286 	uint32_t mdata_size;
287 	bool parts_ok[2] = { false };
288 	struct fwu_mdata *parts_mdata[2];
289 
290 	err = fwu_get_mdata_size(&mdata_size);
291 	if (err)
292 		return err;
293 
294 	parts_mdata[0] = g_fwu_data.fwu_mdata;
295 	if (!parts_mdata[0]) {
296 		log_err("Memory not allocated for the FWU Metadata copies\n");
297 		return -ENOMEM;
298 	}
299 
300 	parts_mdata[1] = (struct fwu_mdata *)((char *)parts_mdata[0] +
301 					      mdata_size);
302 
303 	/* if mdata already read and ready */
304 	err = mdata_crc_check(parts_mdata[0]);
305 	if (!err)
306 		goto ret_mdata;
307 
308 	/* else read, verify and, if needed, fix mdata */
309 	for (int i = 0; i < 2; i++) {
310 		parts_ok[i] = false;
311 		err = fwu_read_mdata(g_dev, parts_mdata[i], !i, mdata_size);
312 		if (!err) {
313 			err = mdata_crc_check(parts_mdata[i]);
314 			if (!err)
315 				parts_ok[i] = true;
316 			else
317 				log_debug("mdata : %s crc32 failed\n", i ? "secondary" : "primary");
318 		}
319 	}
320 
321 	if (parts_ok[0] && parts_ok[1]) {
322 		/*
323 		 * Before returning, check that both the
324 		 * FWU metadata copies are the same.
325 		 */
326 		err = memcmp(parts_mdata[0], parts_mdata[1], mdata_size);
327 		if (!err)
328 			goto ret_mdata;
329 
330 		/*
331 		 * If not, populate the secondary partition from the
332 		 * primary partition copy.
333 		 */
334 		log_info("Both FWU metadata copies are valid but do not match.");
335 		log_info(" Restoring the secondary partition from the primary\n");
336 		parts_ok[1] = false;
337 	}
338 
339 	for (int i = 0; i < 2; i++) {
340 		if (parts_ok[i])
341 			continue;
342 
343 		memcpy(parts_mdata[i], parts_mdata[1 - i], mdata_size);
344 		err = fwu_sync_mdata(parts_mdata[i], i ? SECONDARY_PART : PRIMARY_PART);
345 		if (err) {
346 			log_debug("mdata : %s write failed\n", i ? "secondary" : "primary");
347 			return err;
348 		}
349 	}
350 
351 ret_mdata:
352 	if (!err && mdata)
353 		memcpy(mdata, parts_mdata[0], mdata_size);
354 
355 	return err;
356 }
357 
358 /**
359  * fwu_get_active_index() - Get active_index from the FWU metadata
360  * @active_idx: active_index value to be read
361  *
362  * Read the active_index field from the FWU metadata and place it in
363  * the variable pointed to be the function argument.
364  *
365  * Return: 0 if OK, -ve on error
366  *
367  */
fwu_get_active_index(uint * active_idx)368 int fwu_get_active_index(uint *active_idx)
369 {
370 	int ret = 0;
371 	struct fwu_data *data = &g_fwu_data;
372 
373 	/*
374 	 * Found the FWU metadata partition, now read the active_index
375 	 * value
376 	 */
377 	*active_idx = data->active_index;
378 	if (*active_idx >= CONFIG_FWU_NUM_BANKS) {
379 		log_debug("Active index value read is incorrect\n");
380 		ret = -EINVAL;
381 	}
382 
383 	return ret;
384 }
385 
386 /**
387  * fwu_set_active_index() - Set active_index in the FWU metadata
388  * @active_idx: active_index value to be set
389  *
390  * Update the active_index field in the FWU metadata
391  *
392  * Return: 0 if OK, -ve on error
393  *
394  */
fwu_set_active_index(uint active_idx)395 int fwu_set_active_index(uint active_idx)
396 {
397 	int ret;
398 	struct fwu_data *data =  &g_fwu_data;
399 
400 	if (active_idx >= CONFIG_FWU_NUM_BANKS) {
401 		log_debug("Invalid active index value\n");
402 		return -EINVAL;
403 	}
404 
405 	/*
406 	 * Update the active index and previous_active_index fields
407 	 * in the FWU metadata
408 	 */
409 	data->previous_active_index = data->active_index;
410 	data->active_index = active_idx;
411 
412 	fwu_populate_mdata_bank_index(data);
413 
414 	/*
415 	 * Now write this updated FWU metadata to both the
416 	 * FWU metadata partitions
417 	 */
418 	ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS);
419 	if (ret) {
420 		log_debug("Failed to update FWU metadata partitions\n");
421 		ret = -EIO;
422 	}
423 
424 	return ret;
425 }
426 
427 /**
428  * fwu_get_dfu_alt_num() - Get the dfu_alt_num to be used for capsule update
429  * @image_index:	The Image Index for the image
430  * @alt_num:		pointer to store dfu_alt_num
431  *
432  * Currently, the capsule update driver uses the DFU framework for
433  * the updates. This function gets the DFU alt number which is to
434  * be used for capsule update.
435  *
436  * Return: 0 if OK, -ve on error
437  *
438  */
fwu_get_dfu_alt_num(u8 image_index,u8 * alt_num)439 int fwu_get_dfu_alt_num(u8 image_index, u8 *alt_num)
440 {
441 	int ret, i;
442 	uint update_bank;
443 	efi_guid_t *image_guid, image_type_id;
444 	struct fwu_data *data = &g_fwu_data;
445 	struct fwu_image_entry *img_entry;
446 	struct fwu_image_bank_info *img_bank_info;
447 
448 	ret = fwu_plat_get_update_index(&update_bank);
449 	if (ret) {
450 		log_debug("Failed to get the FWU update bank\n");
451 		goto out;
452 	}
453 
454 	ret = fwu_get_image_type_id(image_index, &image_type_id);
455 	if (ret) {
456 		log_debug("Unable to get image_type_id for image_index %u\n",
457 			  image_index);
458 		goto out;
459 	}
460 
461 	ret = -EINVAL;
462 	/*
463 	 * The FWU metadata has been read. Now get the image_guid for the
464 	 * image with the update_bank.
465 	 */
466 	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
467 		if (!guidcmp(&image_type_id,
468 			     &data->fwu_images[i].image_type_guid)) {
469 			img_entry = &data->fwu_images[i];
470 			img_bank_info = &img_entry->img_bank_info[update_bank];
471 			image_guid = &img_bank_info->image_guid;
472 			ret = fwu_plat_get_alt_num(g_dev, image_guid, alt_num);
473 			if (ret)
474 				log_debug("alt_num not found for partition with GUID %pUs\n",
475 					  image_guid);
476 			else
477 				log_debug("alt_num %d for partition %pUs\n",
478 					  *alt_num, image_guid);
479 
480 			goto out;
481 		}
482 	}
483 
484 	log_err("Partition with the image type %pUs not found\n",
485 		&image_type_id);
486 
487 out:
488 	return ret;
489 }
490 
491 /**
492  * fwu_revert_boot_index() - Revert the active index in the FWU metadata
493  *
494  * Revert the active_index value in the FWU metadata, by swapping the values
495  * of active_index and previous_active_index in both copies of the
496  * FWU metadata.
497  *
498  * Return: 0 if OK, -ve on error
499  *
500  */
fwu_revert_boot_index(void)501 int fwu_revert_boot_index(void)
502 {
503 	int ret;
504 	u32 cur_active_index;
505 	struct fwu_data *data =  &g_fwu_data;
506 
507 	/*
508 	 * Swap the active index and previous_active_index fields
509 	 * in the FWU metadata
510 	 */
511 	cur_active_index = data->active_index;
512 	data->active_index = data->previous_active_index;
513 	data->previous_active_index = cur_active_index;
514 
515 	fwu_populate_mdata_bank_index(data);
516 
517 	/*
518 	 * Now write this updated FWU metadata to both the
519 	 * FWU metadata partitions
520 	 */
521 	ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS);
522 	if (ret) {
523 		log_debug("Failed to update FWU metadata partitions\n");
524 		ret = -EIO;
525 	}
526 
527 	return ret;
528 }
529 
530 /**
531  * fwu_clrset_image_accept() - Set or Clear the Acceptance bit for the image
532  * @img_type_id: GUID of the image type for which the accepted bit is to be
533  *               set or cleared
534  * @bank: Bank of which the image's Accept bit is to be set or cleared
535  * @action: Action which specifies whether image's Accept bit is to be set or
536  *          cleared
537  *
538  * Set/Clear the accepted bit for the image specified by the img_guid parameter.
539  * This indicates acceptance or rejection of image for subsequent boots by some
540  * governing component like OS(or firmware).
541  *
542  * Return: 0 if OK, -ve on error
543  *
544  */
fwu_clrset_image_accept(efi_guid_t * img_type_id,u32 bank,u8 action)545 static int fwu_clrset_image_accept(efi_guid_t *img_type_id, u32 bank, u8 action)
546 {
547 	int ret, i;
548 	struct fwu_data *data = &g_fwu_data;
549 	struct fwu_image_entry *img_entry;
550 	struct fwu_image_bank_info *img_bank_info;
551 
552 	img_entry = &data->fwu_images[0];
553 	for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) {
554 		if (!guidcmp(&img_entry[i].image_type_guid, img_type_id)) {
555 			img_bank_info = &img_entry[i].img_bank_info[bank];
556 			if (action == IMAGE_ACCEPT_SET)
557 				img_bank_info->accepted |= FWU_IMAGE_ACCEPTED;
558 			else
559 				img_bank_info->accepted = 0;
560 
561 			fwu_populate_mdata_image_info(data);
562 			ret = fwu_sync_mdata(data->fwu_mdata, BOTH_PARTS);
563 			goto out;
564 		}
565 	}
566 
567 	/* Image not found */
568 	ret = -ENOENT;
569 
570 out:
571 	return ret;
572 }
573 
574 /**
575  * fwu_accept_image() - Set the Acceptance bit for the image
576  * @img_type_id: GUID of the image type for which the accepted bit is to be
577  *               cleared
578  * @bank: Bank of which the image's Accept bit is to be set
579  *
580  * Set the accepted bit for the image specified by the img_guid parameter. This
581  * indicates acceptance of image for subsequent boots by some governing component
582  * like OS(or firmware).
583  *
584  * Return: 0 if OK, -ve on error
585  *
586  */
fwu_accept_image(efi_guid_t * img_type_id,u32 bank)587 int fwu_accept_image(efi_guid_t *img_type_id, u32 bank)
588 {
589 	return fwu_clrset_image_accept(img_type_id, bank,
590 				       IMAGE_ACCEPT_SET);
591 }
592 
593 /**
594  * fwu_clear_accept_image() - Clear the Acceptance bit for the image
595  * @img_type_id: GUID of the image type for which the accepted bit is to be
596  *               cleared
597  * @bank: Bank of which the image's Accept bit is to be cleared
598  *
599  * Clear the accepted bit for the image type specified by the img_type_id parameter.
600  * This function is called after the image has been updated. The accepted bit is
601  * cleared to be set subsequently after passing the image acceptance criteria, by
602  * either the OS(or firmware)
603  *
604  * Return: 0 if OK, -ve on error
605  *
606  */
fwu_clear_accept_image(efi_guid_t * img_type_id,u32 bank)607 int fwu_clear_accept_image(efi_guid_t *img_type_id, u32 bank)
608 {
609 	return fwu_clrset_image_accept(img_type_id, bank,
610 				       IMAGE_ACCEPT_CLEAR);
611 }
612 
613 /**
614  * fwu_plat_get_update_index() - Get the value of the update bank
615  * @update_idx: Bank number to which images are to be updated
616  *
617  * Get the value of the bank(partition) to which the update needs to be
618  * made.
619  *
620  * Note: This is a weak function and platforms can override this with
621  * their own implementation for selection of the update bank.
622  *
623  * Return: 0 if OK, -ve on error
624  *
625  */
fwu_plat_get_update_index(uint * update_idx)626 __weak int fwu_plat_get_update_index(uint *update_idx)
627 {
628 	int ret;
629 	u32 active_idx;
630 
631 	ret = fwu_get_active_index(&active_idx);
632 	if (ret < 0)
633 		return -1;
634 
635 	*update_idx = (active_idx + 1) % CONFIG_FWU_NUM_BANKS;
636 
637 	return ret;
638 }
639 
640 /**
641  * fwu_plat_get_bootidx() - Get the value of the boot index
642  * @boot_idx: Boot index value
643  *
644  * Get the value of the bank(partition) from which the platform
645  * has booted. This value is passed to U-Boot from the earlier
646  * stage bootloader which loads and boots all the relevant
647  * firmware images
648  */
fwu_plat_get_bootidx(uint * boot_idx)649 __weak void fwu_plat_get_bootidx(uint *boot_idx)
650 {
651 	int ret;
652 
653 	ret = fwu_get_active_index(boot_idx);
654 	if (ret < 0)
655 		*boot_idx = 0; /* Dummy value */
656 }
657 
658 /**
659  * fwu_update_checks_pass() - Check if FWU update can be done
660  *
661  * Check if the FWU update can be executed. The updates are
662  * allowed only when the platform is not in Trial State and
663  * the boot time checks have passed
664  *
665  * Return: 1 if OK, 0 if checks do not pass
666  *
667  */
fwu_update_checks_pass(void)668 u8 fwu_update_checks_pass(void)
669 {
670 	return !in_trial && boottime_check;
671 }
672 
673 /**
674  * fwu_empty_capsule_checks_pass() - Check if empty capsule can be processed
675  *
676  * Check if the empty capsule can be processed to either accept or revert
677  * an earlier executed update. The empty capsules need to be processed
678  * only when the platform is in Trial State and the boot time checks have
679  * passed
680  *
681  * Return: 1 if OK, 0 if not to be allowed
682  *
683  */
fwu_empty_capsule_checks_pass(void)684 u8 fwu_empty_capsule_checks_pass(void)
685 {
686 	return in_trial && boottime_check;
687 }
688 
689 /**
690  * fwu_trial_state_ctr_start() - Start the Trial State counter
691  *
692  * Start the counter to identify the platform booting in the
693  * Trial State. The counter is implemented as an EFI variable.
694  *
695  * Return: 0 if OK, -ve on error
696  *
697  */
fwu_trial_state_ctr_start(void)698 int fwu_trial_state_ctr_start(void)
699 {
700 	int ret;
701 	u16 trial_state_ctr;
702 
703 	trial_state_ctr = 0;
704 	ret = trial_counter_update(&trial_state_ctr);
705 	if (ret)
706 		log_err("Unable to initialise TrialStateCtr\n");
707 
708 	return ret;
709 }
710 
fwu_boottime_checks(void)711 static int fwu_boottime_checks(void)
712 {
713 	int ret;
714 	u32 boot_idx, active_idx;
715 
716 	ret = uclass_first_device_err(UCLASS_FWU_MDATA, &g_dev);
717 	if (ret) {
718 		log_debug("Cannot find fwu device\n");
719 		return ret;
720 	}
721 
722 	/* Don't have boot time checks on sandbox */
723 	if (IS_ENABLED(CONFIG_SANDBOX)) {
724 		boottime_check = 1;
725 		return 0;
726 	}
727 
728 	ret = fwu_init();
729 	if (ret) {
730 		log_debug("fwu_init() failed\n");
731 		return ret;
732 	}
733 
734 	/*
735 	 * Get the Boot Index, i.e. the bank from
736 	 * which the platform has booted. This value
737 	 * gets passed from the ealier stage bootloader
738 	 * which booted u-boot, e.g. tf-a. If the
739 	 * boot index is not the same as the
740 	 * active_index read from the FWU metadata,
741 	 * update the active_index.
742 	 */
743 	fwu_plat_get_bootidx(&boot_idx);
744 	if (boot_idx >= CONFIG_FWU_NUM_BANKS) {
745 		log_err("Received incorrect value of boot_index\n");
746 		return 0;
747 	}
748 
749 	ret = fwu_get_active_index(&active_idx);
750 	if (ret) {
751 		log_err("Unable to read active_index\n");
752 		return 0;
753 	}
754 
755 	if (boot_idx != active_idx) {
756 		log_info("Boot idx %u is not matching active idx %u, changing active_idx\n",
757 			 boot_idx, active_idx);
758 		ret = fwu_set_active_index(boot_idx);
759 		if (!ret)
760 			boottime_check = 1;
761 	}
762 
763 	if (efi_init_obj_list() != EFI_SUCCESS)
764 		return 0;
765 
766 	in_trial = in_trial_state();
767 
768 	ret = in_trial ? fwu_trial_count_update() : trial_counter_update(NULL);
769 
770 	if (!ret)
771 		boottime_check = 1;
772 
773 	return 0;
774 }
775 EVENT_SPY_SIMPLE(EVT_MAIN_LOOP, fwu_boottime_checks);
776