/*
@file app_anti-rollback.c
@brief Contains test code for most of the QSEE fuse APIs.

*/
/*===========================================================================
   Copyright (c) 2011 by Qualcomm Technologies, Incorporated.  All Rights Reserved.
===========================================================================*/

/*===========================================================================

                            EDIT HISTORY FOR FILE
  $Header: 
  $DateTime: 
  $Author: pwbldsvc $

# when       who     what, where, why
# 
===========================================================================*/

#include <stdbool.h>
#include "qsee_log.h"
#include "qsee_heap.h"
#include "qsee_fuse.h"
#include "qfprom.h"
#include "qsee_oem_buffer.h"
#include "bksecapp_fuse_location.h"
#include "bksecapp_anti-rollback.h"

/* Bus frequency is required when calling the qfprom APIs,
   but the value is not actually used.*/
#define BUS_FREQUENCY 0

uint32 get_anti_rollback_en(void)
{
		uint32 fuse_addr, anti_en;
		uint32 qfprom_status = 0;
		uint32 row_data_read[2] = {0x0, 0x0};

		fuse_addr = HWIO_QFPROM_RAW_OEM_CONFIG_ROW2_LSB_ADDR;
		qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif

		if(qfprom_status != QFPROM_NO_ERR)
		{
			qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
			return -1;
		}
#ifdef DEBUG_LOG_ENABLE
		else
		{
			qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
		}
#endif

		anti_en = row_data_read[1] & ANTI_ROLLBACK_EN_BMSK;
		anti_en = anti_en >> ANTI_ROLLBACK_EN_SHFT;
#ifdef DEBUG_LOG_ENABLE
		qsee_log(QSEE_LOG_MSG_ERROR, "anti_en 0x%x\n", anti_en);
#endif

		return anti_en;
}

uint32 get_anti_rollback_ignore(void)
{
		uint32 fuse_addr, anti_en;
		uint32 qfprom_status = 0;
		uint32 row_data_read[2] = {0x0, 0x0};

		anti_en = get_anti_rollback_en();
		fuse_addr = HWIO_QFPROM_RAW_WR_PERM_LSB_ADDR;
		qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif

		if(qfprom_status != QFPROM_NO_ERR)
		{
			qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
			return -1;
		}
#ifdef DEBUG_LOG_ENABLE
		else
		{
			qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
		}
#endif

		if( !anti_en && ((row_data_read[0] & ANTI_ROLLBACK_IGNORE_BMSK) == ANTI_ROLLBACK_IGNORE_VALUE))
			return 1;

		return 0;
}

uint32 get_anti_rollback_xbl_ver(void)
{
// RP bits shared for XBL, APPSBL, PMIC
// Hence same function called for all 3
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_XBL0_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif	

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE	
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[0] = row_data_read[0] & ANTI_ROLLBACK_XBL0_BMSK;
	row_data_read[0] = row_data_read[0] >> ANTI_ROLLBACK_XBL0_SHFT;

	if(row_data_read[0])
	{
		count = ANTI_ROLLBACK_XBL0_MAX;
		while(count--)
		{
			if(row_data_read[0] & 0x1)
				sw_rev++;
			row_data_read[0] = row_data_read[0] >> 1;
		}
	}

	row_data_read[1] = row_data_read[1] & ANTI_ROLLBACK_XBL1_BMSK;
	row_data_read[1] = row_data_read[1] >> ANTI_ROLLBACK_XBL1_SHFT;

	if(row_data_read[1])
	{
		count = ANTI_ROLLBACK_XBL1_MAX;
		while(count--)
		{
			if(row_data_read[1] & 0x1)
				sw_rev++;
			row_data_read[1] = row_data_read[1] >> 1;
		}
	}

	return sw_rev;
}

uint32 get_anti_rollback_pil_ver()
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_PIL_LSB_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif	

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE	
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[0] = row_data_read[0] & ANTI_ROLLBACK_PIL_LSB_BMSK;
	row_data_read[0] = row_data_read[0] >> ANTI_ROLLBACK_PIL_LSB_SHFT;

	if(row_data_read[0])
	{
		count = ANTI_ROLLBACK_PIL_LSB_MAX;
		while(count--)
		{
			if(row_data_read[0] & 0x1)
				sw_rev++;
			row_data_read[0] = row_data_read[0] >> 1;
		}
	}

	fuse_addr = ANTI_ROLLBACK_PIL_MSB_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif	

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE	
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[0] = row_data_read[0] & ANTI_ROLLBACK_PIL_MSB_BMSK;
	row_data_read[0] = row_data_read[0] >> ANTI_ROLLBACK_PIL_MSB_SHFT;

	if(row_data_read[0])
	{
		count = ANTI_ROLLBACK_PIL_MSB_MAX;
		while(count--)
		{
			if(row_data_read[0] & 0x1)
				sw_rev++;
			row_data_read[0] = row_data_read[0] >> 1;
		}
	}

	return sw_rev;
}

uint32 get_anti_rollback_tz_ver(void)
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_TZ_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif
	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif

	row_data_read[1] = row_data_read[1] & ANTI_ROLLBACK_TZ_BMSK;
	row_data_read[1] = row_data_read[1] >> ANTI_ROLLBACK_TZ_SHFT;

	if(row_data_read[1])
	{
		count = ANTI_ROLLBACK_TZ_MAX;
		while(count--)
		{
			if(row_data_read[1] & 0x1)
				sw_rev++;
			row_data_read[1] = row_data_read[1] >> 1;
		}
	}

	return sw_rev;
}

uint32 get_anti_rollback_rpm_ver(void)
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_RPM_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif
	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE	
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[1] = row_data_read[1] & ANTI_ROLLBACK_RPM_BMSK;
	row_data_read[1] = row_data_read[1] >> ANTI_ROLLBACK_RPM_SHFT;

	if(row_data_read[1])
	{
		count = ANTI_ROLLBACK_RPM_MAX;
		while(count--)
		{
			if(row_data_read[1] & 0x1)
				sw_rev++;
			row_data_read[1] = row_data_read[1] >> 1;
		}
	}

	return sw_rev;
}

uint32 get_anti_rollback_hyp_ver(void)
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_HYP_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif	

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE	
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[1] = row_data_read[1] & ANTI_ROLLBACK_HYP_BMSK;
	row_data_read[1] = row_data_read[1] >> ANTI_ROLLBACK_HYP_SHFT;

	if(row_data_read[1])
	{
		count = ANTI_ROLLBACK_HYP_MAX;
		while(count--)
		{
			if(row_data_read[1] & 0x1)
				sw_rev++;
			row_data_read[1] = row_data_read[1] >> 1;
		}
	}

	return sw_rev;
}

uint32 get_anti_rollback_dp_ver(void)
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_DP_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif	

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE	
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[1] = row_data_read[1] & ANTI_ROLLBACK_DP_BMSK;
	row_data_read[1] = row_data_read[1] >> ANTI_ROLLBACK_DP_SHFT;

	if(row_data_read[1])
	{
		count = ANTI_ROLLBACK_DP_MAX;
		while(count--)
		{
			if(row_data_read[1] & 0x1)
				sw_rev++;
			row_data_read[1] = row_data_read[1] >> 1;
		}
	}

	return sw_rev;
}

uint32 get_anti_rollback_dev_cfg_ver(void)
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_DEV_CFG_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif	

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE	
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif

	row_data_read[1] = row_data_read[1] & ANTI_ROLLBACK_DEV_CFG_BMSK;
	row_data_read[1] = row_data_read[1] >> ANTI_ROLLBACK_DEV_CFG_SHFT;

	if(row_data_read[1])
	{
		count = ANTI_ROLLBACK_DEV_CFG_MAX;
		while(count--)
		{
			if(row_data_read[1] & 0x1)
				sw_rev++;
			row_data_read[1] = row_data_read[1] >> 1;
		}
	}

	return sw_rev;
}

uint32 get_anti_rollback_xbl_config_ver(void)
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = ANTI_ROLLBACK_XBL_CONFIG_ADDRESS;
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);
#ifdef DEBUG_LOG_ENABLE
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value LSB : %x", row_data_read[0]);
	qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value MSB : %x", row_data_read[1]);
#endif	

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[0] = row_data_read[0] & ANTI_ROLLBACK_XBL_CONFIG0_BMSK;
	row_data_read[0] = row_data_read[0] >> ANTI_ROLLBACK_XBL_CONFIG0_SHFT;

	if(row_data_read[0])
	{
		count = ANTI_ROLLBACK_XBL_CONFIG0_MAX;
		while(count--)
		{
			if(row_data_read[0] & 0x1)
				sw_rev++;
			row_data_read[0] = row_data_read[0] >> 1;
		}
	}

	row_data_read[1] = row_data_read[1] & ANTI_ROLLBACK_XBL_CONFIG1_BMSK;
	row_data_read[1] = row_data_read[1] >> ANTI_ROLLBACK_XBL_CONFIG1_SHFT;

	if(row_data_read[1])
	{
		count = ANTI_ROLLBACK_XBL_CONFIG1_MAX;
		while(count--)
		{
			if(row_data_read[1] & 0x1)
				sw_rev++;
			row_data_read[1] = row_data_read[1] >> 1;
		}
	}
	return sw_rev;
}

uint32 get_rpmb_fuse(void)
{
	uint32 fuse_addr;
	uint32 qfprom_status = 0;
	uint32 row_data_read[2] = {0x0, 0x0};
	uint32 count, sw_rev = 0;

	fuse_addr = RPMB_FUSE_ADDRESS;
#ifdef DEBUG_LOG_ENABLE	
	qsee_log(QSEE_LOG_MSG_ERROR, "Read Fuse address [%x]", fuse_addr);
#endif	
	/*Read the fuse value*/
	qsee_fuse_read(fuse_addr, QFPROM_ADDR_SPACE_RAW, row_data_read, &qfprom_status);

	if(qfprom_status != QFPROM_NO_ERR)
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read returned error: %d", qfprom_status);
		return -1;
	}
#ifdef DEBUG_LOG_ENABLE
	else
	{
		qsee_log(QSEE_LOG_MSG_ERROR, "Initial read value: %x %x",row_data_read[0], row_data_read[1]);
	}
#endif	

	row_data_read[0] = row_data_read[0] & RPMB_FUSE_BMSK;
	row_data_read[0] = row_data_read[0] >> RPMB_FUSE_SHFT;

	return row_data_read[0];
}

