#ifndef __APP_GRDM_H
#define __APP_GRDM_H

#include <grdm_common.h>
#include <grdm_fw.h>
#include <sha.h>

//#define GRDM_DEBUG_DATA
//#define DEBUG_APDU // for debug - need to check star_apdu.c

#define SUPPORT_FW_UPGRADE
//#define GRDM_CHECK_FACTORY
//#define GRDM_RESET
// temporary feature, this will be removed when rel branch out
#define SUPPORT_SET_RPMB_SEED

#define UUID_SIZE 64
#define SALT_SIZE 256
#define AUTH_KEY_SIZE 32
#define NUM_IMAGE_STATUS 12
#ifdef SUPPORT_FW_UPGRADE
//#define GRDM_FW_IMG_HEADER_SIZE	256
//#define GRDM_FW_START_DATA_SIZE	300
//#define GRDM_FW_SECTOR_SIZE	GRDM_SECTOR_SIZE
#endif

#define GRDM_BL_RPMB_NO_ERROR               0x00000000
#define GRDM_BL_RPMB_FAILURE                0xf0000010
#define GRDM_BL_RPMB_NOT_INITIALIZED        0xf0000011
#define GRDM_BL_RPMB_ALREADY_INITIALIZED    0xf0000012
#define GRDM_BL_MAGIC_FAILURE               0xf0000013
#define GRDM_BL_RPMB_INIT_FAILED            0xf0000014
#define GRDM_BL_RPMB_READ_FAILED            0xf0000015
#define GRDM_BL_RPMB_WRITE_FAILED           0xf0000016
#define GRDM_BL_RPMB_NOT_PROVISIONED        0xf0000017

typedef enum _grdm_fw_state_t {
  Grdm_FW_Image_Header,
  Grdm_FW_Start,
  Grdm_FW_Update,
  Grdm_FW_Finish,
  GRDM_FW_STATE_MAX = (int)0xFFFFFFFFULL,
} grdm_fw_state_t;

typedef struct
{
	uint8_t  devInfoBuff[SHA256_DIGEST_LENGTH];
    uint32_t ap_serial_0;
    uint32_t magic;
    uint32_t is_fused;
} __attribute__ ((packed)) grdm_session_info_t;

typedef struct {
    uint32_t rp_ver;                    // possible values : 0,1,2..
    uint32_t kernel_rp;                 // possible values : 0,1,2..0xFFFFFFFF (0,1,2 ... : kernel RP version , 0XFFFFFFFF :feature not present)
    uint32_t system_rp;                 // possible values : 0,1,2..0xFFFFFFFF (0,1,2 ... : system RP version , 0XFFFFFFFF :feature not present)
    uint32_t test_bit;                  // possible values : 0,1 (0: not blown , 1:blown)
    uint32_t sec_boot;                  // possible values : 0,1 (0:disable , 1:enable)
    uint32_t react_lock;                // possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present)
    uint32_t kiwi_lock;                 // possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present)
    uint32_t frp_lock;                  // possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present)
    uint32_t cc_mode;                   // possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present)
    uint32_t mdm_mode;                  // possible values : 0,1,0xFFFFFFFF(0:off , 1:on , 0xFFFFFFFF:feature not present)
    uint32_t curr_bin_status;           // possible values : 0,1 (0:official , 1:custom)
    uint32_t afw_value;                 // possible values : 0,1,0xFFFFFFFF (0:off , 1:on, 0xFFFFFFFF: Unknown/Uninitialized)
    uint32_t warranty_bit;              // possible values : 0,1 (0: not blown , 1:blown)
    uint32_t kap_status;                // possible values : 0,1,3,0xFFFFFFFF(0:KAP OFF , 1:KAP ON - No tamper , 3:Violation(RKP and/or DMVerity says device is tampered) , 0xFFFFFFFF:feature not present)
    uint32_t image_status[NUM_IMAGE_STATUS];  // possible values : 0,1,0xFF (0:official , 1:custom , 0xFFFFFFFF : FRP not present so cannot get image status)
    uint32_t image_status_bl;
    uint32_t WarrantyBitHistory;
    uint32_t ap_serial_0;
    uint32_t ap_serial_1;
    uint32_t em_status;
    uint32_t em_token;
    uint32_t trustboot_flag;               //132B
} __attribute__ ((packed)) grdm_bl_status_t;


typedef struct
{
	uint32_t verified_boot_state;
	uint32_t device_locked;
	uint32_t os_version;
	uint32_t patch_month_year;
	uint32_t verified_boot_key[8];
	uint32_t boot_patch_level;
	uint32_t vendor_patch_level;
	uint32_t verified_boot_hash[8];
} __attribute__ ((packed)) grdm_rot_status_t;

typedef struct
{
    grdm_bl_status_t grdm_secure_info_bl;
    grdm_rot_status_t grdm_secure_info_rot;
} grdm_bl_rot_data_t;


typedef struct
{
	uint32_t magic;
	uint32_t seed_value;
	uint8_t fw_version[8];
    uint32_t is_fused;
} grdm_rpmb_data_t;

#ifdef SUPPORT_FW_UPGRADE
typedef struct
{
	grdm_fw_state_t fw_state;
	uint8_t fw_data[GRDM_SECTOR_SIZE];
} __attribute__ ((packed)) grdm_fw_data_t;

typedef struct
{
    uint32_t next_size;
	uint32_t fw_start_addr;
	uint32_t target_size;
	uint8_t fw_version[8];
	uint8_t partition;
} grdm_fw_info_t;
#endif

typedef struct blgrd_send_cmd{
	uint32_t cmd_id;
	grdm_session_info_t grdm_session_info;
	union {
        grdm_bl_rot_data_t bl_rot_data;
		uint32_t seed_id;
#ifdef SUPPORT_FW_UPGRADE
		grdm_fw_data_t grdm_fw_data;
#endif
	} data;
} blgrd_send_cmd_t;


typedef struct blgrd_send_cmd_rsp {
	int32_t status;
	union {
        grdm_rpmb_data_t rpmb_data;
#ifdef SUPPORT_FW_UPGRADE
		grdm_fw_info_t fw_info;
#endif
	} data;
    uint32_t grdm_status;
} blgrd_send_cmd_rsp_t;

GRDM_RESULT grdm_write_bl_rot_data(grdm_session_info_t *grdm_session_info, grdm_bl_rot_data_t *bl_rot_data);
GRDM_RESULT grdm_get_data(uint32_t seed_id, grdm_rpmb_data_t* resp_data);
#ifndef SUPPORT_SET_RPMB_SEED
GRDM_RESULT grdm_set_data(uint32_t seed_id);
#else
GRDM_RESULT grdm_set_data(uint32_t seed_id, uint32_t value);
#endif
GRDM_RESULT grdm_FWupgrade_Header(uint8_t *fw_header, grdm_fw_info_t* fw_info);
GRDM_RESULT grdm_FWupgrade_Start(uint8_t *fw_data);
GRDM_RESULT grdm_FWupgrade_Data(uint8_t *fw_data, uint32_t *next_size);
GRDM_RESULT grdm_FWupgrade_Finish(uint8_t* fw_version);
GRDM_RESULT grdm_get_fw_version(grdm_fw_info_t* fw_info);

GRDM_RESULT grdm_fuse(uint32_t seed_id);
GRDM_RESULT grdm_set_fuse_flag(uint32_t seed_id, uint32_t flag);
GRDM_RESULT grdm_set_fw_version(uint8_t *fw_ver);
#ifdef GRDM_RESET
GRDM_RESULT grdm_reset(uint32_t seed_id);
#endif

GRDM_RESULT grdm_fdc_check_status(uint32_t *status);
GRDM_RESULT grdm_fdc_check_Restriction(uint32_t *status);

#ifdef GRDM_CHECK_FACTORY
GRDM_RESULT grdm_check_bl_authkey();
#endif

#endif /*__APP_GRDM_H */
