ta/wallet_ta.c
/**
  * Reads from the write cache or from the wallet storage when needed.
  * \param session_data A data pointer to a session context.
  * \param param_types The types of the four parameters.
  * \param params A pointer to an array of four parameters.
  * \return TEE_SUCCESS in case of success otherwise returns the result
  *         received from the failed operation. The information about all
  *         possible returns is present in TEE Client API Specification - 4.4.2
  *         published by GlobalPlatform.
  */
Reads from the write cache or from the wallet storage when needed.
\param session_data A data pointer to a session context.
\param param_types The types of the four parameters.
\param params A pointer to an array of four parameters.
\return TEE_SUCCESS in case of success otherwise returns the result
received from the failed operation. The information about all
possible returns is present in TEE Client API Specification - 4.4.2
published by GlobalPlatform.
Reads from the write cache or from the wallet storage when needed . \ param session_data A data pointer to a session context . \ param param_types The types of the four parameters . \ param params A pointer to an array of four parameters . \ return TEE_SUCCESS in case of success otherwise returns the result received from the failed operation . The information about all possible returns is present in TEE Client API Specification - 4 . 4 . 2 published by GlobalPlatform .
static TEE_Result read_cache_wallet_storage(Session_data * session_data, uint32_t param_types, TEE_Param params[4])
{
	TEE_Result result = TEE_SUCCESS;
	uint32_t address_tag;
	uint32_t address;
	uint32_t length;
    uint32_t end;
    uint32_t nv_read_length;
    uint32_t data_index;
	uint32_t exp_param_types;
	exp_param_types = TEE_PARAM_TYPES(
							TEE_PARAM_TYPE_MEMREF_OUTPUT,
							TEE_PARAM_TYPE_VALUE_INOUT,
							TEE_PARAM_TYPE_NONE,
							TEE_PARAM_TYPE_NONE);
	if (param_types != exp_param_types || params[0].memref.buffer == NULL)
		return TEE_ERROR_BAD_PARAMETERS;
	if (session_data->is_storage_open == false)
		return TEE_ERROR_BAD_STATE;
	address = params[1].value.a;
	length = params[0].memref.size;
	end = address + length;
	nv_read_length = 0;
	data_index = 0;
	while (address < end)
	{
		address_tag = address & SECTOR_TAG_MASK;
		if ((session_data->write_cache_valid) && (address_tag == (session_data->write_cache_tag)))
		{
			if (nv_read_length > 0)
			{
				result = read_wallet_storage_internal(
							session_data,
							(uint8_t*)&((uint8_t*)(params[0].memref.buffer))[data_index],
							(size_t)nv_read_length,
							address - nv_read_length);
				if (result != TEE_SUCCESS)
			    {
			    	#ifdef OP_TEE_TA
			    	DMSG("Failed to read from the wallet storage: 0x%x", result);
			    	#endif
			    	goto cleanup1;
			    }
			    data_index += nv_read_length;
                nv_read_length = 0;
			}
			((uint8_t*)(params[0].memref.buffer))[data_index] = (session_data->write_cache)[address & SECTOR_OFFSET_MASK];
			data_index++;
		}
		else
		{
			nv_read_length++;
		}
		address++;
	} 
	if (nv_read_length > 0)
	{
		result = read_wallet_storage_internal(
					session_data,
					(uint8_t*)&((uint8_t*)(params[0].memref.buffer))[data_index],
					(size_t)nv_read_length,
					address - nv_read_length);
		if (result != TEE_SUCCESS)
	    {
	    	#ifdef OP_TEE_TA
	    	DMSG("Failed to read from the wallet storage: 0x%x", result);
	    	#endif
	    	goto cleanup1;
	    }
	}
    cleanup1:
		return result;
}
static TEE_Result read_cache_wallet_storage ( Session_data * session_data , uint32_t param_types , TEE_Param params [ 4 ] ) { TEE_Result result = TEE_SUCCESS ; uint32_t address_tag ; uint32_t address ; uint32_t length ; uint32_t end ; uint32_t nv_read_length ; uint32_t data_index ; uint32_t exp_param_types ; exp_param_types = TEE_PARAM_TYPES ( TEE_PARAM_TYPE_MEMREF_OUTPUT , TEE_PARAM_TYPE_VALUE_INOUT , TEE_PARAM_TYPE_NONE , TEE_PARAM_TYPE_NONE ) ; if ( param_types != exp_param_types || params [ 0 ] . memref . buffer == NULL ) return TEE_ERROR_BAD_PARAMETERS ; if ( session_data -> is_storage_open == false ) return TEE_ERROR_BAD_STATE ; address = params [ 1 ] . value . a ; length = params [ 0 ] . memref . size ; end = address + length ; nv_read_length = 0 ; data_index = 0 ; while ( address < end ) { address_tag = address & SECTOR_TAG_MASK ; if ( ( session_data -> write_cache_valid ) && ( address_tag == ( session_data -> write_cache_tag ) ) ) { if ( nv_read_length > 0 ) { result = read_wallet_storage_internal ( session_data , ( uint8_t * ) & ( ( uint8_t * ) ( params [ 0 ] . memref . buffer ) ) [ data_index ] , ( size_t ) nv_read_length , address - nv_read_length ) ; if ( result != TEE_SUCCESS ) { #ifdef OP_TEE_TA DMSG ( " " , result ) ; #endif goto cleanup1 ; } data_index += nv_read_length ; nv_read_length = 0 ; } ( ( uint8_t * ) ( params [ 0 ] . memref . buffer ) ) [ data_index ] = ( session_data -> write_cache ) [ address & SECTOR_OFFSET_MASK ] ; data_index ++ ; } else { nv_read_length ++ ; } address ++ ; } if ( nv_read_length > 0 ) { result = read_wallet_storage_internal ( session_data , ( uint8_t * ) & ( ( uint8_t * ) ( params [ 0 ] . memref . buffer ) ) [ data_index ] , ( size_t ) nv_read_length , address - nv_read_length ) ; if ( result != TEE_SUCCESS ) { #ifdef OP_TEE_TA DMSG ( " " , result ) ; #endif goto cleanup1 ; } } cleanup1 : return result ; }
Reads from the write cache or from the wallet storage when needed.
Reads from the write cache or from the wallet storage when needed .
/*
	 * Expected:
	 * [OUT] params[0].memref.buffer -> Buffer to write the data read.
	 * [OUT] params[0].memref.size   -> Size of the data to be read.
	 * [IN]  params[1].value.a 	     -> Start address to read the data from.
	 * [OUT] params[1].value.b 	     -> Size of the data that was actually read.
	 */ /* Some sanity checks */ /* Check if the wallet storage is open */ /* Set the end of the region to read */ /* Length of contiguous non-volatile read */ /* Initialize data index variable */ /*
     * The code below attempts to group non-volatile reads together. It is
     * possible (and simpler) to read one byte at a time, but that is much less
     * efficient. Since reads are expected to occur much more frequently than
     * writes, inefficient reading will incur a significant performance penalty.
     */ /* Set the address of the sector where the the data is to be read from */ /* The data in the cache is from the sector to be read */ /*
                 * Beginning of write cache; end of contiguous non-volatile
                 * read.
                 */ /* Address is in cache; read from the cache. */ /* Don't read just yet; queue it up and do all the reads together. */ /* End while (address < end) */ /* End of contiguous non-volatile read. */ /* Resource cleanup */