// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2014 Freescale Semiconductor, Inc.
 *
 */

#include <common.h>
#include <cpu_func.h>
#include <log.h>
#include <malloc.h>
#include <memalign.h>
#include <fsl_sec.h>
#include <asm/cache.h>
#include <linux/errno.h>
#include "jobdesc.h"
#include "desc.h"
#include "jr.h"

/**
 * blob_decap() - Decapsulate the data from a blob
 * @key_mod:    - Key modifier address
 * @src:        - Source address (blob)
 * @dst:        - Destination address (data)
 * @len:        - Size of decapsulated data
 *
 * Note: Start and end of the key_mod, src and dst buffers have to be aligned to
 * the cache line size (ARCH_DMA_MINALIGN) for the CAAM operation to succeed.
 *
 * Returns zero on success, negative on error.
 */
int blob_decap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
{
	int ret, size, i = 0;
	u32 *desc;

	if (!IS_ALIGNED((uintptr_t)key_mod, ARCH_DMA_MINALIGN) ||
	    !IS_ALIGNED((uintptr_t)src, ARCH_DMA_MINALIGN) ||
	    !IS_ALIGNED((uintptr_t)dst, ARCH_DMA_MINALIGN)) {
		puts("Error: blob_decap: Address arguments are not aligned!\n");
		return -EINVAL;
	}

	printf("\nDecapsulating blob to get data\n");
	desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
	if (!desc) {
		debug("Not enough memory for descriptor allocation\n");
		return -ENOMEM;
	}

	size = ALIGN(16, ARCH_DMA_MINALIGN);
	flush_dcache_range((unsigned long)key_mod,
			   (unsigned long)key_mod + size);

	size = ALIGN(BLOB_SIZE(len), ARCH_DMA_MINALIGN);
	flush_dcache_range((unsigned long)src,
			   (unsigned long)src + size);

	inline_cnstr_jobdesc_blob_decap(desc, key_mod, src, dst, len);

	debug("Descriptor dump:\n");
	for (i = 0; i < 14; i++)
		debug("Word[%d]: %08x\n", i, *(desc + i));

	size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN);
	flush_dcache_range((unsigned long)desc,
			   (unsigned long)desc + size);

	flush_dcache_range((unsigned long)dst,
			   (unsigned long)dst + size);

	ret = run_descriptor_jr(desc);

	if (ret) {
		/* clear the blob data output buffer */
		memset(dst, 0x00, len);
		size = ALIGN(len, ARCH_DMA_MINALIGN);
		flush_dcache_range((unsigned long)dst, (unsigned long)dst + size);
		printf("Error in blob decapsulation: %d\n", ret);
	} else {
		size = ALIGN(len, ARCH_DMA_MINALIGN);
		invalidate_dcache_range((unsigned long)dst,
					(unsigned long)dst + size);

		puts("Blob decapsulation successful.\n");
	}

	free(desc);
	return ret;
}

/**
 * blob_encap() - Encapsulate the data as a blob
 * @key_mod:    - Key modifier address
 * @src:        - Source address (data)
 * @dst:        - Destination address (blob)
 * @len:        - Size of data to be encapsulated
 *
 * Note: Start and end of the key_mod, src and dst buffers have to be aligned to
 * the cache line size (ARCH_DMA_MINALIGN) for the CAAM operation to succeed.
 *
 * Returns zero on success, negative on error.
 */
int blob_encap(u8 *key_mod, u8 *src, u8 *dst, u32 len)
{
	int ret, size, i = 0;
	u32 *desc;

	if (!IS_ALIGNED((uintptr_t)key_mod, ARCH_DMA_MINALIGN) ||
	    !IS_ALIGNED((uintptr_t)src, ARCH_DMA_MINALIGN) ||
	    !IS_ALIGNED((uintptr_t)dst, ARCH_DMA_MINALIGN)) {
		puts("Error: blob_encap: Address arguments are not aligned!\n");
		return -EINVAL;
	}

	printf("\nEncapsulating data to form blob\n");
	desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE);
	if (!desc) {
		debug("Not enough memory for descriptor allocation\n");
		return -ENOMEM;
	}

	size = ALIGN(16, ARCH_DMA_MINALIGN);
	flush_dcache_range((unsigned long)key_mod,
			   (unsigned long)key_mod + size);

	size = ALIGN(len, ARCH_DMA_MINALIGN);
	flush_dcache_range((unsigned long)src,
			   (unsigned long)src + size);

	inline_cnstr_jobdesc_blob_encap(desc, key_mod, src, dst, len);

	debug("Descriptor dump:\n");
	for (i = 0; i < 14; i++)
		debug("Word[%d]: %08x\n", i, *(desc + i));

	size = ALIGN(sizeof(int) * MAX_CAAM_DESCSIZE, ARCH_DMA_MINALIGN);
	flush_dcache_range((unsigned long)desc,
			   (unsigned long)desc + size);

	flush_dcache_range((unsigned long)dst,
			   (unsigned long)dst + size);

	ret = run_descriptor_jr(desc);

	if (ret) {
		printf("Error in blob encapsulation: %d\n", ret);
	} else {
		size = ALIGN(BLOB_SIZE(len), ARCH_DMA_MINALIGN);
		invalidate_dcache_range((unsigned long)dst,
					(unsigned long)dst + size);

		puts("Blob encapsulation successful.\n");
	}

	free(desc);
	return ret;
}

#ifdef CONFIG_CMD_DEKBLOB
int blob_dek(const u8 *src, u8 *dst, u8 len)
{
	int ret, size, i = 0;
	u32 *desc;

	int out_sz =  WRP_HDR_SIZE + len + KEY_BLOB_SIZE + MAC_SIZE;

	puts("\nEncapsulating provided DEK to form blob\n");
	desc = memalign(ARCH_DMA_MINALIGN,
			sizeof(uint32_t) * DEK_BLOB_DESCSIZE);
	if (!desc) {
		debug("Not enough memory for descriptor allocation\n");
		return -ENOMEM;
	}

	ret = inline_cnstr_jobdesc_blob_dek(desc, src, dst, len);
	if (ret) {
		debug("Error in Job Descriptor Construction:  %d\n", ret);
	} else {
		size = roundup(sizeof(uint32_t) * DEK_BLOB_DESCSIZE,
			      ARCH_DMA_MINALIGN);
		flush_dcache_range((unsigned long)desc,
				   (unsigned long)desc + size);
		size = roundup(sizeof(uint8_t) * out_sz, ARCH_DMA_MINALIGN);
		flush_dcache_range((unsigned long)dst,
				   (unsigned long)dst + size);

		ret = run_descriptor_jr(desc);
	}

	if (ret) {
		debug("Error in Encapsulation %d\n", ret);
	   goto err;
	}

	size = roundup(out_sz, ARCH_DMA_MINALIGN);
	invalidate_dcache_range((unsigned long)dst, (unsigned long)dst+size);

	puts("DEK Blob\n");
	for (i = 0; i < out_sz; i++)
		printf("%02X", ((uint8_t *)dst)[i]);
	printf("\n");

err:
	free(desc);
	return ret;
}
#endif
