Skip to content
17 changes: 12 additions & 5 deletions core/arch/arm/plat-qcom/hoya/lemans/target.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ ifneq ($(CFG_INSECURE),y)
CFG_QCOM_QFPROM_FUSEPROV ?= y
endif

ifeq ($(CFG_QCOM_QFPROM_FUSEPROV),y)
$(call force,CFG_QCOM_QFPROM,y)
endif

CFG_QCOM_PAS_PTA ?= y

ifeq ($(CFG_QCOM_PAS_PTA),y)
Expand All @@ -20,7 +16,18 @@ ifeq ($(CFG_QCOM_PAS_PTA),y)
CFG_RESERVED_VASPACE_SIZE ?= (256 * 1024 * 1024)
CFG_IN_TREE_EARLY_TAS += qcom_pas/cff7d191-7ca0-4784-af13-48223b9a4fbe
CFG_QCOM_PAS_AUTH ?= y
CFG_PAS_MD_SLOTS = 8
endif

CFG_QCOM_HWKM ?= y

ifeq ($(CFG_QCOM_PAS_AUTH),y)
$(call force,CFG_QCOM_FUSE_PTA,y)
CFG_PAS_MD_SLOTS = 8
# This chip's OEM_CONFIG2 fuse row has a per-root-cert hash function
# select bit; targets without it always use SHA-384.
$(call force,CFG_QCOM_SEGMENT_HASH_SELECT,y)
endif

ifneq ($(filter y,$(CFG_QCOM_QFPROM_FUSEPROV) $(CFG_QCOM_FUSE_PTA)),)
$(call force,CFG_QCOM_QFPROM,y)
endif
26 changes: 26 additions & 0 deletions core/drivers/qcom/qfprom/lemans/qfprom_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,30 @@ enum qfprom_perm_bit_pos {
#define OEM_SPARE_30_PERM_MASK BIT(OEM_SPARE_30)
#define OEM_SPARE_31_PERM_MASK BIT(OEM_SPARE_31)

#define OEM_CONFIG2_OFFSET 0x6054
#define EKU_ENFORCEMENT_EN_SHFT 30
#define SEGMENT_HASH_FUNCTION_SELECT0_SHFT 16

#define SECURE_BOOT_APPS_OFFSET 0x606c
#define SECURE_BOOT_AUTH_EN_BMSK BIT(5)
#define SECURE_BOOT_USE_SERIAL_NUM_BMSK BIT(6)

#define JTAG_ID_OFFSET 0x6130
#define JTAG_ID_AUTH_BMSK GENMASK_32(27, 0)

#define SERIAL_NUM_OFFSET 0x6134

#define OEM_ID_OFFSET 0x6138
#define OEM_ID_BMSK GENMASK_32(31, 16)
#define OEM_ID_SHFT 16
#define MODEL_ID_BMSK GENMASK_32(15, 0)
#define MODEL_ID_SHFT 0

#define PK_HASH0_OFFSET 0x6190
#define QFPROM_ROOT_OF_TRUST_BYTE_SIZE 48

#define TCSR_SOC_HW_VERSION_ADDR 0x01FC8000
#define SOC_HW_VERSION_FAM_DEV_BMSK 0xffff0000
#define SOC_HW_VERSION_FAM_DEV_SHFT 16

#endif /* __QFPROM_TARGET_H__ */
192 changes: 192 additions & 0 deletions core/drivers/qcom/qfprom/qfprom_secboot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/

#include <config.h>
#include <inttypes.h>
#include <io.h>
#include <mm/core_memprot.h>
#include <mm/core_mmu.h>
#include <string.h>
#include <trace.h>
#include <utee_defines.h>
#include <util.h>

#include "qfprom_priv.h"
#include "qfprom_target.h"

register_phys_mem_pgdir(MEM_AREA_IO_SEC, TCSR_SOC_HW_VERSION_ADDR,
CORE_MMU_PGDIR_SIZE);

static TEE_Result read_sense_reg(uint32_t offset, uint32_t *out)
{
struct qfprom_context *drv = qfprom_get_context();

if (!drv->raw_base_va)
return TEE_ERROR_BAD_STATE;

*out = io_read32(drv->raw_base_va + offset);

return TEE_SUCCESS;
}

TEE_Result qcom_secboot_is_enabled(bool *enabled)
{
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t val = 0;

if (!enabled)
return TEE_ERROR_BAD_PARAMETERS;

res = read_sense_reg(SECURE_BOOT_APPS_OFFSET, &val);
if (res)
return res;

*enabled = (val & SECURE_BOOT_AUTH_EN_BMSK) != 0;

return TEE_SUCCESS;
}

TEE_Result qcom_secboot_is_use_serial_num_enabled(bool *enabled)
{
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t val = 0;

if (!enabled)
return TEE_ERROR_BAD_PARAMETERS;

res = read_sense_reg(SECURE_BOOT_APPS_OFFSET, &val);
if (res)
return res;

*enabled = (val & SECURE_BOOT_USE_SERIAL_NUM_BMSK) != 0;

return TEE_SUCCESS;
}

TEE_Result qcom_secboot_get_root_of_trust(uint8_t *hash, size_t len)
{
size_t off = 0;

if (!hash)
return TEE_ERROR_BAD_PARAMETERS;

if (len != QFPROM_ROOT_OF_TRUST_BYTE_SIZE)
return TEE_ERROR_BAD_PARAMETERS;

for (off = 0; off < len; off += sizeof(uint32_t)) {
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t word = 0;

res = read_sense_reg(PK_HASH0_OFFSET + off, &word);
if (res)
return res;

memcpy(hash + off, &word, sizeof(word));
}

return TEE_SUCCESS;
}

TEE_Result qcom_secboot_get_device_ids(struct qcom_secboot_device_ids *ids)
{
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t val = 0;

if (!ids)
return TEE_ERROR_BAD_PARAMETERS;

res = read_sense_reg(OEM_ID_OFFSET, &val);
if (res)
return res;
ids->oem_id = (val & OEM_ID_BMSK) >> OEM_ID_SHFT;
ids->model_id = (val & MODEL_ID_BMSK) >> MODEL_ID_SHFT;

res = read_sense_reg(JTAG_ID_OFFSET, &val);
if (res)
return res;
ids->jtag_id = val & JTAG_ID_AUTH_BMSK;

res = read_sense_reg(SERIAL_NUM_OFFSET, &ids->serial_num);
if (res)
return res;

return TEE_SUCCESS;
}

#define SEGMENT_HASH_ROOT_CERT_SEL_MAX 3U

/*
* Return the hash algorithm's digest size (SHA-256 or SHA-384) selected
* for the root cert at @root_cert_sel, per the OEM_CONFIG2 fuse row.
*/
TEE_Result qcom_secboot_get_segment_hash_len(uint32_t root_cert_sel,
uint32_t *hash_len)
Comment thread
zelvam95 marked this conversation as resolved.
{
if (!hash_len)
return TEE_ERROR_BAD_PARAMETERS;

if (root_cert_sel > SEGMENT_HASH_ROOT_CERT_SEL_MAX)
return TEE_ERROR_BAD_PARAMETERS;

if (IS_ENABLED(CFG_QCOM_SEGMENT_HASH_SELECT)) {
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t val = 0;

res = read_sense_reg(OEM_CONFIG2_OFFSET, &val);
if (res)
return res;

if (val & BIT32(SEGMENT_HASH_FUNCTION_SELECT0_SHFT +
root_cert_sel))
*hash_len = TEE_SHA256_HASH_SIZE;
else
*hash_len = TEE_SHA384_HASH_SIZE;
} else {
*hash_len = TEE_SHA384_HASH_SIZE;
}

return TEE_SUCCESS;
}

TEE_Result qcom_secboot_get_eku_enforcement_en(bool *enabled)
{
TEE_Result res = TEE_ERROR_GENERIC;
uint32_t val = 0;

if (!enabled)
return TEE_ERROR_BAD_PARAMETERS;

res = read_sense_reg(OEM_CONFIG2_OFFSET, &val);
if (res)
return res;

*enabled = val & BIT32(EKU_ENFORCEMENT_EN_SHFT);

return TEE_SUCCESS;
}

TEE_Result qcom_secboot_get_soc_hw_version(uint32_t *fam_dev)
{
static vaddr_t soc_hw_version_addr;
uint32_t val = 0;

if (!fam_dev)
return TEE_ERROR_BAD_PARAMETERS;

if (!soc_hw_version_addr) {
soc_hw_version_addr =
(vaddr_t)phys_to_virt(TCSR_SOC_HW_VERSION_ADDR,
MEM_AREA_IO_SEC,
sizeof(uint32_t));
if (!soc_hw_version_addr)
return TEE_ERROR_GENERIC;
}

val = io_read32(soc_hw_version_addr);
*fam_dev = (val & SOC_HW_VERSION_FAM_DEV_BMSK) >>
SOC_HW_VERSION_FAM_DEV_SHFT;

return TEE_SUCCESS;
}
1 change: 1 addition & 0 deletions core/drivers/qcom/qfprom/sub.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ srcs-y += qfprom_core.c
srcs-y += qfprom_hal.c
srcs-y += qfprom_target.c
srcs-y += $(PLATFORM_FLAVOR)/qfprom_fuse_region.c
srcs-$(CFG_QCOM_FUSE_PTA) += qfprom_secboot.c
Comment thread
zelvam95 marked this conversation as resolved.

global-incdirs-y += .
global-incdirs-y += $(PLATFORM_FLAVOR)
32 changes: 32 additions & 0 deletions core/include/drivers/qcom/qfprom/qfprom.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,43 @@ enum qfprom_error {
QFPROM_ERROR_TIMEOUT = 0x11,
};

struct qcom_secboot_device_ids {
uint32_t oem_id;
uint32_t model_id;
uint32_t jtag_id;
uint32_t serial_num;
};

/* Read QFPROM row data */
TEE_Result qfprom_read_row(uint32_t addr,
enum qfprom_addr_space type,
uint32_t *data);

/* Is secure boot (authentication) enabled on this device? */
TEE_Result qcom_secboot_is_enabled(bool *enabled);
Comment thread
zelvam95 marked this conversation as resolved.

/* Is the serial-number fuse used as part of device binding? */
TEE_Result qcom_secboot_is_use_serial_num_enabled(bool *enabled);

/* Read the OEM root-of-trust anchor hash (PK_HASH0). */
TEE_Result qcom_secboot_get_root_of_trust(uint8_t *hash, size_t len);

/* Read the OEM/model/JTAG/serial device-identity fuses. */
TEE_Result qcom_secboot_get_device_ids(struct qcom_secboot_device_ids *ids);

/* Read the SoC family/device word from TCSR_SOC_HW_VERSION. */
TEE_Result qcom_secboot_get_soc_hw_version(uint32_t *fam_dev);

/*
* Segment/hash-table digest size for @root_cert_sel; unrelated to
* cert-chain or root-of-trust hashing.
*/
TEE_Result qcom_secboot_get_segment_hash_len(uint32_t root_cert_sel,
uint32_t *hash_len);

/* Is code-signing EKU enforcement required for this device? */
TEE_Result qcom_secboot_get_eku_enforcement_en(bool *enabled);

/* Write QFPROM row data */
TEE_Result qfprom_write_row(uint32_t addr, uint32_t *data);

Expand Down
Loading
Loading