Commit ed915f7d455a34ede75d9962919181b8b8ba57ec
1 parent
648a4c5376
Exists in
smarc_8mq-imx_v2020.04_5.4.24_2.1.0
and in
1 other branch
MA-14916-4 support dual bootloader for imx8m/imx8q
This commit enables dual bootloader feature for imx8m/imx8q, but as commit 'a2018ab' already brings in some dual bootloader codes when enabling fastboot support, so this commit won't be a complete and standalone patch to introduce the dual bootloader feature. This commit will do the following: 1. clean up dual bootloader flow and add missing implementation. 2. Merge the dual bootloader entry for fit and container to one function 'mmc_load_image_raw_sector_dual_uboot'. Change-Id: Ic9410a48092cc05de599dd897fc912177e2a1fe1 Signed-off-by: Ji Luo <ji.luo@nxp.com>
Showing 8 changed files with 90 additions and 158 deletions Side-by-side Diff
arch/arm/mach-imx/imx8/parse-container.c
... | ... | @@ -192,6 +192,12 @@ |
192 | 192 | } |
193 | 193 | } |
194 | 194 | |
195 | +#if defined(CONFIG_SPL_BUILD) && \ | |
196 | + defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_IMX_TRUSTY_OS) | |
197 | + /* Everything checks out, get the sw_version now. */ | |
198 | + spl_image->rbindex = (uint64_t)container->sw_version; | |
199 | +#endif | |
200 | + | |
195 | 201 | end_auth: |
196 | 202 | #ifdef CONFIG_AHAB_BOOT |
197 | 203 | if (sc_seco_authenticate(-1, SC_SECO_REL_CONTAINER, 0)) |
common/spl/spl_fit.c
... | ... | @@ -63,6 +63,10 @@ |
63 | 63 | return -ENOENT; |
64 | 64 | } |
65 | 65 | |
66 | +#ifdef CONFIG_DUAL_BOOTLOADER | |
67 | +extern int spl_fit_get_rbindex(const void *fit, int images); | |
68 | +#endif | |
69 | + | |
66 | 70 | /** |
67 | 71 | * spl_fit_get_image_name(): By using the matching configuration subnode, |
68 | 72 | * retrieve the name of an image, specified by a property name and an index |
... | ... | @@ -571,6 +575,16 @@ |
571 | 575 | debug("%s: Cannot find /images node: %d\n", __func__, images); |
572 | 576 | return -1; |
573 | 577 | } |
578 | + | |
579 | +#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_IMX_TRUSTY_OS) | |
580 | + int rbindex; | |
581 | + rbindex = spl_fit_get_rbindex(fit, images); | |
582 | + if (rbindex < 0) { | |
583 | + printf("Error! Can't get rollback index!\n"); | |
584 | + return -1; | |
585 | + } else | |
586 | + spl_image->rbindex = rbindex; | |
587 | +#endif | |
574 | 588 | |
575 | 589 | #ifdef CONFIG_SPL_FPGA_SUPPORT |
576 | 590 | node = spl_fit_get_image_node(fit, images, "fpga", 0); |
common/spl/spl_mmc.c
... | ... | @@ -41,7 +41,7 @@ |
41 | 41 | return 0; |
42 | 42 | } |
43 | 43 | |
44 | -static ulong h_spl_load_read(struct spl_load_info *load, ulong sector, | |
44 | +ulong h_spl_load_read(struct spl_load_info *load, ulong sector, | |
45 | 45 | ulong count, void *buf) |
46 | 46 | { |
47 | 47 | struct mmc *mmc = load->dev; |
... | ... | @@ -62,6 +62,8 @@ |
62 | 62 | #if defined(CONFIG_IMX_TRUSTY_OS) |
63 | 63 | /* Pre-declaration of check_rpmb_blob. */ |
64 | 64 | int check_rpmb_blob(struct mmc *mmc); |
65 | +int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image, | |
66 | + struct mmc *mmc); | |
65 | 67 | #endif |
66 | 68 | |
67 | 69 | static __maybe_unused |
68 | 70 | |
... | ... | @@ -116,21 +118,10 @@ |
116 | 118 | return -1; |
117 | 119 | } |
118 | 120 | |
119 | - /* Images loaded, now check the rpmb keyblob for Trusty OS. | |
120 | - * Skip this step when the dual bootloader feature is enabled | |
121 | - * since the blob should be checked earlier. | |
122 | - */ | |
123 | -#if defined(CONFIG_IMX_TRUSTY_OS) | |
124 | - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { | |
125 | -#if !defined(CONFIG_DUAL_BOOTLOADER) | |
121 | + /* Images loaded, now check the rpmb keyblob for Trusty OS. */ | |
122 | +#if defined(CONFIG_IMX_TRUSTY_OS) && !defined(CONFIG_AVB_ATX) | |
126 | 123 | ret = check_rpmb_blob(mmc); |
127 | 124 | #endif |
128 | - } else { | |
129 | -#if !defined(CONFIG_AVB_ATX) | |
130 | - ret = check_rpmb_blob(mmc); | |
131 | -#endif | |
132 | - } | |
133 | -#endif | |
134 | 125 | |
135 | 126 | return ret; |
136 | 127 | } |
137 | 128 | |
... | ... | @@ -383,11 +374,18 @@ |
383 | 374 | * 1 and 2 match up to boot0 / boot1 and 7 is user data |
384 | 375 | * which is the first physical partition (0). |
385 | 376 | */ |
377 | +#ifdef CONFIG_DUAL_BOOTLOADER | |
378 | + /* Bootloader is stored in eMMC user partition for | |
379 | + * dual bootloader. | |
380 | + */ | |
381 | + part = 0; | |
382 | +#else | |
386 | 383 | part = (mmc->part_config >> 3) & PART_ACCESS_MASK; |
387 | 384 | |
388 | 385 | if (part == 7) |
389 | 386 | part = 0; |
390 | 387 | #endif |
388 | +#endif | |
391 | 389 | |
392 | 390 | if (CONFIG_IS_ENABLED(MMC_TINY)) |
393 | 391 | err = mmc_switch_part(mmc, part); |
394 | 392 | |
... | ... | @@ -410,7 +408,9 @@ |
410 | 408 | return err; |
411 | 409 | } |
412 | 410 | |
411 | +#ifndef CONFIG_DUAL_BOOTLOADER | |
413 | 412 | raw_sect = spl_mmc_get_uboot_raw_sector(mmc, raw_sect); |
413 | +#endif | |
414 | 414 | |
415 | 415 | #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION |
416 | 416 | err = mmc_load_image_raw_partition(spl_image, mmc, raw_part, |
417 | 417 | |
... | ... | @@ -419,8 +419,12 @@ |
419 | 419 | return err; |
420 | 420 | #endif |
421 | 421 | #ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR |
422 | +#ifdef CONFIG_DUAL_BOOTLOADER | |
423 | + err = mmc_load_image_raw_sector_dual_uboot(spl_image, mmc); | |
424 | +#else | |
422 | 425 | err = mmc_load_image_raw_sector(spl_image, mmc, |
423 | 426 | raw_sect + spl_mmc_raw_uboot_offset(part)); |
427 | +#endif | |
424 | 428 | if (!err) |
425 | 429 | return err; |
426 | 430 | #endif |
disk/part_efi.c
... | ... | @@ -266,8 +266,10 @@ |
266 | 266 | printf("\tguid:\t%s\n", uuid); |
267 | 267 | } |
268 | 268 | |
269 | +#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD) | |
269 | 270 | /* Remember to free pte */ |
270 | 271 | free(gpt_pte); |
272 | +#endif | |
271 | 273 | return; |
272 | 274 | } |
273 | 275 | |
274 | 276 | |
... | ... | @@ -291,7 +293,9 @@ |
291 | 293 | !is_pte_valid(&gpt_pte[part - 1])) { |
292 | 294 | debug("%s: *** ERROR: Invalid partition number %d ***\n", |
293 | 295 | __func__, part); |
296 | +#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD) | |
294 | 297 | free(gpt_pte); |
298 | +#endif | |
295 | 299 | return -1; |
296 | 300 | } |
297 | 301 | |
298 | 302 | |
... | ... | @@ -318,8 +322,14 @@ |
318 | 322 | debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__, |
319 | 323 | info->start, info->size, info->name); |
320 | 324 | |
321 | - /* Remember to free pte */ | |
325 | +#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD) | |
326 | + /* Heap memory is very limited in SPL, if the dual bootloader is | |
327 | + * enabled, just load pte to dram instead of oc-ram. In such case, | |
328 | + * this part of memory shouldn't be freed. But in common routine, | |
329 | + * don't forget to free the memory after use. | |
330 | + */ | |
322 | 331 | free(gpt_pte); |
332 | +#endif | |
323 | 333 | return 0; |
324 | 334 | } |
325 | 335 | |
326 | 336 | |
327 | 337 | |
... | ... | @@ -1106,10 +1116,19 @@ |
1106 | 1116 | (u32) le32_to_cpu(pgpt_head->sizeof_partition_entry), |
1107 | 1117 | (ulong)count); |
1108 | 1118 | |
1109 | - /* Allocate memory for PTE, remember to FREE */ | |
1119 | + /* Allocate memory for PTE. | |
1120 | + * Heap memory is very limited in SPL, if the dual bootloader is | |
1121 | + * enabled, just load pte to dram instead of oc-ram. In such case, | |
1122 | + * this part of memory shouldn't be freed. But in common routine, | |
1123 | + * don't forget to free the memory after use. | |
1124 | + */ | |
1110 | 1125 | if (count != 0) { |
1126 | +#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD) | |
1127 | + pte = (gpt_entry *)CONFIG_SYS_SPL_PTE_RAM_BASE; | |
1128 | +#else | |
1111 | 1129 | pte = memalign(ARCH_DMA_MINALIGN, |
1112 | 1130 | PAD_TO_BLOCKSIZE(count, dev_desc)); |
1131 | +#endif | |
1113 | 1132 | } |
1114 | 1133 | |
1115 | 1134 | if (count == 0 || pte == NULL) { |
1116 | 1135 | |
... | ... | @@ -1123,7 +1142,9 @@ |
1123 | 1142 | blk_cnt = BLOCK_CNT(count, dev_desc); |
1124 | 1143 | if (blk_dread(dev_desc, blk, (lbaint_t)blk_cnt, pte) != blk_cnt) { |
1125 | 1144 | printf("*** ERROR: Can't read GPT Entries ***\n"); |
1145 | +#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD) | |
1126 | 1146 | free(pte); |
1147 | +#endif | |
1127 | 1148 | return NULL; |
1128 | 1149 | } |
1129 | 1150 | return pte; |
include/part.h
... | ... | @@ -270,7 +270,8 @@ |
270 | 270 | #ifdef CONFIG_SPL_BUILD |
271 | 271 | # define part_print_ptr(x) NULL |
272 | 272 | # if defined(CONFIG_SPL_FS_EXT4) || defined(CONFIG_SPL_FS_FAT) || \ |
273 | - defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) | |
273 | + defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) || \ | |
274 | + defined(CONFIG_DUAL_BOOTLOADER) | |
274 | 275 | # define part_get_info_ptr(x) x |
275 | 276 | # else |
276 | 277 | # define part_get_info_ptr(x) NULL |
include/spl.h
lib/avb/fsl/fsl_avb_ab_flow.c
... | ... | @@ -214,7 +214,7 @@ |
214 | 214 | } |
215 | 215 | } |
216 | 216 | |
217 | -#ifndef CONFIG_XEN | |
217 | +#if !defined(CONFIG_XEN) && defined(CONFIG_IMX_TRUSTY_OS) | |
218 | 218 | static int spl_verify_rbidx(struct mmc *mmc, AvbABSlotData *slot, |
219 | 219 | struct spl_image_info *spl_image) |
220 | 220 | { |
221 | 221 | |
222 | 222 | |
223 | 223 | |
224 | 224 | |
... | ... | @@ -274,19 +274,21 @@ |
274 | 274 | } |
275 | 275 | |
276 | 276 | } |
277 | -#endif /* CONFIG_XEN */ | |
277 | +#endif /* !CONFIG_XEN && CONFIG_IMX_TRUSTY_OS */ | |
278 | 278 | |
279 | -#ifdef CONFIG_PARSE_CONTAINER | |
280 | -int mmc_load_image_parse_container_dual_uboot( | |
281 | - struct spl_image_info *spl_image, struct mmc *mmc) | |
279 | +int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image, | |
280 | + struct mmc *mmc) | |
282 | 281 | { |
282 | + unsigned long count; | |
283 | 283 | disk_partition_t info; |
284 | 284 | int ret = 0, n = 0; |
285 | 285 | char partition_name[PARTITION_NAME_LEN]; |
286 | 286 | struct blk_desc *dev_desc; |
287 | + struct image_header *header; | |
288 | + struct spl_load_info load; | |
287 | 289 | AvbABData ab_data, ab_data_orig; |
288 | 290 | size_t slot_index_to_boot, target_slot; |
289 | -#ifndef CONFIG_XEN | |
291 | +#if !defined(CONFIG_XEN) && defined(CONFIG_IMX_TRUSTY_OS) | |
290 | 292 | struct keyslot_package kp; |
291 | 293 | #endif |
292 | 294 | |
... | ... | @@ -302,8 +304,7 @@ |
302 | 304 | return -1; |
303 | 305 | } |
304 | 306 | |
305 | -#ifndef CONFIG_XEN | |
306 | - /* Read RPMB keyslot package, xen won't check this. */ | |
307 | +#if !defined(CONFIG_XEN) && defined(CONFIG_IMX_TRUSTY_OS) | |
307 | 308 | read_keyslot_package(&kp); |
308 | 309 | if (strcmp(kp.magic, KEYPACK_MAGIC)) { |
309 | 310 | if (rpmbkey_is_set()) { |
... | ... | @@ -347,126 +348,6 @@ |
347 | 348 | ret = -1; |
348 | 349 | goto end; |
349 | 350 | } else { |
350 | - ret = mmc_load_image_parse_container(spl_image, mmc, info.start); | |
351 | - | |
352 | - /* Don't need to check rollback index for xen. */ | |
353 | -#ifndef CONFIG_XEN | |
354 | - /* Image loaded successfully, go to verify rollback index */ | |
355 | - if (!ret && rpmbkey_is_set()) | |
356 | - ret = spl_verify_rbidx(mmc, &ab_data.slots[target_slot], spl_image); | |
357 | - | |
358 | - /* Copy rpmb keyslot to secure memory. */ | |
359 | - if (!ret) | |
360 | - fill_secure_keyslot_package(&kp); | |
361 | -#endif | |
362 | - } | |
363 | - | |
364 | - /* Set current slot to unbootable if load/verify fail. */ | |
365 | - if (ret != 0) { | |
366 | - printf("Load or verify bootloader%s fail, setting unbootable..\n", | |
367 | - slot_suffixes[target_slot]); | |
368 | - fsl_slot_set_unbootable(&ab_data.slots[target_slot]); | |
369 | - /* Switch to another slot. */ | |
370 | - target_slot = (target_slot == 1 ? 0 : 1); | |
371 | - } else { | |
372 | - slot_index_to_boot = target_slot; | |
373 | - n = 2; | |
374 | - } | |
375 | - } | |
376 | - | |
377 | - if (slot_index_to_boot == 2) { | |
378 | - /* No bootable slots! */ | |
379 | - printf("No bootable slots found.\n"); | |
380 | - ret = -1; | |
381 | - goto end; | |
382 | - } else if (!ab_data.slots[slot_index_to_boot].successful_boot && | |
383 | - (ab_data.slots[slot_index_to_boot].tries_remaining > 0)) { | |
384 | - /* Set the bootloader_verified flag if current slot only has one chance. */ | |
385 | - if (ab_data.slots[slot_index_to_boot].tries_remaining == 1) | |
386 | - ab_data.slots[slot_index_to_boot].bootloader_verified = 1; | |
387 | - ab_data.slots[slot_index_to_boot].tries_remaining -= 1; | |
388 | - } | |
389 | - printf("Booting from bootloader%s...\n", slot_suffixes[slot_index_to_boot]); | |
390 | - | |
391 | -end: | |
392 | - /* Save metadata if changed. */ | |
393 | - if (fsl_save_metadata_if_changed_dual_uboot(dev_desc, &ab_data, &ab_data_orig)) { | |
394 | - ret = -1; | |
395 | - } | |
396 | - | |
397 | - if (ret) | |
398 | - return -1; | |
399 | - else | |
400 | - return 0; | |
401 | -} | |
402 | -#else /* CONFIG_PARSE_CONTAINER */ | |
403 | -int mmc_load_image_raw_sector_dual_uboot( | |
404 | - struct spl_image_info *spl_image, struct mmc *mmc) | |
405 | -{ | |
406 | - unsigned long count; | |
407 | - disk_partition_t info; | |
408 | - int ret = 0, n = 0; | |
409 | - char partition_name[PARTITION_NAME_LEN]; | |
410 | - struct blk_desc *dev_desc; | |
411 | - struct image_header *header; | |
412 | - AvbABData ab_data, ab_data_orig; | |
413 | - size_t slot_index_to_boot, target_slot; | |
414 | - struct keyslot_package kp; | |
415 | - | |
416 | - /* Check if gpt is valid */ | |
417 | - dev_desc = mmc_get_blk_desc(mmc); | |
418 | - if (dev_desc) { | |
419 | - if (part_get_info(dev_desc, 1, &info)) { | |
420 | - printf("GPT is invalid, please flash correct GPT!\n"); | |
421 | - return -1; | |
422 | - } | |
423 | - } else { | |
424 | - printf("Get block desc fail!\n"); | |
425 | - return -1; | |
426 | - } | |
427 | - | |
428 | - /* Init RPMB keyslot package if not initialized before. */ | |
429 | - read_keyslot_package(&kp); | |
430 | - if (strcmp(kp.magic, KEYPACK_MAGIC)) { | |
431 | - printf("keyslot package magic error. Will generate new one\n"); | |
432 | - if (gen_rpmb_key(&kp)) { | |
433 | - printf("Generate keyslot package fail!\n"); | |
434 | - return -1; | |
435 | - } | |
436 | - } | |
437 | - /* Set power-on write protection to boot1 partition. */ | |
438 | - if (mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, BOOT1_PWR_WP)) { | |
439 | - printf("Unable to set power-on write protection to boot1!\n"); | |
440 | - return -1; | |
441 | - } | |
442 | - | |
443 | - /* Load AB metadata from misc partition */ | |
444 | - if (fsl_load_metadata_dual_uboot(dev_desc, &ab_data, | |
445 | - &ab_data_orig)) { | |
446 | - return -1; | |
447 | - } | |
448 | - | |
449 | - slot_index_to_boot = 2; // Means not 0 or 1 | |
450 | - target_slot = | |
451 | - (ab_data.slots[1].priority > ab_data.slots[0].priority) ? 1 : 0; | |
452 | - | |
453 | - for (n = 0; n < 2; n++) { | |
454 | - if (!fsl_slot_is_bootable(&ab_data.slots[target_slot])) { | |
455 | - target_slot = (target_slot == 1 ? 0 : 1); | |
456 | - continue; | |
457 | - } | |
458 | - /* Choose slot to load. */ | |
459 | - snprintf(partition_name, PARTITION_NAME_LEN, | |
460 | - PARTITION_BOOTLOADER"%s", | |
461 | - slot_suffixes[target_slot]); | |
462 | - | |
463 | - /* Read part info from gpt */ | |
464 | - if (part_get_info_by_name(dev_desc, partition_name, &info) == -1) { | |
465 | - printf("Can't get partition info of partition bootloader%s\n", | |
466 | - slot_suffixes[target_slot]); | |
467 | - ret = -1; | |
468 | - goto end; | |
469 | - } else { | |
470 | 351 | header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - |
471 | 352 | sizeof(struct image_header)); |
472 | 353 | |
473 | 354 | |
474 | 355 | |
475 | 356 | |
476 | 357 | |
477 | 358 | |
... | ... | @@ -477,30 +358,32 @@ |
477 | 358 | goto end; |
478 | 359 | } |
479 | 360 | |
480 | - /* Load fit and check HAB */ | |
361 | + /* Load fit/container and check HAB */ | |
362 | + load.dev = mmc; | |
363 | + load.priv = NULL; | |
364 | + load.filename = NULL; | |
365 | + load.bl_len = mmc->read_bl_len; | |
366 | + load.read = h_spl_load_read; | |
481 | 367 | if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && |
482 | 368 | image_get_magic(header) == FDT_MAGIC) { |
483 | - struct spl_load_info load; | |
484 | - | |
485 | - debug("Found FIT\n"); | |
486 | - load.dev = mmc; | |
487 | - load.priv = NULL; | |
488 | - load.filename = NULL; | |
489 | - load.bl_len = mmc->read_bl_len; | |
490 | - load.read = h_spl_load_read; | |
369 | + /* Fit */ | |
491 | 370 | ret = spl_load_simple_fit(spl_image, &load, |
492 | 371 | info.start, header); |
493 | - } else { | |
372 | + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { | |
373 | + /* container */ | |
374 | + ret = spl_load_imx_container(spl_image, &load, info.start); | |
375 | + } else | |
494 | 376 | ret = -1; |
495 | - } | |
496 | 377 | |
497 | - /* Fit image loaded successfully, go to verify rollback index */ | |
378 | +#if !defined(CONFIG_XEN) && defined(CONFIG_IMX_TRUSTY_OS) | |
379 | + /* Image loaded successfully, go to verify rollback index */ | |
498 | 380 | if (!ret) |
499 | 381 | ret = spl_verify_rbidx(mmc, &ab_data.slots[target_slot], spl_image); |
500 | 382 | |
501 | 383 | /* Copy rpmb keyslot to secure memory. */ |
502 | 384 | if (!ret) |
503 | 385 | fill_secure_keyslot_package(&kp); |
386 | +#endif | |
504 | 387 | } |
505 | 388 | |
506 | 389 | /* Set current slot to unbootable if load/verify fail. */ |
... | ... | @@ -572,7 +455,6 @@ |
572 | 455 | |
573 | 456 | return index; |
574 | 457 | } |
575 | -#endif /* CONFIG_PARSE_CONTAINER */ | |
576 | 458 | |
577 | 459 | /* For normal build */ |
578 | 460 | #elif !defined(CONFIG_SPL_BUILD) |
scripts/config_whitelist.txt