/*
 * Copyright (c) 2015-2021, Renesas Electronics Corporation
 * All rights reserved.
 */

/******************************************************************************
 * @file          auth.c
 * - Version      : 0.01
 * @brief         Read data from certificate.
 * .
 *****************************************************************************/
/******************************************************************************
 * History : DD.MM.YYYY Version  Description
 *         : 29.05.2020 0.01     First Release
 *****************************************************************************/

#include <stdint.h>
#include <mmio.h>
#include "rcar_def.h"
#include "debug.h"
#include "auth.h"


#define RCAR_CERT_INFO_SIZE_OFFSET  (0x264U)    /* byte address set : must 4byte alignment */
#define RCAR_CERT_INFO_DST_OFFSET   (0x154U)    /* byte address set : must 4byte alignment */
#define RCAR_CERT_INFO_SIZE_OFFSET1 (0x364U)    /* for Map Type-1 */
#define RCAR_CERT_INFO_DST_OFFSET1  (0x1D4U)    /* for Map Type-1 */
#define RCAR_CERT_INFO_SIZE_OFFSET2 (0x464U)    /* for Map Type-2 */
#define RCAR_CERT_INFO_DST_OFFSET2  (0x254U)    /* for Map Type-2 */

#define RCAR_BOOT_KEY_CERT_NEW      (0xE6300F00U)
#define RCAR_CERT_MAGIC_NUM         (0xE291F358U)

#define FLASH_SEC_BOOT_CERT_ADDR    (0x00000800U)
#define FLASH_SEC_BOOT_CERT_ADDR2   (0x00000B00U)
#define FLASH_IPL_CERT_ADDR         (0x00000C00U)
#define FLASH_IPL_CERT_ADDR2        (0x00000080U)

static uint32_t s_boot_cert_offset = 0U;
static uint32_t s_ipl_cert_offset = 0U;

void pre_read_cert_info(void)
{
    uint32_t    magicNumber;

    magicNumber = mmio_read_32((uintptr_t)RCAR_BOOT_KEY_CERT_NEW);

    if (RCAR_CERT_MAGIC_NUM == magicNumber) {
        s_boot_cert_offset = FLASH_SEC_BOOT_CERT_ADDR2;
        s_ipl_cert_offset = FLASH_IPL_CERT_ADDR2;
    } else {
        s_boot_cert_offset = FLASH_SEC_BOOT_CERT_ADDR;
        s_ipl_cert_offset = FLASH_IPL_CERT_ADDR;
    }
}
/* End of function pre_read_cert_info */

void get_cert_info(uint32_t *boot_cert_addr, uint32_t *size,
    uint32_t *ipl_cert_addr)
{
    *boot_cert_addr = s_boot_cert_offset;
    *size = 0x1100U;
    *ipl_cert_addr = s_ipl_cert_offset;
}
/* End of function get_cert_info */

void get_info_from_cert(uint32_t cert_addr, uint32_t *size,
    uintptr_t *dest_addr)
{
    uint32_t    val;
    uint32_t    magicNumber;
    uint32_t    certInfo1;
    uintptr_t   pSize;
    uintptr_t   pDestL;

    magicNumber = mmio_read_32((uintptr_t)RCAR_BOOT_KEY_CERT_NEW);
    val = mmio_read_32((uintptr_t)cert_addr + 0xCU);
    certInfo1 = (val >> 21U) & 0x3U;

    if (RCAR_CERT_MAGIC_NUM == magicNumber)
    {
        if (0x2U == certInfo1)
        {
            pSize = cert_addr + RCAR_CERT_INFO_SIZE_OFFSET2;
            *size = mmio_read_32(pSize) * 4U;
            pDestL = cert_addr + RCAR_CERT_INFO_DST_OFFSET2;
            *dest_addr = (uintptr_t)mmio_read_32(pDestL);
        } 
        else if (0x1U == certInfo1)
        {
            pSize = cert_addr + RCAR_CERT_INFO_SIZE_OFFSET1;
            *size = mmio_read_32(pSize) * 4U;
            pDestL = cert_addr + RCAR_CERT_INFO_DST_OFFSET1;
            *dest_addr = (uintptr_t)mmio_read_32(pDestL);
        }
        else if (0x0U == certInfo1)
        {
            pSize = cert_addr + RCAR_CERT_INFO_SIZE_OFFSET;
            *size = mmio_read_32(pSize) * 4U;
            pDestL = cert_addr + RCAR_CERT_INFO_DST_OFFSET;
            *dest_addr = (uintptr_t)mmio_read_32(pDestL);
        }
        else  /* if (0x3U == certInfo2) */
        {
            ERROR("Cert is invalid.\n");
            *size = 0x0U;
            *dest_addr = 0x0U;
        }
    }
    else
    {
        pSize = cert_addr + RCAR_CERT_INFO_SIZE_OFFSET;
        *size = mmio_read_32(pSize) * 4U;
        pDestL = cert_addr + RCAR_CERT_INFO_DST_OFFSET;
        *dest_addr = (uintptr_t)mmio_read_32(pDestL);
    }
}
/* End of function get_info_from_cert */

