blob: cbfaa918feedca58e1a5071984a4ce3dd8941e83 [file] [log] [blame] [edit]
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
/*
* common/anti-rollback.c
*
* Copyright (C) 2020 Amlogic, Inc. All rights reserved.
*
*/
#include <common.h>
#include <asm/arch/bl31_apis.h>
#include <linux/arm-smccc.h>
#include "anti-rollback.h"
#define FUNCID_ANTIROLLBACK_VERSION_CHECK 0xb2000010
#define FUNCID_AVB_VERSION_SET 0xb2000011
#define FUNCID_AVB_VERSION_GET 0xb2000012
#define FUNCID_AVB_LOCK_STATE_GET 0xb2000013
#define FUNCID_AVB_LOCK 0xb2000014
#define FUNCID_AVB_UNLOCK 0xb2000015
#define IMAGE_VERSION_TYPE_BOOTLOADER 0x001
#define IMAGE_VERSION_TYPE_RECOVERY 0x002
#define IMAGE_VERSION_TYPE_BOOT 0x003
#define KERNEL_TYPE_UNKNOWN 0x00
#define KERNEL_TYPE_BOOT 0x01
#define KERNEL_TYPE_RECOVERY 0x02
static uint32_t antirollback_image_version_check(uint32_t type,
uint32_t version)
{
struct arm_smccc_res res;
arm_smccc_smc(FUNCID_ANTIROLLBACK_VERSION_CHECK, type, version, 0, 0, 0, 0, 0, &res);
return res.a0;
}
bool check_antirollback(uint32_t kernel_version)
{
bool ret = true;
uint32_t type = (kernel_version >> 24);
uint32_t version = ((kernel_version << 8) >> 8);
if (KERNEL_TYPE_BOOT == type) {
if (antirollback_image_version_check(IMAGE_VERSION_TYPE_BOOT,
version) != 0) {
printf("checking boot.img version failed\n");
ret = false;
}
}
else if (KERNEL_TYPE_RECOVERY == type) {
if (antirollback_image_version_check(
IMAGE_VERSION_TYPE_RECOVERY,
version) != 0) {
printf("checking recovery.img version failed\n");
ret = false;
}
}
else {
printf("the kernel type is unknown\n");
ret = false;
}
if (ret)
printf("checking version success\n");
return ret;
}
bool set_avb_antirollback(uint32_t index, uint32_t version)
{
struct arm_smccc_res res;
arm_smccc_smc(FUNCID_AVB_VERSION_SET, index, version, 0, 0, 0, 0, 0, &res);
return res.a0 == 0;
}
bool get_avb_antirollback(uint32_t index, uint32_t* version)
{
struct arm_smccc_res res;
arm_smccc_smc(FUNCID_AVB_VERSION_GET, index, 0, 0, 0, 0, 0, 0, &res);
if (res.a0 == 0)
*version = res.a1;
return res.a0 == 0;
}
bool get_avb_lock_state(uint32_t* lock_state)
{
struct arm_smccc_res res;
arm_smccc_smc(FUNCID_AVB_LOCK_STATE_GET, 0, 0, 0, 0, 0, 0, 0, &res);
if (res.a0 == 0)
*lock_state = res.a1;
return res.a0 == 0;
}
bool avb_lock(void)
{
struct arm_smccc_res res;
arm_smccc_smc(FUNCID_AVB_LOCK, 0, 0, 0, 0, 0, 0, 0, &res);
return res.a0 == 0;
}
bool avb_unlock(void)
{
struct arm_smccc_res res;
arm_smccc_smc(FUNCID_AVB_UNLOCK, 0, 0, 0, 0, 0, 0, 0, &res);
return res.a0 == 0;
}