[iot] Support dual bootloader in SPL
Move the A/B slot check to SPL, the A/B slot switch workflow is just like what we have in libavb_ab. Test: A/B select works fine on imx8m. Change-Id: Ie3d827a9be0298b491bf2bc8d48833597fd70e90 Signed-off-by: Luo Ji <ji.luo@nxp.com>
This commit is contained in:
parent
4cfd7437ac
commit
dbcf1e3cc0
|
|
@ -4,6 +4,8 @@
|
|||
*
|
||||
* Aneesh V <aneesh@ti.com>
|
||||
*
|
||||
* Copyright 2018 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
|
|
@ -18,7 +20,7 @@
|
|||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
static int mmc_load_legacy(struct spl_image_info *spl_image, struct mmc *mmc,
|
||||
int mmc_load_legacy(struct spl_image_info *spl_image, struct mmc *mmc,
|
||||
ulong sector, struct image_header *header)
|
||||
{
|
||||
u32 image_size_sectors;
|
||||
|
|
@ -44,7 +46,7 @@ static int mmc_load_legacy(struct spl_image_info *spl_image, struct mmc *mmc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
|
||||
ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
|
||||
ulong count, void *buf)
|
||||
{
|
||||
struct mmc *mmc = load->dev;
|
||||
|
|
@ -52,9 +54,15 @@ static ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
|
|||
return blk_dread(mmc_get_blk_desc(mmc), sector, count, buf);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DUAL_BOOTLOADER
|
||||
/* Pre-declaration of mmc_load_image_raw_sector_dual_uboot().
|
||||
*/
|
||||
extern int mmc_load_image_raw_sector_dual_uboot(struct spl_image_info *spl_image,
|
||||
struct mmc *mmc);
|
||||
#else
|
||||
static __maybe_unused
|
||||
int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
|
||||
struct mmc *mmc, unsigned long sector)
|
||||
struct mmc *mmc, unsigned long sector)
|
||||
{
|
||||
struct image_header *header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
|
||||
sizeof(struct image_header));
|
||||
|
|
@ -98,6 +106,8 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DUAL_BOOTLOADER */
|
||||
|
||||
static int spl_mmc_get_device_index(u32 boot_device)
|
||||
{
|
||||
switch (boot_device) {
|
||||
|
|
@ -329,10 +339,15 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
|
|||
* 1 and 2 match up to boot0 / boot1 and 7 is user data
|
||||
* which is the first physical partition (0).
|
||||
*/
|
||||
#ifdef CONFIG_DUAL_BOOTLOADER
|
||||
/* Bootloader is stored in eMMC user partition for dual bootloader */
|
||||
part = 0;
|
||||
#else
|
||||
part = (mmc->part_config >> 3) & PART_ACCESS_MASK;
|
||||
|
||||
if (part == 7)
|
||||
part = 0;
|
||||
#endif
|
||||
|
||||
if (CONFIG_IS_ENABLED(MMC_TINY))
|
||||
err = mmc_switch_part(mmc, part);
|
||||
|
|
@ -361,8 +376,13 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
|
|||
return err;
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
|
||||
#ifdef CONFIG_DUAL_BOOTLOADER
|
||||
err = mmc_load_image_raw_sector_dual_uboot(spl_image,
|
||||
mmc);
|
||||
#else
|
||||
err = mmc_load_image_raw_sector(spl_image, mmc,
|
||||
spl_mmc_get_uboot_raw_sector(mmc));
|
||||
#endif
|
||||
if (!err)
|
||||
return err;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -68,3 +68,4 @@ CONFIG_USB_XHCI_IMX8M=y
|
|||
CONFIG_USB_XHCI_DWC3=y
|
||||
CONFIG_USB_DWC3=y
|
||||
CONFIG_USB_DWC3_GADGET=y
|
||||
CONFIG_SPL_LIBDISK_SUPPORT=y
|
||||
|
|
|
|||
|
|
@ -42,6 +42,9 @@ CONFIG_DM_THERMAL=y
|
|||
CONFIG_FIT=y
|
||||
CONFIG_SPL_FIT=y
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_SPL_MMC_SUPPORT=y
|
||||
CONFIG_SPL_MMC_WRITE=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_DM_USB=y
|
||||
CONFIG_ANDROID_BOOT_IMAGE=y
|
||||
CONFIG_SPL_LIBDISK_SUPPORT=y
|
||||
|
|
|
|||
|
|
@ -280,8 +280,10 @@ void part_print_efi(struct blk_desc *dev_desc)
|
|||
printf("\tguid:\t%s\n", uuid);
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
|
||||
/* Remember to free pte */
|
||||
free(gpt_pte);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +318,9 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
|
|||
!is_pte_valid(&gpt_pte[part - 1])) {
|
||||
debug("%s: *** ERROR: Invalid partition number %d ***\n",
|
||||
__func__, part);
|
||||
#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
|
||||
free(gpt_pte);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -343,8 +347,14 @@ int part_get_info_efi(struct blk_desc *dev_desc, int part,
|
|||
debug("%s: start 0x" LBAF ", size 0x" LBAF ", name %s\n", __func__,
|
||||
info->start, info->size, info->name);
|
||||
|
||||
/* Remember to free pte */
|
||||
#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
|
||||
/* Heap memory is very limited in SPL, if the dual bootloader is
|
||||
* enabled, just load pte to dram instead of oc-ram. In such case,
|
||||
* this part of memory shouldn't be freed. But in common routine,
|
||||
* don't forget to free the memory after use.
|
||||
*/
|
||||
free(gpt_pte);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1039,10 +1049,17 @@ static int is_gpt_valid(struct blk_desc *dev_desc, u64 lba,
|
|||
}
|
||||
|
||||
if (validate_gpt_entries(pgpt_head, *pgpt_pte)) {
|
||||
|
||||
#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
|
||||
/* Heap memory is very limited in SPL, if the dual bootloader is
|
||||
* enabled, just load pte to dram instead of oc-ram. In such case,
|
||||
* this part of memory shouldn't be freed. But in common routine,
|
||||
* don't forget to free the memory after use.
|
||||
*/
|
||||
free(*pgpt_pte);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're done, all's well */
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1076,10 +1093,19 @@ static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
|
|||
(u32) le32_to_cpu(pgpt_head->sizeof_partition_entry),
|
||||
(ulong)count);
|
||||
|
||||
/* Allocate memory for PTE, remember to FREE */
|
||||
/* Allocate memory for PTE.
|
||||
* Heap memory is very limited in SPL, if the dual bootloader is
|
||||
* enabled, just load pte to dram instead of oc-ram. In such case,
|
||||
* this part of memory shouldn't be freed. But in common routine,
|
||||
* don't forget to free the memory after use.
|
||||
*/
|
||||
if (count != 0) {
|
||||
#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
|
||||
pte = (gpt_entry *)CONFIG_SYS_SPL_PTE_RAM_BASE;
|
||||
#else
|
||||
pte = memalign(ARCH_DMA_MINALIGN,
|
||||
PAD_TO_BLOCKSIZE(count, dev_desc));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (count == 0 || pte == NULL) {
|
||||
|
|
@ -1087,13 +1113,14 @@ static gpt_entry *alloc_read_gpt_entries(struct blk_desc *dev_desc,
|
|||
__func__, (ulong)count);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read GPT Entries from device */
|
||||
blk = le64_to_cpu(pgpt_head->partition_entry_lba);
|
||||
blk_cnt = BLOCK_CNT(count, dev_desc);
|
||||
if (blk_dread(dev_desc, blk, (lbaint_t)blk_cnt, pte) != blk_cnt) {
|
||||
printf("*** ERROR: Can't read GPT Entries ***\n");
|
||||
#if !defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
|
||||
free(pte);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
return pte;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#define CONFIG_SPL_BSS_MAX_SIZE 0x2000 /* 8 KB */
|
||||
#define CONFIG_SYS_SPL_MALLOC_START 0x00182000
|
||||
#define CONFIG_SYS_SPL_MALLOC_SIZE 0x6000 /* 24 KB */
|
||||
#define CONFIG_SYS_SPL_PTE_RAM_BASE 0x41580000
|
||||
#define CONFIG_SYS_ICACHE_OFF
|
||||
#define CONFIG_SYS_DCACHE_OFF
|
||||
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@
|
|||
#define CONFIG_SPL_LIBGENERIC_SUPPORT
|
||||
#define CONFIG_SPL_SERIAL_SUPPORT
|
||||
#define CONFIG_SPL_GPIO_SUPPORT
|
||||
#define CONFIG_SPL_MMC_SUPPORT
|
||||
#define CONFIG_SPL_BSS_START_ADDR 0x00180000
|
||||
#define CONFIG_SPL_BSS_MAX_SIZE 0x2000 /* 8 KB */
|
||||
#define CONFIG_SYS_SPL_MALLOC_START 0x00182000
|
||||
#define CONFIG_SYS_SPL_MALLOC_SIZE 0x2000 /* 8 KB */
|
||||
#define CONFIG_SYS_SPL_PTE_RAM_BASE 0x41580000
|
||||
#define CONFIG_SYS_ICACHE_OFF
|
||||
#define CONFIG_SYS_DCACHE_OFF
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@ AvbIOResult fsl_read_from_partition(AvbOps* ops, const char* partition,
|
|||
/* multi block read version
|
||||
* */
|
||||
AvbIOResult fsl_read_from_partition_multi(AvbOps* ops, const char* partition,
|
||||
int64_t offset, size_t num_bytes,
|
||||
void* buffer, size_t* out_num_read);
|
||||
int64_t offset, size_t num_bytes,
|
||||
void* buffer, size_t* out_num_read);
|
||||
|
||||
/* Writes |num_bytes| from |bffer| at offset |offset| to partition
|
||||
* with name |partition| (NUL-terminated UTF-8 string). If |offset|
|
||||
|
|
@ -87,11 +87,11 @@ AvbIOResult fsl_write_ab_metadata(AvbABOps* ab_ops, const struct AvbABData* data
|
|||
* true if trusted or false if untrusted.
|
||||
*/
|
||||
AvbIOResult fsl_validate_vbmeta_public_key_rpmb(AvbOps* ops,
|
||||
const uint8_t* public_key_data,
|
||||
size_t public_key_length,
|
||||
const uint8_t* public_key_metadata,
|
||||
size_t public_key_metadata_length,
|
||||
bool* out_is_trusted);
|
||||
const uint8_t* public_key_data,
|
||||
size_t public_key_length,
|
||||
const uint8_t* public_key_metadata,
|
||||
size_t public_key_metadata_length,
|
||||
bool* out_is_trusted);
|
||||
|
||||
/* Gets the rollback index corresponding to the slot given by
|
||||
* |rollback_index_slot|. The value is returned in
|
||||
|
|
@ -103,7 +103,7 @@ AvbIOResult fsl_validate_vbmeta_public_key_rpmb(AvbOps* ops,
|
|||
* this number.
|
||||
*/
|
||||
AvbIOResult fsl_read_rollback_index_rpmb(AvbOps* ops, size_t rollback_index_slot,
|
||||
uint64_t* out_rollback_index);
|
||||
uint64_t* out_rollback_index);
|
||||
|
||||
/* Sets the rollback index corresponding to the slot given by
|
||||
* |rollback_index_slot| to |rollback_index|. Returns
|
||||
|
|
@ -115,7 +115,7 @@ AvbIOResult fsl_read_rollback_index_rpmb(AvbOps* ops, size_t rollback_index_slot
|
|||
* this number.
|
||||
*/
|
||||
AvbIOResult fsl_write_rollback_index_rpmb(AvbOps* ops, size_t rollback_index_slot,
|
||||
uint64_t rollback_index);
|
||||
uint64_t rollback_index);
|
||||
|
||||
/* Gets whether the device is unlocked. The value is returned in
|
||||
* |out_is_unlocked| (true if unlocked, false otherwise). Returns
|
||||
|
|
@ -135,9 +135,9 @@ AvbIOResult fsl_read_is_device_unlocked(AvbOps* ops, bool* out_is_unlocked);
|
|||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||
*/
|
||||
AvbIOResult fsl_get_unique_guid_for_partition(AvbOps* ops,
|
||||
const char* partition,
|
||||
char* guid_buf,
|
||||
size_t guid_buf_size);
|
||||
const char* partition,
|
||||
char* guid_buf,
|
||||
size_t guid_buf_size);
|
||||
|
||||
/* Gets the size of a partition with the name in |partition|
|
||||
* (NUL-terminated UTF-8 string). Returns the value in
|
||||
|
|
@ -145,8 +145,8 @@ AvbIOResult fsl_get_unique_guid_for_partition(AvbOps* ops,
|
|||
* Returns AVB_IO_RESULT_OK on success, otherwise an error code.
|
||||
*/
|
||||
AvbIOResult fsl_get_size_of_partition(AvbOps* ops,
|
||||
const char* partition,
|
||||
uint64_t* out_size_num_bytes);
|
||||
const char* partition,
|
||||
uint64_t* out_size_num_bytes);
|
||||
/* check if the fastboot getvar cmd is for query [avb] bootctl's slot var
|
||||
* cmd is the fastboot getvar's cmd in
|
||||
* return true if it is a bootctl related cmd, false if it's not.
|
||||
|
|
@ -193,32 +193,42 @@ AvbIOResult fsl_read_permanent_attributes(
|
|||
* permanently read-only location (e.g. fuses) when a device is LOCKED. On
|
||||
* success, returned AVB_IO_RESULT_OK and populates |hash|.
|
||||
*/
|
||||
AvbIOResult fsl_read_permanent_attributes_hash(
|
||||
AvbAtxOps* atx_ops, uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
|
||||
AvbIOResult fsl_read_permanent_attributes_hash(AvbAtxOps* atx_ops,
|
||||
uint8_t hash[AVB_SHA256_DIGEST_SIZE]);
|
||||
|
||||
/* Provides the key version of a key used during verification. This may be
|
||||
* useful for managing the minimum key version.
|
||||
*/
|
||||
void fsl_set_key_version(AvbAtxOps* atx_ops,
|
||||
size_t rollback_index_location,
|
||||
uint64_t key_version);
|
||||
size_t rollback_index_location,
|
||||
uint64_t key_version);
|
||||
|
||||
/* This is the fast version of avb_ab_flow(), this function will
|
||||
* not check another slot if one slot can pass the verify (or verify
|
||||
* fail is acceptable). */
|
||||
* fail is acceptable).
|
||||
*/
|
||||
AvbABFlowResult avb_ab_flow_fast(AvbABOps* ab_ops,
|
||||
const char* const* requested_partitions,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbSlotVerifyData** out_data);
|
||||
const char* const* requested_partitions,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbSlotVerifyData** out_data);
|
||||
|
||||
/* This is for legacy i.mx6/7 which don't enable A/B but want to
|
||||
* verify boot/recovery with AVB */
|
||||
AvbABFlowResult avb_single_flow(AvbABOps* ab_ops,
|
||||
const char* const* requested_partitions,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbSlotVerifyData** out_data);
|
||||
const char* const* requested_partitions,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbSlotVerifyData** out_data);
|
||||
|
||||
/* Avb verify flow for dual bootloader, only the slot chosen by SPL will
|
||||
* be verified.
|
||||
*/
|
||||
AvbABFlowResult avb_flow_dual_uboot(AvbABOps* ab_ops,
|
||||
const char* const* requested_partitions,
|
||||
AvbSlotVerifyFlags flags,
|
||||
AvbHashtreeErrorMode hashtree_error_mode,
|
||||
AvbSlotVerifyData** out_data);
|
||||
|
||||
/* Program ATX perm_attr into RPMB partition */
|
||||
int avb_atx_fuse_perm_attr(uint8_t *staged_buffer, uint32_t size);
|
||||
|
|
|
|||
|
|
@ -250,7 +250,8 @@ static inline int blk_get_device_part_str(const char *ifname,
|
|||
#ifdef CONFIG_SPL_BUILD
|
||||
# define part_print_ptr(x) NULL
|
||||
# if defined(CONFIG_SPL_EXT_SUPPORT) || defined(CONFIG_SPL_FAT_SUPPORT) || \
|
||||
defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION)
|
||||
defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) || \
|
||||
defined(CONFIG_DUAL_BOOTLOADER)
|
||||
# define part_get_info_ptr(x) x
|
||||
# else
|
||||
# define part_get_info_ptr(x) NULL
|
||||
|
|
|
|||
|
|
@ -122,6 +122,11 @@ config RBTREE
|
|||
config BITREVERSE
|
||||
bool "Bit reverse library from Linux"
|
||||
|
||||
config DUAL_BOOTLOADER
|
||||
bool "Enable dual bootloader support"
|
||||
help
|
||||
Enable A/B bootloader select in SPL.
|
||||
|
||||
source lib/dhry/Kconfig
|
||||
|
||||
menu "Security support"
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ obj-$(CONFIG_CMD_DHRYSTONE) += dhry/
|
|||
obj-$(CONFIG_ARCH_AT91) += at91/
|
||||
obj-$(CONFIG_IMX_TRUSTY_OS) += trusty/ql-tipc/
|
||||
obj-$(CONFIG_AES) += aes.o
|
||||
obj-$(CONFIG_AVB_SUPPORT) += avb/
|
||||
obj-y += charset.o
|
||||
obj-$(CONFIG_USB_TTY) += circbuf.o
|
||||
obj-y += crc7.o
|
||||
|
|
@ -50,6 +49,7 @@ endif
|
|||
obj-$(CONFIG_RSA) += rsa/
|
||||
obj-$(CONFIG_SHA1) += sha1.o
|
||||
obj-$(CONFIG_SHA256) += sha256.o
|
||||
obj-$(CONFIG_AVB_SUPPORT) += avb/
|
||||
|
||||
obj-$(CONFIG_$(SPL_)ZLIB) += zlib/
|
||||
obj-$(CONFIG_$(SPL_)GZIP) += gunzip.o
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ subdir-ccflags-y += -I./lib/avb \
|
|||
-Wno-unused-parameter \
|
||||
-ffunction-sections \
|
||||
-std=gnu99
|
||||
obj-y += libavb/
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-y += libavb_ab/
|
||||
obj-$(CONFIG_AVB_ATX) += libavb_atx/
|
||||
endif
|
||||
obj-y += libavb/
|
||||
obj-y += fsl/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
ccflags-y += -Werror
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-y += fsl_avb.o
|
||||
obj-y += fsl_avbkey.o
|
||||
obj-y += fsl_bootctl.o
|
||||
obj-y += fsl_avb_ab_flow.o
|
||||
obj-y += fsl_avb_sysdeps_uboot.o
|
||||
endif
|
||||
|
||||
obj-y += utils.o
|
||||
obj-y += fsl_avb_ab_flow.o
|
||||
|
|
|
|||
|
|
@ -4,13 +4,19 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <fsl_avb.h>
|
||||
#include <mmc.h>
|
||||
#include <spl.h>
|
||||
#include <part.h>
|
||||
#include <image.h>
|
||||
#include "utils.h"
|
||||
|
||||
#if defined(CONFIG_DUAL_BOOTLOADER) || !defined(CONFIG_SPL_BUILD)
|
||||
static const char* slot_suffixes[2] = {"_a", "_b"};
|
||||
|
||||
/* This is a copy of slot_set_unbootable() form
|
||||
* lib/avb/libavb_ab/avb_ab_flow.c.
|
||||
* external/avb/libavb_ab/avb_ab_flow.c.
|
||||
*/
|
||||
static void fsl_slot_set_unbootable(AvbABSlotData* slot) {
|
||||
void fsl_slot_set_unbootable(AvbABSlotData* slot) {
|
||||
slot->priority = 0;
|
||||
slot->tries_remaining = 0;
|
||||
slot->successful_boot = 0;
|
||||
|
|
@ -18,10 +24,10 @@ static void fsl_slot_set_unbootable(AvbABSlotData* slot) {
|
|||
|
||||
/* Ensure all unbootable and/or illegal states are marked as the
|
||||
* canonical 'unbootable' state, e.g. priority=0, tries_remaining=0,
|
||||
* and successful_boot=0. This is a copy of fsl_slot_normalize from
|
||||
* lib/avb/libavb_ab/avb_ab_flow.c.
|
||||
* and successful_boot=0. This is a copy of slot_normalize from
|
||||
* external/avb/libavb_ab/avb_ab_flow.c.
|
||||
*/
|
||||
static void fsl_slot_normalize(AvbABSlotData* slot) {
|
||||
void fsl_slot_normalize(AvbABSlotData* slot) {
|
||||
if (slot->priority > 0) {
|
||||
if ((slot->tries_remaining == 0) && (!slot->successful_boot)) {
|
||||
/* We've exhausted all tries -> unbootable. */
|
||||
|
|
@ -38,9 +44,279 @@ static void fsl_slot_normalize(AvbABSlotData* slot) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Writes A/B metadata to disk only if it has changed - returns
|
||||
* AVB_IO_RESULT_OK on success, error code otherwise. This is a
|
||||
* copy of save_metadata_if_changed form lib/avb/libavb_ab/avb_ab_flow.c.
|
||||
/* This is a copy of slot_is_bootable() from
|
||||
* externel/avb/libavb_ab/avb_ab_flow.c.
|
||||
*/
|
||||
bool fsl_slot_is_bootable(AvbABSlotData* slot) {
|
||||
return (slot->priority > 0) &&
|
||||
(slot->successful_boot || (slot->tries_remaining > 0));
|
||||
}
|
||||
#endif /* CONFIG_DUAL_BOOTLOADER || !CONFIG_SPL_BUILD */
|
||||
|
||||
#if defined(CONFIG_DUAL_BOOTLOADER) && defined(CONFIG_SPL_BUILD)
|
||||
|
||||
#define FSL_AB_METADATA_MISC_PARTITION_OFFSET 2048
|
||||
#define PARTITION_NAME_LEN 13
|
||||
#define PARTITION_MISC "misc"
|
||||
#define PARTITION_BOOTLOADER "bootloader"
|
||||
|
||||
/* Pre-declaration of h_spl_load_read(), see detail implementation in
|
||||
* common/spl/spl_mmc.c.
|
||||
*/
|
||||
ulong h_spl_load_read(struct spl_load_info *load, ulong sector,
|
||||
ulong count, void *buf);
|
||||
|
||||
void fsl_avb_ab_data_update_crc_and_byteswap(const AvbABData* src,
|
||||
AvbABData* dest) {
|
||||
memcpy(dest, src, sizeof(AvbABData));
|
||||
dest->crc32 = cpu_to_be32(
|
||||
avb_crc32((const uint8_t*)dest,
|
||||
sizeof(AvbABData) - sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
void fsl_avb_ab_data_init(AvbABData* data) {
|
||||
memset(data, '\0', sizeof(AvbABData));
|
||||
memcpy(data->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN);
|
||||
data->version_major = AVB_AB_MAJOR_VERSION;
|
||||
data->version_minor = AVB_AB_MINOR_VERSION;
|
||||
data->slots[0].priority = AVB_AB_MAX_PRIORITY;
|
||||
data->slots[0].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
|
||||
data->slots[0].successful_boot = 0;
|
||||
data->slots[1].priority = AVB_AB_MAX_PRIORITY - 1;
|
||||
data->slots[1].tries_remaining = AVB_AB_MAX_TRIES_REMAINING;
|
||||
data->slots[1].successful_boot = 0;
|
||||
}
|
||||
|
||||
bool fsl_avb_ab_data_verify_and_byteswap(const AvbABData* src,
|
||||
AvbABData* dest) {
|
||||
/* Ensure magic is correct. */
|
||||
if (memcmp(src->magic, AVB_AB_MAGIC, AVB_AB_MAGIC_LEN) != 0) {
|
||||
printf("Magic is incorrect.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(dest, src, sizeof(AvbABData));
|
||||
dest->crc32 = be32_to_cpu(dest->crc32);
|
||||
|
||||
/* Ensure we don't attempt to access any fields if the major version
|
||||
* is not supported.
|
||||
*/
|
||||
if (dest->version_major > AVB_AB_MAJOR_VERSION) {
|
||||
printf("No support for given major version.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fail if CRC32 doesn't match. */
|
||||
if (dest->crc32 !=
|
||||
avb_crc32((const uint8_t*)dest, sizeof(AvbABData) - sizeof(uint32_t))) {
|
||||
printf("CRC32 does not match.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Writes A/B metadata to disk only if it has changed.
|
||||
*/
|
||||
int fsl_save_metadata_if_changed_dual_uboot(struct blk_desc *dev_desc,
|
||||
AvbABData* ab_data,
|
||||
AvbABData* ab_data_orig) {
|
||||
AvbABData serialized;
|
||||
size_t num_bytes;
|
||||
disk_partition_t info;
|
||||
|
||||
/* Save metadata if changed. */
|
||||
if (memcmp(ab_data, ab_data_orig, sizeof(AvbABData)) != 0) {
|
||||
/* Get misc partition info */
|
||||
if (part_get_info_by_name(dev_desc, PARTITION_MISC, &info) == -1) {
|
||||
printf("Can't get partition info of partition: misc\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Writing A/B metadata to disk. */
|
||||
fsl_avb_ab_data_update_crc_and_byteswap(ab_data, &serialized);
|
||||
if (write_to_partition_in_bytes(dev_desc, &info,
|
||||
FSL_AB_METADATA_MISC_PARTITION_OFFSET,
|
||||
sizeof(AvbABData),
|
||||
(void *)&serialized, &num_bytes) ||
|
||||
(num_bytes != sizeof(AvbABData))) {
|
||||
printf("Error--write metadata fail!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load metadate from misc partition.
|
||||
*/
|
||||
int fsl_load_metadata_dual_uboot(struct blk_desc *dev_desc,
|
||||
AvbABData* ab_data,
|
||||
AvbABData* ab_data_orig) {
|
||||
disk_partition_t info;
|
||||
AvbABData serialized;
|
||||
size_t num_bytes;
|
||||
|
||||
if (part_get_info_by_name(dev_desc, PARTITION_MISC, &info) == -1) {
|
||||
printf("Can't get partition info of partition: misc\n");
|
||||
return -1;
|
||||
} else {
|
||||
read_from_partition_in_bytes(
|
||||
dev_desc, &info, FSL_AB_METADATA_MISC_PARTITION_OFFSET,
|
||||
sizeof(AvbABData),
|
||||
(void *)ab_data, &num_bytes );
|
||||
if (num_bytes != sizeof(AvbABData)) {
|
||||
printf("Error--read metadata fail!\n");
|
||||
return -1;
|
||||
} else {
|
||||
if (!fsl_avb_ab_data_verify_and_byteswap(ab_data, &serialized)) {
|
||||
printf("Error validating A/B metadata from disk.\n");
|
||||
printf("Resetting and writing new A/B metadata to disk.\n");
|
||||
fsl_avb_ab_data_init(ab_data);
|
||||
fsl_avb_ab_data_update_crc_and_byteswap(ab_data, &serialized);
|
||||
num_bytes = 0;
|
||||
if (write_to_partition_in_bytes(
|
||||
dev_desc, &info,
|
||||
FSL_AB_METADATA_MISC_PARTITION_OFFSET,
|
||||
sizeof(AvbABData),
|
||||
(void *)&serialized, &num_bytes) ||
|
||||
(num_bytes != sizeof(AvbABData))) {
|
||||
printf("Error--write metadata fail!\n");
|
||||
return -1;
|
||||
} else
|
||||
return 0;
|
||||
} else {
|
||||
memcpy(ab_data_orig, ab_data, sizeof(AvbABData));
|
||||
/* Ensure data is normalized, e.g. illegal states will be marked as
|
||||
* unbootable and all unbootable states are represented with
|
||||
* (priority=0, tries_remaining=0, successful_boot=0).
|
||||
*/
|
||||
fsl_slot_normalize(&ab_data->slots[0]);
|
||||
fsl_slot_normalize(&ab_data->slots[1]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mmc_load_image_raw_sector_dual_uboot(
|
||||
struct spl_image_info *spl_image, struct mmc *mmc)
|
||||
{
|
||||
unsigned long count;
|
||||
disk_partition_t info;
|
||||
int ret = 0, n = 0;
|
||||
char partition_name[PARTITION_NAME_LEN];
|
||||
struct blk_desc *dev_desc;
|
||||
struct image_header *header;
|
||||
AvbABData ab_data, ab_data_orig;
|
||||
size_t slot_index_to_boot, target_slot;
|
||||
|
||||
/* Check if gpt is valid */
|
||||
dev_desc = mmc_get_blk_desc(mmc);
|
||||
if (dev_desc) {
|
||||
if (part_get_info(dev_desc, 1, &info)) {
|
||||
printf("GPT is invalid, please flash correct GPT!\n");
|
||||
ret = -EIO;
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
printf("Get block desc fail!\n");
|
||||
ret = -EIO;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Load AB metadata from misc partition */
|
||||
if (fsl_load_metadata_dual_uboot(dev_desc, &ab_data,
|
||||
&ab_data_orig)) {
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
slot_index_to_boot = 2; // Means not 0 or 1
|
||||
target_slot =
|
||||
(ab_data.slots[1].priority > ab_data.slots[0].priority) ? 1 : 0;
|
||||
|
||||
for (n = 0; n < 2; n++) {
|
||||
if (!fsl_slot_is_bootable(&ab_data.slots[target_slot])) {
|
||||
target_slot = (target_slot == 1 ? 0 : 1);
|
||||
continue;
|
||||
}
|
||||
/* Choose slot to load. */
|
||||
snprintf(partition_name, PARTITION_NAME_LEN,
|
||||
PARTITION_BOOTLOADER"%s",
|
||||
slot_suffixes[target_slot]);
|
||||
|
||||
/* Read part info from gpt */
|
||||
if (part_get_info_by_name(dev_desc, partition_name, &info) == -1) {
|
||||
printf("Can't get partition info of partition bootloader%s\n",
|
||||
slot_suffixes[target_slot]);
|
||||
} else {
|
||||
header = (struct image_header *)(CONFIG_SYS_TEXT_BASE -
|
||||
sizeof(struct image_header));
|
||||
|
||||
/* read image header to find the image size & load address */
|
||||
count = blk_dread(dev_desc, info.start, 1, header);
|
||||
if (count == 0) {
|
||||
ret = -EIO;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
|
||||
image_get_magic(header) == FDT_MAGIC) {
|
||||
struct spl_load_info load;
|
||||
|
||||
debug("Found FIT\n");
|
||||
load.dev = mmc;
|
||||
load.priv = NULL;
|
||||
load.filename = NULL;
|
||||
load.bl_len = mmc->read_bl_len;
|
||||
load.read = h_spl_load_read;
|
||||
ret = spl_load_simple_fit(spl_image, &load,
|
||||
info.start, header);
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set current slot to unbootable if load/verify fail. */
|
||||
if (ret != 0) {
|
||||
printf("Load or verify bootloader%s fail, setting unbootable..\n",
|
||||
slot_suffixes[target_slot]);
|
||||
fsl_slot_set_unbootable(&ab_data.slots[target_slot]);
|
||||
/* Switch to another slot. */
|
||||
target_slot = (target_slot == 1 ? 0 : 1);
|
||||
} else {
|
||||
slot_index_to_boot = target_slot;
|
||||
n = 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (slot_index_to_boot == 2) {
|
||||
/* No bootable slots! */
|
||||
printf("No bootable slots found.\n");
|
||||
ret = -1;
|
||||
goto end;
|
||||
} else if (!ab_data.slots[slot_index_to_boot].successful_boot &&
|
||||
(ab_data.slots[slot_index_to_boot].tries_remaining > 0)) {
|
||||
ab_data.slots[slot_index_to_boot].tries_remaining -= 1;
|
||||
}
|
||||
printf("Booting from bootloader%s...\n", slot_suffixes[slot_index_to_boot]);
|
||||
|
||||
end:
|
||||
/* Save metadata if changed. */
|
||||
if (fsl_save_metadata_if_changed_dual_uboot(dev_desc, &ab_data, &ab_data_orig)) {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For normal build */
|
||||
#elif !defined(CONFIG_SPL_BUILD)
|
||||
|
||||
/* Writes A/B metadata to disk only if it has been changed.
|
||||
*/
|
||||
static AvbIOResult fsl_save_metadata_if_changed(AvbABOps* ab_ops,
|
||||
AvbABData* ab_data,
|
||||
|
|
@ -52,14 +328,6 @@ static AvbIOResult fsl_save_metadata_if_changed(AvbABOps* ab_ops,
|
|||
return AVB_IO_RESULT_OK;
|
||||
}
|
||||
|
||||
/* This is a copy of slot_is_bootable() from
|
||||
* lib/avb/libavb_ab/avb_ab_flow.c.
|
||||
*/
|
||||
static bool fsl_slot_is_bootable(AvbABSlotData* slot) {
|
||||
return (slot->priority > 0) &&
|
||||
(slot->successful_boot || (slot->tries_remaining > 0));
|
||||
}
|
||||
|
||||
/* Helper function to load metadata - returns AVB_IO_RESULT_OK on
|
||||
* success, error code otherwise. This is a copy of load_metadata()
|
||||
* from /lib/avb/libavb_ab/avb_ab_flow.c.
|
||||
|
|
@ -396,3 +664,5 @@ out:
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DUAL_BOOTLOADER && CONFIG_SPL_BUILD */
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
+ * Copyright 2017 NXP
|
||||
+ * Copyright 2018 NXP
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
|
|
@ -10,9 +10,13 @@
|
|||
#include "debug.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* get margin_pos struct from offset [to the partition start/end] and num_bytes to read/write */
|
||||
/*
|
||||
* get margin_pos struct from offset [to the partition start/end] and
|
||||
* num_bytes to read/write
|
||||
*/
|
||||
int get_margin_pos(uint64_t part_start, uint64_t part_end, unsigned long blksz,
|
||||
margin_pos_t *margin, int64_t offset, size_t num_bytes, bool allow_partial) {
|
||||
margin_pos_t *margin, int64_t offset, size_t num_bytes,
|
||||
bool allow_partial) {
|
||||
long off;
|
||||
if (margin == NULL)
|
||||
return -1;
|
||||
|
|
@ -22,21 +26,27 @@ int get_margin_pos(uint64_t part_start, uint64_t part_end, unsigned long blksz,
|
|||
|
||||
if (offset < 0) {
|
||||
margin->blk_start = (offset + 1) / (uint64_t)blksz + part_end;
|
||||
margin->start = (off = offset % (uint64_t)blksz) == 0 ? 0 : blksz + off; // offset == -1 means the last byte?, or start need -1
|
||||
// offset == -1 means the last byte?, or start need -1
|
||||
margin->start = (off = offset % (uint64_t)blksz) == 0 ?
|
||||
0 : blksz + off;
|
||||
if (offset + num_bytes - 1 >= 0) {
|
||||
if (!allow_partial)
|
||||
return -1;
|
||||
margin->blk_end = part_end;
|
||||
margin->end = blksz - 1;
|
||||
} else {
|
||||
margin->blk_end = (num_bytes + offset) / (uint64_t)blksz + part_end; // which blk the last byte is in
|
||||
margin->end = (off = (num_bytes + offset - 1) % (uint64_t)blksz) == 0 ?
|
||||
0 : blksz + off; // last byte
|
||||
// which blk the last byte is in
|
||||
margin->blk_end = (num_bytes + offset) /
|
||||
(uint64_t)blksz + part_end;
|
||||
margin->end = (off = (num_bytes + offset - 1) %
|
||||
(uint64_t)blksz) == 0 ?
|
||||
0 : blksz + off; // last byte
|
||||
}
|
||||
} else {
|
||||
margin->blk_start = offset / (uint64_t)blksz + part_start;
|
||||
margin->start = offset % (uint64_t)blksz;
|
||||
margin->blk_end = (offset + num_bytes - 1) / (uint64_t)blksz + part_start ;
|
||||
margin->blk_end = ((offset + num_bytes - 1) / (uint64_t)blksz) +
|
||||
part_start ;
|
||||
margin->end = (offset + num_bytes - 1) % (uint64_t)blksz;
|
||||
if (margin->blk_end > part_end) {
|
||||
if (!allow_partial)
|
||||
|
|
@ -46,7 +56,7 @@ int get_margin_pos(uint64_t part_start, uint64_t part_end, unsigned long blksz,
|
|||
}
|
||||
}
|
||||
VDEBUG("bs=%ld, be=%ld, s=%ld, e=%ld\n",
|
||||
margin->blk_start, margin->blk_end, margin->start, margin->end);
|
||||
margin->blk_start, margin->blk_end, margin->start, margin->end);
|
||||
|
||||
if (margin->blk_start > part_end || margin->blk_start < part_start)
|
||||
return -1;
|
||||
|
|
@ -56,3 +66,151 @@ int get_margin_pos(uint64_t part_start, uint64_t part_end, unsigned long blksz,
|
|||
VDEBUG("bm=%ld\n", margin->multi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_from_partition_in_bytes(struct blk_desc *fs_dev_desc,
|
||||
disk_partition_t *info, int64_t offset,
|
||||
size_t num_bytes, void* buffer,
|
||||
size_t* out_num_read)
|
||||
{
|
||||
unsigned char *bdata;
|
||||
unsigned char *out_buf = (unsigned char *)buffer;
|
||||
unsigned char *dst, *dst64 = NULL;
|
||||
unsigned long blksz;
|
||||
unsigned long s, cnt;
|
||||
size_t num_read = 0;
|
||||
lbaint_t part_start, part_end, bs, be, bm, blk_num;
|
||||
margin_pos_t margin;
|
||||
int ret;
|
||||
|
||||
if(buffer == NULL || out_num_read == NULL) {
|
||||
printf("NULL pointer error!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
blksz = fs_dev_desc->blksz;
|
||||
part_start = info->start;
|
||||
part_end = info->start + info->size - 1;
|
||||
|
||||
if (get_margin_pos((uint64_t)part_start, (uint64_t)part_end, blksz,
|
||||
&margin, offset, num_bytes, true))
|
||||
return -1;
|
||||
|
||||
bs = (lbaint_t)margin.blk_start;
|
||||
be = (lbaint_t)margin.blk_end;
|
||||
s = margin.start;
|
||||
bm = margin.multi;
|
||||
|
||||
/* alloc a blksz mem */
|
||||
bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
|
||||
if (bdata == NULL) {
|
||||
printf("Failed to allocate memory!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* support multi blk read */
|
||||
while (bs <= be) {
|
||||
if (!s && bm > 1) {
|
||||
dst = out_buf;
|
||||
/* for mmc blk read alignment */
|
||||
dst64 = PTR_ALIGN(out_buf, 64);
|
||||
if (dst64 != dst) {
|
||||
dst = dst64;
|
||||
bm--;
|
||||
}
|
||||
blk_num = bm;
|
||||
cnt = bm * blksz;
|
||||
bm = 0; /* no more multi blk */
|
||||
} else {
|
||||
blk_num = 1;
|
||||
cnt = blksz - s;
|
||||
if (num_read + cnt > num_bytes)
|
||||
cnt = num_bytes - num_read;
|
||||
dst = bdata;
|
||||
}
|
||||
if (!blk_dread(fs_dev_desc, bs, blk_num, dst)) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (dst == bdata)
|
||||
memcpy(out_buf, bdata + s, cnt);
|
||||
else if (dst == dst64)
|
||||
memcpy(out_buf, dst, cnt); /* internal copy */
|
||||
|
||||
s = 0;
|
||||
bs += blk_num;
|
||||
num_read += cnt;
|
||||
out_buf += cnt;
|
||||
}
|
||||
*out_num_read = num_read;
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
free(bdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int write_to_partition_in_bytes(struct blk_desc *fs_dev_desc,
|
||||
disk_partition_t *info, int64_t offset,
|
||||
size_t num_bytes,
|
||||
void* buffer, size_t *out_num_write)
|
||||
{
|
||||
unsigned char *bdata;
|
||||
unsigned char *in_buf = (unsigned char *)buffer;
|
||||
unsigned long blksz;
|
||||
unsigned long s, cnt;
|
||||
size_t num_write = 0;
|
||||
lbaint_t part_start, part_end, bs;
|
||||
margin_pos_t margin;
|
||||
int ret;
|
||||
|
||||
if(buffer == NULL || out_num_write == NULL) {
|
||||
printf("NULL pointer error!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
blksz = fs_dev_desc->blksz;
|
||||
part_start = info->start;
|
||||
part_end = info->start + info->size - 1;
|
||||
|
||||
if(get_margin_pos((uint64_t)part_start, (uint64_t)part_end, blksz,
|
||||
&margin, offset, num_bytes, false))
|
||||
return -1;
|
||||
|
||||
bs = (lbaint_t)margin.blk_start;
|
||||
s = margin.start;
|
||||
|
||||
// alloc a blksz mem
|
||||
bdata = (unsigned char *)memalign(ALIGN_BYTES, blksz);
|
||||
if (bdata == NULL)
|
||||
return -1;
|
||||
|
||||
while (num_write < num_bytes) {
|
||||
memset(bdata, 0, blksz);
|
||||
cnt = blksz - s;
|
||||
if (num_write + cnt > num_bytes)
|
||||
cnt = num_bytes - num_write;
|
||||
if (!s || cnt != blksz) { //read blk first
|
||||
if (!blk_dread(fs_dev_desc, bs, 1,
|
||||
bdata)) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
memcpy(bdata + s, in_buf, cnt); //change data
|
||||
if (!blk_dwrite(fs_dev_desc, bs, 1, bdata)) {
|
||||
ret = -1;
|
||||
goto fail;
|
||||
}
|
||||
bs++;
|
||||
num_write += cnt;
|
||||
in_buf += cnt;
|
||||
s = 0;
|
||||
}
|
||||
*out_num_write = num_write;
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
free(bdata);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
* Copyright 2018 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
|
@ -26,6 +26,17 @@ struct margin_pos {
|
|||
typedef struct margin_pos margin_pos_t;
|
||||
|
||||
int get_margin_pos(uint64_t part_start, uint64_t part_end, unsigned long blksz,
|
||||
margin_pos_t *margin, int64_t offset, size_t num_bytes, bool allow_partial);
|
||||
margin_pos_t *margin, int64_t offset, size_t num_bytes,
|
||||
bool allow_partial);
|
||||
|
||||
int read_from_partition_in_bytes(struct blk_desc *fs_dev_desc,
|
||||
disk_partition_t *info,
|
||||
int64_t offset, size_t num_bytes,
|
||||
void* buffer, size_t* out_num_read);
|
||||
|
||||
int write_to_partition_in_bytes(struct blk_desc *fs_dev_desc,
|
||||
disk_partition_t *info, int64_t offset,
|
||||
size_t num_bytes, void* buffer,
|
||||
size_t *out_num_write);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,17 +1,21 @@
|
|||
ccflags-y += -DAVB_COMPILATION
|
||||
|
||||
ifndef CONFIG_SPL_BUILD
|
||||
obj-y += avb_descriptor.o \
|
||||
avb_kernel_cmdline_descriptor.o \
|
||||
avb_sha512.o \
|
||||
avb_vbmeta_image.o \
|
||||
avb_chain_partition_descriptor.o \
|
||||
avb_footer.o \
|
||||
avb_property_descriptor.o \
|
||||
avb_slot_verify.o \
|
||||
avb_crc32.o \
|
||||
avb_hash_descriptor.o \
|
||||
avb_rsa.o \
|
||||
avb_crypto.o \
|
||||
avb_hashtree_descriptor.o \
|
||||
avb_sha256.o \
|
||||
avb_util.o \
|
||||
avb_cmdline.o
|
||||
avb_kernel_cmdline_descriptor.o \
|
||||
avb_sha512.o \
|
||||
avb_vbmeta_image.o \
|
||||
avb_chain_partition_descriptor.o \
|
||||
avb_footer.o \
|
||||
avb_property_descriptor.o \
|
||||
avb_slot_verify.o \
|
||||
avb_hash_descriptor.o \
|
||||
avb_rsa.o \
|
||||
avb_crypto.o \
|
||||
avb_hashtree_descriptor.o \
|
||||
avb_sha256.o \
|
||||
avb_util.o \
|
||||
avb_cmdline.o
|
||||
endif
|
||||
|
||||
obj-y += avb_crc32.o
|
||||
|
|
|
|||
Loading…
Reference in New Issue