/*
 * app_bootloader.c
 */

#include <comdef.h>

#include <qsee_oem_buffer.h> // qsee_write_oem_buffer

#include "app_main.h"
#include "app_core.h"
#include "app_initData.h"
#include "app_saveData.h"
#include "app_readData.h"
#include "app_bootloader.h"

#include "tz_iccc_comdef.h"

int tzbsp_oem_write_iccc_bl_info(iccc_bl_status_t *bl_secure_info)
{
    int ret = ICCC_FAILURE;
    uint32_t dmv_value = 0x0;
#if DEBUG_ICCC
    uint32_t debug_temp = 0;
    uint32_t cnt = 0;
#endif

    ICCC_LOG("TZ_ICCC: %s:", __func__);

    /* initialize all the ICCC memory to 0xFFFFFFFF (unsupported or uninitialized) */
    ret = Iccc_Core_InitData_TA(0xFF);
    if (ret) {
        ICCC_LOG("TZ_ICCC: %s: Iccc_Core_InitData_TA() failed!!", __func__);
        return ret;
    }

    /* initialize DMV_STATUS to 0 - success by befault */
    ret = Iccc_Core_SaveData_TA(DMV_STATUS, (uint32_t *) &dmv_value);
    if (ret) {
        ICCC_LOG("TZ_ICCC: %s: Iccc_Core_SaveData_TA() failed! type:%#x, ret:%d", __func__, DMV_STATUS, ret);
        return ret;
    }

    if (bl_secure_info->header.used_size != sizeof(iccc_bl_status_t)) {
        ICCC_LOG("TZ_ICCC: %s: BL struct size mismatch detected! expected:%d but actual:%d!",
                           __func__, sizeof(iccc_bl_status_t), bl_secure_info->header.used_size);
        return ret;
    }

    ret = Iccc_Core_SaveData_TA(BL_STRUCT, (uint32_t *) bl_secure_info);
    if (ret) {
        ICCC_LOG("TZ_ICCC: %s: Iccc_Core_SaveData_TA() failed! type:%#x, ret:%d", __func__, BL_STRUCT, ret);
        return ret;
    }

#if DEBUG_ICCC
    memset(bl_secure_info, 0, sizeof(iccc_bl_status_t));

    Iccc_Core_ReadData_TA(RP_VER, &debug_temp);
    bl_secure_info->rp_ver = debug_temp;
    Iccc_Core_ReadData_TA(KERNEL_RP, &debug_temp);
    bl_secure_info->kernel_rp = debug_temp;
    Iccc_Core_ReadData_TA(SYSTEM_RP, &debug_temp);
    bl_secure_info->system_rp = debug_temp;
    Iccc_Core_ReadData_TA(TEST_BIT, &debug_temp);
    bl_secure_info->test_bit = debug_temp;
    Iccc_Core_ReadData_TA(SEC_BOOT, &debug_temp);
    bl_secure_info->sec_boot = debug_temp;
    Iccc_Core_ReadData_TA(REACT_LOCK, &debug_temp);
    bl_secure_info->react_lock = debug_temp;
    Iccc_Core_ReadData_TA(KIWI_LOCK, &debug_temp);
    bl_secure_info->kiwi_lock = debug_temp;
    Iccc_Core_ReadData_TA(FRP_LOCK, &debug_temp);
    bl_secure_info->frp_lock = debug_temp;
    Iccc_Core_ReadData_TA(CC_MODE, &debug_temp);
    bl_secure_info->cc_mode = debug_temp;
    Iccc_Core_ReadData_TA(MDM_MODE, &debug_temp);
    bl_secure_info->mdm_mode = debug_temp;
    Iccc_Core_ReadData_TA(CURR_BIN_STATUS, &debug_temp);
    bl_secure_info->curr_bin_status = debug_temp;
    Iccc_Core_ReadData_TA(AFW_VALUE, &debug_temp);
    bl_secure_info->afw_value = debug_temp;
    Iccc_Core_ReadData_TA(WARRANTY_BIT, &debug_temp);
    bl_secure_info->warranty_bit = debug_temp;
    Iccc_Core_ReadData_TA(KAP_STATUS, &debug_temp);
    bl_secure_info->kap_status = debug_temp;
    for (cnt = 0; cnt < MAX_IMAGES; cnt++) {
        Iccc_Core_ReadData_TA(IMAGE_STATUS1+cnt, (uint32 *) &debug_temp);
        bl_secure_info->image_status[cnt] = debug_temp;
    }
    Iccc_Core_ReadData_TA(IMAGE_STATUS_BL, &debug_temp);
    bl_secure_info->image_status_bl = debug_temp;
    Iccc_Core_ReadData_TA(WB_HISTORY, &debug_temp);
    bl_secure_info->WbHistory = debug_temp;
    Iccc_Core_ReadData_TA(AP_SERIAL_0, &debug_temp);
    bl_secure_info->ap_serial_0 = debug_temp;
    Iccc_Core_ReadData_TA(AP_SERIAL_1, &debug_temp);
    bl_secure_info->ap_serial_1 = debug_temp;
    Iccc_Core_ReadData_TA(EM_STATUS, &debug_temp);
    bl_secure_info->em_status = debug_temp;
    Iccc_Core_ReadData_TA(EM_TOKEN, &debug_temp);
    bl_secure_info->em_token = debug_temp;

    ICCC_LOG("rp_ver %#x", bl_secure_info->rp_ver);
    ICCC_LOG("kernel_rp %#x", bl_secure_info->kernel_rp);
    ICCC_LOG("system_rp %#x", bl_secure_info->system_rp);
    ICCC_LOG("test_bit %#x", bl_secure_info->test_bit);
    ICCC_LOG("sec_boot %#x",bl_secure_info->sec_boot);
    ICCC_LOG("react_lock %#x", bl_secure_info->react_lock);
    ICCC_LOG("kiwi_lock %#x", bl_secure_info->kiwi_lock);
    ICCC_LOG("frp_lock %#x", bl_secure_info->frp_lock);
    ICCC_LOG("cc_mode %#x", bl_secure_info->cc_mode);
    ICCC_LOG("mdm_mode %#x", bl_secure_info->mdm_mode);
    ICCC_LOG("curr_bin_status %#x", bl_secure_info->curr_bin_status);
    ICCC_LOG("afw_value %#x", bl_secure_info->afw_value);
    ICCC_LOG("warranty_bit %#x", bl_secure_info->warranty_bit);
    ICCC_LOG("kap_status %#x", bl_secure_info->kap_status);
    for (cnt = 0; cnt < MAX_IMAGES; cnt++) {
        ICCC_LOG("image_status[%d] %#x", cnt+1, bl_secure_info->image_status[cnt]);
    }
    ICCC_LOG("image_status_bl %#x", bl_secure_info->image_status_bl);
    ICCC_LOG("wb_history %c(%#x)", bl_secure_info->WbHistory, bl_secure_info->WbHistory);
    ICCC_LOG("ap_serial_0 %#x", bl_secure_info->ap_serial_0);
    ICCC_LOG("ap_serial_1 %#x", bl_secure_info->ap_serial_1);
    ICCC_LOG("em_status %#x", bl_secure_info->em_status);
    ICCC_LOG("em_token %#x", bl_secure_info->em_token);
#endif

    return ret;
}

int tzbsp_oem_write_iccc_rot_bl_info(rot_bl_status_t *bl_secure_info_rot)
{
    int ret = ICCC_FAILURE;
#if DEBUG_ICCC
    uint32_t debug_temp = 0;
#endif

    ICCC_LOG("TZ_ICCC: %s:", __func__);

    if (bl_secure_info_rot->header.used_size != sizeof(rot_bl_status_t)) {
        ICCC_LOG("TZ_ICCC: %s: ROT struct size mismatch detected! expected:%d but actual:%d!",
                           __func__, sizeof(rot_bl_status_t), bl_secure_info_rot->header.used_size);
        return ret;
    }

    ret = Iccc_Core_SaveData_TA(ROT_STRUCT, (uint32_t *) bl_secure_info_rot);
    if (ret) {
        ICCC_LOG("TZ_ICCC: %s: Iccc_Core_SaveData_TA() failed! type:%#x, ret:%d", __func__, ROT_STRUCT, ret);
        return ret;
    }

#if DEBUG_ICCC
    memset(bl_secure_info_rot, 0, sizeof(rot_bl_status_t));

    Iccc_Core_ReadData_TA(VERIFIEDBOOTSTATE_FLAG, &debug_temp);
    bl_secure_info_rot->verified_boot_state = debug_temp;
    Iccc_Core_ReadData_TA(DEVICELOCK_FLAG, &debug_temp);
    bl_secure_info_rot->device_locked = debug_temp;
    Iccc_Core_ReadData_TA(OSVERSION_FLAG, &debug_temp);
    bl_secure_info_rot->os_version = debug_temp;
    Iccc_Core_ReadData_TA(PATCHMONTHYEAR_FLAG, &debug_temp);
    bl_secure_info_rot->patch_month_year = debug_temp;
    Iccc_Core_ReadData_TA(BOOTPATCHLEVEL_FLAG, &debug_temp);
    bl_secure_info_rot->boot_patch_level = debug_temp;
    Iccc_Core_ReadData_TA(VENDORPATCHLEVEL_FLAG, &debug_temp);
    bl_secure_info_rot->vendor_patch_level = debug_temp;

    ICCC_LOG("verified_boot_state %#x", bl_secure_info_rot->verified_boot_state);
    ICCC_LOG("device_locked %#x", bl_secure_info_rot->device_locked);
    ICCC_LOG("os_version %#x", bl_secure_info_rot->os_version);
    ICCC_LOG("patch_month_year %#x", bl_secure_info_rot->patch_month_year);
    ICCC_LOG("system_patch_level %#x", bl_secure_info_rot->boot_patch_level);
    ICCC_LOG("vendor_patch_level %#x", bl_secure_info_rot->vendor_patch_level);
#endif

    return ret;
}

int tzbsp_oem_write_iccc_svb_bl_info(iccc_sys_status_t *bl_secure_info_sys)
{
    int ret = ICCC_FAILURE;
    char svb_magic[] = "SVB1.0";
    int svb_magic_len = sizeof(svb_magic);
    uint32_t trustboot_value = bl_secure_info_sys->trustboot_flag;
#if DEBUG_ICCC
    uint32_t debug_temp = 0;
#endif

    ICCC_LOG("TZ_ICCC: %s:", __func__);

    if (bl_secure_info_sys->header.used_size != sizeof(iccc_sys_status_t)) {
        ICCC_LOG("TZ_ICCC: %s: SYS struct size mismatch detected! expected:%d but actual:%d!",
                           __func__, sizeof(iccc_sys_status_t), bl_secure_info_sys->header.used_size);
        return ret;
    }

    ret = Iccc_Core_SaveData_TA(TRUSTBOOT_FLAG, (uint32_t *) &trustboot_value);
    if (ret) {
        ICCC_LOG("TZ_ICCC: %s: Iccc_Core_SaveData_TA() failed! type:%#x, ret:%d", __func__, TRUSTBOOT_FLAG, ret);
        return ret;
    }

    ret = qsee_write_oem_buffer(ICCC_SVB_MAGIC_OFFSET, (void *)svb_magic, svb_magic_len);
    if (ret) {
        ICCC_LOG("TZ_ICCC: %s: SVB_MAGIC_OFFSET write fail", __func__);
        return ret;
    }

#if DEBUG_ICCC
    Iccc_Core_ReadData_TA(TRUSTBOOT_FLAG, &debug_temp);
    ICCC_LOG("trusted_boot (SVB1.0) %#x", debug_temp);
#endif

    return ret;
}

int tzbsp_oem_write_iccc_kern_info(iccc_kern_status_t *bl_secure_info_kern)
{
    int ret = ICCC_FAILURE;
#if DEBUG_ICCC
    uint32_t debug_temp[8] = {0};
    uint32_t cnt = 0;
#endif

    ICCC_LOG("TZ_ICCC: %s:", __func__);

    if (bl_secure_info_kern->header.used_size != sizeof(iccc_kern_status_t)) {
        ICCC_LOG("TZ_ICCC: %s: KERN struct size mismatch detected! expected:%d but actual:%d!",
                           __func__, sizeof(iccc_kern_status_t), bl_secure_info_kern->header.used_size);
        return ret;
    }

    ret = Iccc_Core_SaveData_TA(VERIFIEDBOOT_HASH, (uint32_t *) bl_secure_info_kern->verified_boot_hash);
    if (ret) {
        ICCC_LOG("TZ_ICCC: %s: Iccc_Core_SaveData_TA() failed! type:%#x, ret:%d", __func__, TRUSTBOOT_FLAG, ret);
        return ret;
    }

#if DEBUG_ICCC
    Iccc_Core_ReadData_TA(VERIFIEDBOOT_HASH, (uint32_t *)&debug_temp);
    for (cnt = 0; cnt < 8; cnt++) {
        ICCC_LOG("verified_boot_hash[%d] %#x", cnt+1, debug_temp[cnt]);
    }
#endif

    return ret;
}
