/*
 * app_main.c
 */

#include <comdef.h>

#include <qsee_log.h>
#include <qsee_heap.h>

#include "app_main.h"

#include "tz_iccc_comdef.h"

#if defined(TEST1_APP)
#define TA_TAG "TA_TEST:"
#elif defined(TEST2_APP)
#define TA_TAG "TA_TEST2:"
#elif defined(TEST3_APP)
#define TA_TAG "TA_TEST3:"
#else
#define TA_TAG "NA: "
#endif

/*
 * Modify the app name to your specific app name
 */
#if defined(TEST1_APP)
char TZ_APP_NAME[] = {"tz_test"};
#elif defined(TEST2_APP)
char TZ_APP_NAME[] = {"tz_test2"};
#elif defined(TEST3_APP)
char TZ_APP_NAME[] = {"tz_test3"};
#else
char TZ_APP_NAME[] = {"na"};
#endif

/*
 * Add any app specific initialization code here
 * QSEE will call this function after secure app is loaded and authenticated
 */
void tz_app_init(void)
{
    qsee_log_set_mask(QSEE_LOG_MSG_ERROR | QSEE_LOG_MSG_DEBUG);
    /*  App specific initialization code*/
    qsee_log(QSEE_LOG_MSG_DEBUG, "%s init", TA_TAG);
}

uint32_t test_saveData(tz_test_generic_payload_t *sendmsg, tz_test_generic_payload_t *respmsg)
{
    uint32_t ret = ICCC_SUCCESS;
    uint32_t type = sendmsg->content.iccc_req.type;
    uint32_t temp = 0xcafebabe;
    uint8_t verified_boot_hash[32] = {0x52, 0x94, 0x31, 0xc2, 0x09, 0xce, 0x01, 0x2a, 0xda, 0xda, 0x58, 0xc4, 0xc9, 0x7f, 0xf2, 0xb4,
                                      0xa2, 0x23, 0x68, 0x90, 0xf7, 0x27, 0x39, 0xb1, 0x8e, 0xd0, 0xda, 0xe3, 0xcb, 0x48, 0x98, 0x2c };
    iccc_kern_status_t iccc_kern_status;
    memcpy(&iccc_kern_status.verified_boot_hash, verified_boot_hash, sizeof(verified_boot_hash));

    switch (type) {
        case SECTIMER_STATUS:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s SECTIMER_STATUS value %d", TA_TAG, temp);
            if (ICCC_SUCCESS == Iccc_SaveData_TA(SECTIMER_STATUS, &temp)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write success for SECTIMER_STATUS", TA_TAG);
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write failure for SECTIMER_STATUS", TA_TAG);
                ret = ICCC_ERROR_WRITE_FAILED;
            }
            break;
        case DMV_STATUS:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s DMV_STATUS value %d", TA_TAG, temp);
            if (ICCC_SUCCESS == Iccc_SaveData_TA(DMV_STATUS, &temp)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write success for DMV_STATUS", TA_TAG);
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write failure for DMV_STATUS", TA_TAG);
                ret = ICCC_ERROR_WRITE_FAILED;
            }
            break;
        case TRUSTBOOT_FLAG:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s TRUSTBOOT_FLAG value %d", TA_TAG, temp);
            if (ICCC_SUCCESS == Iccc_SaveData_TA(TRUSTBOOT_FLAG, &temp)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write success for TRUSTBOOT_FLAG", TA_TAG);
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write failure for TRUSTBOOT_FLAG", TA_TAG);
                ret = ICCC_ERROR_WRITE_FAILED;
            }
            break;
        case VERIFIEDBOOT_HASH:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s VERIFIEDBOOT_HASH value", TA_TAG);
            for (int cnt = 0; cnt < 8; cnt++) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s verified_boot_hash[%d] %#x", TA_TAG, cnt, iccc_kern_status.verified_boot_hash[cnt]);
            }
            if (ICCC_SUCCESS == Iccc_SaveData_TA(VERIFIEDBOOT_HASH, (uint32_t *) iccc_kern_status.verified_boot_hash)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write success for VERIFIEDBOOT_HASH", TA_TAG);
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write failure for VERIFIEDBOOT_HASH", TA_TAG);
                ret = ICCC_ERROR_WRITE_FAILED;
            }
            break;
        default:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s Iccc_SaveData_TA failure", TA_TAG);
            ret = ICCC_UNKNOWN_TYPE;
            break;
    }

    respmsg->content.iccc_rsp.ret = ret;
    return ret;
}

uint32_t test_readData(tz_test_generic_payload_t *sendmsg, tz_test_generic_payload_t *respmsg)
{
    uint32_t ret = ICCC_SUCCESS;
    uint32_t type = sendmsg->content.iccc_req.type;
    uint32_t flag = 1;

    iccc_bl_status_t iccc_bl_status;
    iccc_ta_status_t iccc_ta_status;
    iccc_kern_status_t iccc_kern_status;
    iccc_sys_status_t iccc_sys_status;
    rot_bl_status_t rot_bl_status;
    uint8_t attestation_blob_hash[32] = {0, };
    uint8_t verified_boot_hash[32] = {0, };
    uint8_t verified_boot_key[32] = {0, };
    rot_bl_struct_t rot_bl_struct;

    switch (type) {
        case WARRANTY_BIT:
            if (ICCC_SUCCESS == Iccc_ReadData_TA(WARRANTY_BIT, &flag)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read success for WARRANTY_BIT", TA_TAG);
                if (flag == 0) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s Warranty_bit valid - (%d)", TA_TAG, flag);
                } else {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s Warranty_bit invalid - (%d)", TA_TAG, flag);
                }
                respmsg->content.iccc_rsp.value = flag;
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read failure for WARRANTY_BIT", TA_TAG);
                ret = ICCC_ERROR_READ_FAILED;
            }
            break;
        case TRUSTBOOT_FLAG:
            if (ICCC_SUCCESS == Iccc_ReadData_TA(TRUSTBOOT_FLAG, &flag)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read success for TRUSTBOOT_FLAG", TA_TAG);
                if (flag == 0) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s SVB measurements match (svb1.0) - (%d)", TA_TAG, flag);
                } else {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s SVB measurements mismatch (svb1.0) - (%d)", TA_TAG, flag);
                }
                respmsg->content.iccc_rsp.value = flag;
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read failure for TRUSTBOOT_FLAG", TA_TAG);
                ret = ICCC_ERROR_READ_FAILED;
            }
            break;
        case ATN_BLOB_HASH:
            memset(attestation_blob_hash, 0x00, sizeof(attestation_blob_hash));

            if (ICCC_SUCCESS == Iccc_ReadData_TA(ATN_BLOB_HASH, (uint32_t *) attestation_blob_hash)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read success for ATN_BLOB_HASH", TA_TAG);
                memcpy(&iccc_ta_status.atn_blob_hash, attestation_blob_hash, sizeof(attestation_blob_hash));
                for (int cnt = 0; cnt < 8; cnt++) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s atn_blob_hash[%d] %#x", TA_TAG, cnt, iccc_ta_status.atn_blob_hash[cnt]);
                }
                memcpy(&respmsg->content.iccc_rsp.iccc_ta_status, &iccc_ta_status, sizeof(iccc_ta_status));
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read failure for ATN_BLOB_HASH", TA_TAG);
                ret = ICCC_ERROR_READ_FAILED;
            }
            break;
        case BL_STRUCT:
            memset(&iccc_bl_status, 0x00, sizeof(iccc_bl_status));

            if (ICCC_SUCCESS == Iccc_ReadData_TA(BL_STRUCT, (uint32_t *) &iccc_bl_status)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s rp_ver %#x", TA_TAG, iccc_bl_status.rp_ver);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s kernel_rp %#x", TA_TAG, iccc_bl_status.kernel_rp);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s system_rp %#x", TA_TAG, iccc_bl_status.system_rp);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s test_bit %#x", TA_TAG, iccc_bl_status.test_bit);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s sec_boot %#x", TA_TAG, iccc_bl_status.sec_boot);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s react_lock %#x", TA_TAG, iccc_bl_status.react_lock);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s kiwi_lock %#x", TA_TAG, iccc_bl_status.kiwi_lock);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s frp_lock %#x", TA_TAG, iccc_bl_status.frp_lock);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s cc_mode %#x", TA_TAG, iccc_bl_status.cc_mode);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s mdm_mode %#x", TA_TAG, iccc_bl_status.mdm_mode);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s curr_bin_status %#x", TA_TAG, iccc_bl_status.curr_bin_status);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s afw_value %#x", TA_TAG, iccc_bl_status.afw_value);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s warranty_bit %#x", TA_TAG, iccc_bl_status.warranty_bit);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s kap_status %#x", TA_TAG, iccc_bl_status.kap_status);
                for (int cnt = 0; cnt < 12; cnt++) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s image_status[%d] %#x", TA_TAG, cnt, iccc_bl_status.image_status[cnt]);
                }
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s image_status_bl %#x", TA_TAG, iccc_bl_status.image_status_bl);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s WbHistory %#x", TA_TAG, iccc_bl_status.WbHistory);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ap_serial_0 %#x", TA_TAG, iccc_bl_status.ap_serial_0);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ap_serial_1 %#x", TA_TAG, iccc_bl_status.ap_serial_1);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s em_status %#x", TA_TAG, iccc_bl_status.em_status);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s em_token %#x", TA_TAG, iccc_bl_status.em_token);
                memcpy(&respmsg->content.iccc_rsp.iccc_bl_status, &iccc_bl_status, sizeof(iccc_bl_status));

            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read failure for BL_STRUCT", TA_TAG);
                ret = ICCC_ERROR_READ_FAILED;
            }
            break; 
        case VERIFIEDBOOT_HASH:
            memset(verified_boot_hash, 0x00, sizeof(verified_boot_hash));

            if (ICCC_SUCCESS == Iccc_ReadData_TA(VERIFIEDBOOT_HASH, (uint32_t *) verified_boot_hash)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read success for VERIFIEDBOOT_HASH", TA_TAG);
                memcpy(&iccc_kern_status.verified_boot_hash, verified_boot_hash, sizeof(verified_boot_hash));
                for (int cnt = 0; cnt < 8; cnt++) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s verified_boot_hash[%d] %#x", TA_TAG, cnt, iccc_kern_status.verified_boot_hash[cnt]);
                }
                memcpy(&respmsg->content.iccc_rsp.iccc_kern_status, &iccc_kern_status, sizeof(iccc_kern_status));
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read failure for VERIFIEDBOOT_HASH", TA_TAG);
                ret = ICCC_ERROR_READ_FAILED;
            }
            break;
        case ROT_STRUCT:
            memset(&rot_bl_struct, 0x00, sizeof(rot_bl_struct));

            if (ICCC_SUCCESS == Iccc_ReadData_TA(ROT_STRUCT, (uint32_t *) &rot_bl_struct)) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read success for ROT_STRUCT", TA_TAG);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s verified_boot_state %#x", TA_TAG, rot_bl_struct.verified_boot_state);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s device_locked %#x", TA_TAG, rot_bl_struct.device_locked);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s os_version %#x", TA_TAG, rot_bl_struct.os_version);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s patch_month_year %#x", TA_TAG, rot_bl_struct.patch_month_year);
                for (int cnt = 0; cnt < 8; cnt++) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s verified_boot_key[%d] %#x", TA_TAG, cnt, rot_bl_struct.verified_boot_key[cnt]);
                }
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s boot_patch_level %#x", TA_TAG, rot_bl_struct.boot_patch_level);
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s vendor_patch_level %#x", TA_TAG, rot_bl_struct.vendor_patch_level);
                memcpy(&respmsg->content.iccc_rsp.rot_bl_status, &rot_bl_struct, sizeof(rot_bl_struct));

            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read failure for ROT_STRUCT", TA_TAG);
                ret = ICCC_ERROR_READ_FAILED;
            }
            break;
        case 0xFFFFFFFF: // All Flags
            memset(&iccc_bl_status, 0x00, sizeof(iccc_bl_status));
            memset(&iccc_ta_status, 0x00, sizeof(iccc_ta_status));
            memset(&iccc_kern_status, 0x00, sizeof(iccc_kern_status));
            memset(&iccc_sys_status, 0x00, sizeof(iccc_sys_status));
            memset(&rot_bl_status, 0x00, sizeof(rot_bl_status));
            memset(attestation_blob_hash, 0x00, sizeof(attestation_blob_hash));
            memset(verified_boot_hash, 0x00, sizeof(verified_boot_hash));
            memset(verified_boot_key, 0x00, sizeof(verified_boot_key));

            Iccc_ReadData_TA(RP_VER, &flag);
            iccc_bl_status.rp_ver = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s rp_ver %#x", TA_TAG, iccc_bl_status.rp_ver);
            Iccc_ReadData_TA(KERNEL_RP, &flag);
            iccc_bl_status.kernel_rp = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s kernel_rp %#x", TA_TAG, iccc_bl_status.kernel_rp);
            Iccc_ReadData_TA(SYSTEM_RP, &flag);
            iccc_bl_status.system_rp = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s system_rp %#x", TA_TAG, iccc_bl_status.system_rp);
            Iccc_ReadData_TA(TEST_BIT, &flag);
            iccc_bl_status.test_bit = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s test_bit %#x", TA_TAG, iccc_bl_status.test_bit);
            Iccc_ReadData_TA(SEC_BOOT, &flag);
            iccc_bl_status.sec_boot = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s sec_boot %#x", TA_TAG, iccc_bl_status.sec_boot);
            Iccc_ReadData_TA(REACT_LOCK, &flag);
            iccc_bl_status.react_lock = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s react_lock %#x", TA_TAG, iccc_bl_status.react_lock);
            Iccc_ReadData_TA(KIWI_LOCK, &flag);
            iccc_bl_status.kiwi_lock = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s kiwi_lock %#x", TA_TAG, iccc_bl_status.kiwi_lock);
            Iccc_ReadData_TA(FRP_LOCK, &flag);
            iccc_bl_status.frp_lock = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s frp_lock %#x", TA_TAG, iccc_bl_status.frp_lock);
            Iccc_ReadData_TA(CC_MODE, &flag);
            iccc_bl_status.cc_mode = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s cc_mode %#x", TA_TAG, iccc_bl_status.cc_mode);
            Iccc_ReadData_TA(MDM_MODE, &flag);
            iccc_bl_status.mdm_mode = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s mdm_mode %#x", TA_TAG, iccc_bl_status.mdm_mode);
            Iccc_ReadData_TA(CURR_BIN_STATUS, &flag);
            iccc_bl_status.curr_bin_status = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s curr_bin_status %#x", TA_TAG, iccc_bl_status.curr_bin_status);
            Iccc_ReadData_TA(AFW_VALUE, &flag);
            iccc_bl_status.afw_value = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s afw_value %#x", TA_TAG, iccc_bl_status.afw_value);
            Iccc_ReadData_TA(WARRANTY_BIT, &flag);
            iccc_bl_status.warranty_bit = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s warranty_bit %#x", TA_TAG, iccc_bl_status.warranty_bit);
            Iccc_ReadData_TA(KAP_STATUS, &flag);
            iccc_bl_status.kap_status = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s kap_status %#x", TA_TAG, iccc_bl_status.kap_status);
            for (int cnt = 0; cnt < 12; cnt++) {
                Iccc_ReadData_TA(IMAGE_STATUS1+cnt, &flag);
                iccc_bl_status.image_status[cnt] = flag;
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s image_status[%d] %#x", TA_TAG, cnt, iccc_bl_status.image_status[cnt]);
            }
            Iccc_ReadData_TA(IMAGE_STATUS_BL, &flag);
            iccc_bl_status.image_status_bl = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s image_status_bl %#x", TA_TAG, iccc_bl_status.image_status_bl);
            Iccc_ReadData_TA(WB_HISTORY, &flag);
            iccc_bl_status.WbHistory = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s WbHistory %#x", TA_TAG, iccc_bl_status.WbHistory);
            Iccc_ReadData_TA(AP_SERIAL_0, &flag);
            iccc_bl_status.ap_serial_0 = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s ap_serial_0 %#x", TA_TAG, iccc_bl_status.ap_serial_0);
            Iccc_ReadData_TA(AP_SERIAL_1, &flag);
            iccc_bl_status.ap_serial_1 = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s ap_serial_1 %#x", TA_TAG, iccc_bl_status.ap_serial_1);
            Iccc_ReadData_TA(EM_STATUS, &flag);
            iccc_bl_status.em_status = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s em_status %#x", TA_TAG, iccc_bl_status.em_status);
            Iccc_ReadData_TA(EM_TOKEN, &flag);
            iccc_bl_status.em_token = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s em_token %#x", TA_TAG, iccc_bl_status.em_token);
            Iccc_ReadData_TA(SECTIMER_BASE, &flag);
            iccc_ta_status.sectimer_base = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s sectimer_base %#x", TA_TAG, iccc_ta_status.sectimer_base);
            Iccc_ReadData_TA(SECTIMER_FLAG, &flag);
            iccc_ta_status.sectimer_flag = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s sectimer_flag %#x", TA_TAG, iccc_ta_status.sectimer_flag);
            Iccc_ReadData_TA(SECTIMER_STATUS, &flag);
            iccc_ta_status.sectimer_status = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s sectimer_status %#x", TA_TAG, iccc_ta_status.sectimer_status);
            Iccc_ReadData_TA(ATN_BLOB_HASH, (uint32_t *) attestation_blob_hash);
            memcpy(&iccc_ta_status.atn_blob_hash, attestation_blob_hash, sizeof(attestation_blob_hash));
            for (int cnt = 0; cnt < 8; cnt++) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s atn_blob_hash[%d] %#x", TA_TAG, cnt, iccc_ta_status.atn_blob_hash[cnt]);
            }
            Iccc_ReadData_TA(DMV_STATUS, &flag);
            iccc_kern_status.dmv_status = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s dmv_status %#x", TA_TAG, iccc_kern_status.dmv_status);
            Iccc_ReadData_TA(VERIFIEDBOOT_HASH, (uint32_t *) verified_boot_hash);
            memcpy(&iccc_kern_status.verified_boot_hash, verified_boot_hash, sizeof(verified_boot_hash));
            for (int cnt = 0; cnt < 8; cnt++) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s verified_boot_hash[%d] %#x", TA_TAG, cnt, iccc_kern_status.verified_boot_hash[cnt]);
            }
            Iccc_ReadData_TA(TRUSTBOOT_FLAG, &flag);
            iccc_sys_status.trustboot_flag = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s trustboot_flag %#x", TA_TAG, iccc_sys_status.trustboot_flag);
            Iccc_ReadData_TA(TIMA_VERSION_FLAG, &flag);
            iccc_sys_status.tima_version_flag = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s tima_version_flag %#x", TA_TAG, iccc_sys_status.tima_version_flag);

            Iccc_ReadData_TA(VERIFIEDBOOTSTATE_FLAG, &flag);
            rot_bl_status.verified_boot_state = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s verified_boot_state %#x", TA_TAG, rot_bl_status.verified_boot_state);
            Iccc_ReadData_TA(DEVICELOCK_FLAG, &flag);
            rot_bl_status.device_locked = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s device_locked %#x", TA_TAG, rot_bl_status.device_locked);
            Iccc_ReadData_TA(OSVERSION_FLAG, &flag);
            rot_bl_status.os_version = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s os_version %#x", TA_TAG, rot_bl_status.os_version);
            Iccc_ReadData_TA(PATCHMONTHYEAR_FLAG, &flag);
            rot_bl_status.patch_month_year = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s patch_month_year %#x", TA_TAG, rot_bl_status.patch_month_year);
            Iccc_ReadData_TA(VERIFIEDBOOTKEY_FLAG, (uint32_t *) verified_boot_key);
            memcpy(&rot_bl_status.verified_boot_key, verified_boot_key, sizeof(verified_boot_key));
            for (int cnt = 0; cnt < 8; cnt++) {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s verified_boot_key[%d] %#x", TA_TAG, cnt, rot_bl_status.verified_boot_key[cnt]);
            }
            Iccc_ReadData_TA(BOOTPATCHLEVEL_FLAG, &flag);
            rot_bl_status.boot_patch_level = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s boot_patch_level %#x", TA_TAG, rot_bl_status.boot_patch_level);
            Iccc_ReadData_TA(VENDORPATCHLEVEL_FLAG, &flag);
            rot_bl_status.vendor_patch_level = flag;
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s vendor_patch_level %#x", TA_TAG, rot_bl_status.vendor_patch_level);

            memcpy(&respmsg->content.iccc_rsp.iccc_bl_status, &iccc_bl_status, sizeof(iccc_bl_status));
            memcpy(&respmsg->content.iccc_rsp.iccc_ta_status, &iccc_ta_status, sizeof(iccc_ta_status));
            memcpy(&respmsg->content.iccc_rsp.iccc_kern_status, &iccc_kern_status, sizeof(iccc_kern_status));
            memcpy(&respmsg->content.iccc_rsp.iccc_sys_status, &iccc_sys_status, sizeof(iccc_sys_status));
            memcpy(&respmsg->content.iccc_rsp.rot_bl_status, &rot_bl_status, sizeof(rot_bl_status));

            break;
        default:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s Iccc_ReadData_TA failure with unknown type", TA_TAG);
            ret = ICCC_UNKNOWN_TYPE;
            break;
    }

    respmsg->content.iccc_rsp.ret = ret;
    return ret;
}

uint32_t test_getDeviceStatus(tz_test_generic_payload_t *sendmsg, tz_test_generic_payload_t *respmsg)
{
    uint32_t ret = ICCC_SUCCESS;
    uint32_t type = sendmsg->content.iccc_req.type;
    uint8_t resp_msg_buf[ICCC_STATUS_MAX_RESULT_MESSAGE] = {0, };
    uint32_t resp_msg_len = 0;
    uint32_t result_code = 1;

    switch (type) {
        case ICCC_STATUS_COMP_TYPE_SOFT_INTEGRITY:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC_STATUS_COMP_TYPE_SOFT_INTEGRITY", TA_TAG);
            if (ICCC_SUCCESS == Iccc_DeviceStatus_TA(type, resp_msg_buf, sizeof(resp_msg_buf), &resp_msg_len, &result_code)) {
                if (result_code == 0) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s Device integrity check (%d) is success - (%s - %d), (0x%08x)", TA_TAG, type, resp_msg_buf, resp_msg_len, result_code);
                } else {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s Device integrity check (%d) is failed - (%s - %d), (0x%08x)", TA_TAG, type, resp_msg_buf, resp_msg_len, result_code);
                }
                respmsg->content.iccc_rsp.result_code = result_code;
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC integrity check failure with Iccc_DeviceStatus_TA", TA_TAG);
                ret = ICCC_ERROR_DEVICE_STATUS_FAILED;
            }
            break;
        case ICCC_STATUS_COMP_TYPE_HARD_INTEGRITY:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC_STATUS_COMP_TYPE_HARD_INTEGRITY", TA_TAG);
            if (ICCC_SUCCESS == Iccc_DeviceStatus_TA(type, resp_msg_buf, sizeof(resp_msg_buf), &resp_msg_len, &result_code)) {
                if (result_code == 0) {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s Device integrity check (%d) is success - (%s - %d), (0x%08x)", TA_TAG, type, resp_msg_buf, resp_msg_len, result_code);
                } else {
                    qsee_log(QSEE_LOG_MSG_DEBUG, "%s Device integrity check (%d) is failed - (%s - %d), (0x%08x)", TA_TAG, type, resp_msg_buf, resp_msg_len, result_code);
                }
                respmsg->content.iccc_rsp.result_code = result_code;
            } else {
                qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC integrity check failure with Iccc_DeviceStatus_TA", TA_TAG);
                ret = ICCC_ERROR_DEVICE_STATUS_FAILED;
            }
            break;
        default:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s Iccc_DeviceStatus_TA failure with unknown type", TA_TAG);
            ret = ICCC_UNKNOWN_TYPE;
            break;
    }

    respmsg->content.iccc_rsp.ret = ret;
    return ret;
}

uint32_t test_negative(tz_test_generic_payload_t *sendmsg, tz_test_generic_payload_t *respmsg)
{
    uint32_t ret = ICCC_SUCCESS;
    uint32_t ng_flag = 0;
    uint32_t value = 0;

    if (ICCC_SUCCESS == Iccc_ReadData_TA(0xFFFFFFFF, &ng_flag)) {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read success with unsupported flag", TA_TAG);
    } else {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC read failure with unsupported flag", TA_TAG);
        ret = ICCC_ERROR_READ_FAILED;
    }

    if (ICCC_SUCCESS == Iccc_SaveData_TA(0xFFFFFFFF, &value)) {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write success for unsupported flag", TA_TAG);
    } else {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC write failure for unsupported flag", TA_TAG);
        ret = ICCC_ERROR_WRITE_FAILED;
    }

    uint32_t type = ICCC_STATUS_COMP_TYPE_DIR_INTEGRITY;
    uint8_t resp_msg_buf[ICCC_STATUS_MAX_RESULT_MESSAGE] = {0, };
    uint32_t resp_msg_len = 0;
    uint32_t result_code = 1;
    if (ICCC_SUCCESS == Iccc_DeviceStatus_TA(type, resp_msg_buf, sizeof(resp_msg_buf), &resp_msg_len, &result_code)) {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC integrity check success with unsupported flag", TA_TAG);
    } else {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s ICCC integrity check failure with unsupported flag", TA_TAG);
        ret = ICCC_ERROR_DEVICE_STATUS_FAILED;
    }

    respmsg->content.iccc_rsp.ret = ret;
    return ret;
}

/*
 * App specific command handler
 * App executes code based on input command
 */
void tz_app_cmd_handler(void *cmd, uint32 cmdlen, void *rsp, uint32 rsplen)
{

    uint32_t ret = ICCC_SUCCESS;
    tciMessage_t *sendmsg = NULL;
    tciMessage_t *respmsg = NULL;
    uint32_t cmd_id;

    if (cmd == NULL || cmdlen < sizeof(tciMessage_t) || rsp == NULL || rsplen < sizeof(tciMessage_t)
        || ((cmd < rsp) && ((void *)((uint8_t *)cmd + cmdlen) > rsp))
        || ((rsp < cmd) && ((void *)((uint8_t *)rsp + rsplen) > cmd))) {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s invalid input buffer", TA_TAG);
        return;
    }

    /* Local buffer to prevent Race Condition */
    sendmsg = (tciMessage_t*)qsee_malloc(sizeof(tciMessage_t));
    respmsg = (tciMessage_t*)qsee_malloc(sizeof(tciMessage_t));
    if (!sendmsg) {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s sendmsg pointer is NULL", TA_TAG);
        goto exit;
    }
    memset((void *)sendmsg, 0, sizeof(tciMessage_t));
    memcpy((void *)sendmsg, cmd, sizeof(tciMessage_t));

    if (!respmsg) {
        qsee_log(QSEE_LOG_MSG_DEBUG, "%s respmsg pointer is NULL", TA_TAG);
        goto exit;
    }
    memset((void *)respmsg, 0, sizeof(tciMessage_t));
    memcpy((void *)respmsg, rsp, sizeof(tciMessage_t));

    cmd_id = sendmsg->header.id;
    qsee_log(QSEE_LOG_MSG_DEBUG, "%s tz_app_cmd_handler: cmd_id: %d", TA_TAG, cmd_id);

    /* Process command message */
    switch (cmd_id) {
        case CMD_ICCC_TEST_SAVEDATA:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s CMD_ICCC_TEST_SAVEDATA", TA_TAG);
            ret = test_saveData(&sendmsg->payload.generic, &respmsg->payload.generic);
            break;
        case CMD_ICCC_TEST_READDATA:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s CMD_ICCC_TEST_READDATA", TA_TAG);
            ret = test_readData(&sendmsg->payload.generic, &respmsg->payload.generic);
            break;
        case CMD_ICCC_TEST_GETDEVISESTAT:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s CMD_ICCC_TEST_GETDEVISESTAT", TA_TAG);
            ret = test_getDeviceStatus(&sendmsg->payload.generic, &respmsg->payload.generic);
            break;
        case CMD_ICCC_TEST_NEGATIVE:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s CMD_ICCC_TEST_NEGATIVE", TA_TAG);
            ret = test_negative(&sendmsg->payload.generic, &respmsg->payload.generic);
            break;
        default:
            qsee_log(QSEE_LOG_MSG_DEBUG, "%s received unknown command: %d!", TA_TAG, cmd_id);
            ret = ICCC_UNKNOWN_CMD;
            respmsg->payload.generic.content.iccc_rsp.ret = ret;
            break;
    }

    respmsg->header.id = RSP_ID(cmd_id);
    respmsg->header.status = ret;

exit:
    if (sendmsg) {
        memcpy(cmd, (void *)sendmsg, sizeof(tciMessage_t));
        qsee_free(sendmsg);
    }

    if (respmsg) {
        memcpy(rsp, (void *)respmsg, sizeof(tciMessage_t));
        qsee_free(respmsg);
    }

    qsee_log(QSEE_LOG_MSG_DEBUG, "%s tz_app_cmd_handler: ret: %d", TA_TAG, ret);
}

/*
 * App specific shutdown
 * App will be given a chance to shutdown gracefully
 */
void tz_app_shutdown(void)
{
    /* App specific shutdown code*/
    qsee_log(QSEE_LOG_MSG_DEBUG, "%s shutdown", TA_TAG);
    return;
}
