meson/gxl: Add support for SHA256 DMA engine
In order to configure and boot SCP, BL31 has to compute and send the SHA-256 of the firmware data via scpi. Luckily Amlogic GXL SOC has a DMA facility that could be used to offload SHA-256 computations. This adds basic support of this hardware SHA-256 engine. Signed-off-by: Remi Pommarel <repk@triplefau.lt>
This commit is contained in:
parent
95d0d13ce2
commit
b99f9224ed
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <crypto/sha_dma.h>
|
||||
|
||||
#define AML_SHA_DMA_BASE 0xc883e000
|
||||
|
||||
#define AML_SHA_DMA_DESC (AML_SHA_DMA_BASE + 0x08)
|
||||
#define AML_SHA_DMA_STATUS (AML_SHA_DMA_BASE + 0x18)
|
||||
|
||||
#define ASD_MODE_SHA224 0x7
|
||||
#define ASD_MODE_SHA256 0x6
|
||||
|
||||
/* SHA DMA descriptor */
|
||||
struct asd_desc {
|
||||
uint32_t cfg;
|
||||
uint32_t src;
|
||||
uint32_t dst;
|
||||
};
|
||||
#define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk))
|
||||
#define ASD_DESC_SET(x, v, msk, off) \
|
||||
((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off)))
|
||||
|
||||
#define ASD_DESC_LEN_OFF 0
|
||||
#define ASD_DESC_LEN_MASK 0x1ffff
|
||||
#define ASD_DESC_LEN(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
|
||||
#define ASD_DESC_LEN_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF))
|
||||
|
||||
#define ASD_DESC_IRQ_OFF 17
|
||||
#define ASD_DESC_IRQ_MASK 0x1
|
||||
#define ASD_DESC_IRQ(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
|
||||
#define ASD_DESC_IRQ_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF))
|
||||
|
||||
#define ASD_DESC_EOD_OFF 18
|
||||
#define ASD_DESC_EOD_MASK 0x1
|
||||
#define ASD_DESC_EOD(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
|
||||
#define ASD_DESC_EOD_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF))
|
||||
|
||||
#define ASD_DESC_LOOP_OFF 19
|
||||
#define ASD_DESC_LOOP_MASK 0x1
|
||||
#define ASD_DESC_LOOP(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
|
||||
#define ASD_DESC_LOOP_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF))
|
||||
|
||||
#define ASD_DESC_MODE_OFF 20
|
||||
#define ASD_DESC_MODE_MASK 0xf
|
||||
#define ASD_DESC_MODE(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
|
||||
#define ASD_DESC_MODE_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF))
|
||||
|
||||
#define ASD_DESC_BEGIN_OFF 24
|
||||
#define ASD_DESC_BEGIN_MASK 0x1
|
||||
#define ASD_DESC_BEGIN(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
|
||||
#define ASD_DESC_BEGIN_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF))
|
||||
|
||||
#define ASD_DESC_END_OFF 25
|
||||
#define ASD_DESC_END_MASK 0x1
|
||||
#define ASD_DESC_END(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
|
||||
#define ASD_DESC_END_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF))
|
||||
|
||||
#define ASD_DESC_OP_OFF 26
|
||||
#define ASD_DESC_OP_MASK 0x2
|
||||
#define ASD_DESC_OP(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
|
||||
#define ASD_DESC_OP_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF))
|
||||
|
||||
#define ASD_DESC_ENCONLY_OFF 28
|
||||
#define ASD_DESC_ENCONLY_MASK 0x1
|
||||
#define ASD_DESC_ENCONLY(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
|
||||
#define ASD_DESC_ENCONLY_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF))
|
||||
|
||||
#define ASD_DESC_BLOCK_OFF 29
|
||||
#define ASD_DESC_BLOCK_MASK 0x1
|
||||
#define ASD_DESC_BLOCK(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
|
||||
#define ASD_DESC_BLOCK_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF))
|
||||
|
||||
#define ASD_DESC_ERR_OFF 30
|
||||
#define ASD_DESC_ERR_MASK 0x1
|
||||
#define ASD_DESC_ERR(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
|
||||
#define ASD_DESC_ERR_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF))
|
||||
|
||||
#define ASD_DESC_OWNER_OFF 31
|
||||
#define ASD_DESC_OWNER_MASK 0x1
|
||||
#define ASD_DESC_OWNER(d) \
|
||||
(ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
|
||||
#define ASD_DESC_OWNER_SET(d, v) \
|
||||
(ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF))
|
||||
|
||||
static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len,
|
||||
int finalize)
|
||||
{
|
||||
/* Make it cache line size aligned ? */
|
||||
struct asd_desc desc = {
|
||||
.src = (uint32_t)(uintptr_t)data,
|
||||
.dst = (uint32_t)(uintptr_t)ctx->digest,
|
||||
};
|
||||
|
||||
/* Check data address is 32bit compatible */
|
||||
assert((uintptr_t)data == (uintptr_t)desc.src);
|
||||
assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst);
|
||||
assert((uintptr_t)&desc == (uintptr_t)&desc);
|
||||
|
||||
ASD_DESC_LEN_SET(&desc, len);
|
||||
ASD_DESC_OWNER_SET(&desc, 1);
|
||||
ASD_DESC_ENCONLY_SET(&desc, 1);
|
||||
ASD_DESC_EOD_SET(&desc, 1);
|
||||
if (ctx->started == 0) {
|
||||
ASD_DESC_BEGIN_SET(&desc, 1);
|
||||
ctx->started = 1;
|
||||
}
|
||||
if (finalize) {
|
||||
ASD_DESC_END_SET(&desc, 1);
|
||||
ctx->started = 0;
|
||||
}
|
||||
if (ctx->mode == ASM_SHA224)
|
||||
ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224);
|
||||
else
|
||||
ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256);
|
||||
|
||||
flush_dcache_range((uintptr_t)&desc, sizeof(desc));
|
||||
flush_dcache_range((uintptr_t)data, len);
|
||||
|
||||
mmio_write_32(AML_SHA_DMA_STATUS, 0xf);
|
||||
mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2);
|
||||
while (mmio_read_32(AML_SHA_DMA_STATUS) == 0)
|
||||
continue;
|
||||
flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ);
|
||||
}
|
||||
|
||||
void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len)
|
||||
{
|
||||
size_t nr;
|
||||
|
||||
if (ctx->blocksz) {
|
||||
nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz);
|
||||
memcpy(ctx->block + ctx->blocksz, data, nr);
|
||||
ctx->blocksz += nr;
|
||||
len -= nr;
|
||||
data += nr;
|
||||
}
|
||||
|
||||
if (ctx->blocksz == SHA256_BLOCKSZ) {
|
||||
asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0);
|
||||
ctx->blocksz = 0;
|
||||
}
|
||||
|
||||
asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0);
|
||||
data += len & ~(SHA256_BLOCKSZ - 1);
|
||||
|
||||
if (len & (SHA256_BLOCKSZ - 1)) {
|
||||
nr = len & (SHA256_BLOCKSZ - 1);
|
||||
memcpy(ctx->block + ctx->blocksz, data, nr);
|
||||
ctx->blocksz += nr;
|
||||
}
|
||||
}
|
||||
|
||||
void asd_sha_finalize(struct asd_ctx *ctx)
|
||||
{
|
||||
asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Remi Pommarel <repk@triplefau.lt>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef SHA_DMA_H
|
||||
#define SHA_DMA_H
|
||||
|
||||
#define SHA256_HASHSZ 32
|
||||
#define SHA256_BLOCKSZ 0x40
|
||||
|
||||
enum ASD_MODE {
|
||||
ASM_INVAL,
|
||||
ASM_SHA256,
|
||||
ASM_SHA224,
|
||||
};
|
||||
|
||||
struct asd_ctx {
|
||||
uint8_t digest[SHA256_HASHSZ];
|
||||
uint8_t block[SHA256_BLOCKSZ];
|
||||
size_t blocksz;
|
||||
enum ASD_MODE mode;
|
||||
uint8_t started;
|
||||
};
|
||||
|
||||
static inline void asd_sha_init(struct asd_ctx *ctx, enum ASD_MODE mode)
|
||||
{
|
||||
ctx->started = 0;
|
||||
ctx->mode = mode;
|
||||
ctx->blocksz = 0;
|
||||
}
|
||||
|
||||
void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len);
|
||||
void asd_sha_finalize(struct asd_ctx *ctx);
|
||||
|
||||
#endif
|
|
@ -7,6 +7,7 @@
|
|||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
PLAT_INCLUDES := -Iinclude/drivers/meson/ \
|
||||
-Iinclude/drivers/meson/gxl \
|
||||
-Iplat/meson/gxl/include
|
||||
|
||||
GXBB_GIC_SOURCES := drivers/arm/gic/common/gic_common.c \
|
||||
|
@ -22,13 +23,14 @@ PLAT_BL_COMMON_SOURCES := drivers/meson/console/aarch64/meson_console.S \
|
|||
BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
|
||||
plat/common/plat_psci_common.c \
|
||||
plat/meson/gxl/aarch64/gxl_helpers.S \
|
||||
plat/meson/gxl/gxl_bl31_setup.c \
|
||||
plat/meson/gxl/gxl_bl31_setup.c \
|
||||
plat/meson/gxl/gxl_efuse.c \
|
||||
plat/meson/gxl/gxl_mhu.c \
|
||||
plat/meson/gxl/gxl_pm.c \
|
||||
plat/meson/gxl/gxl_pm.c \
|
||||
plat/meson/gxl/gxl_scpi.c \
|
||||
plat/meson/gxl/gxl_sip_svc.c \
|
||||
plat/meson/gxl/gxl_thermal.c \
|
||||
drivers/meson/gxl/crypto/sha_dma.c \
|
||||
${GXBB_GIC_SOURCES}
|
||||
|
||||
# Tune compiler for Cortex-A53
|
||||
|
|
Loading…
Reference in New Issue