size_t connection_read_data_msg(struct connection *conn, void *buffer,
				uint32_t len)
{
	size_t ret = -1;
	MCDRV_DBG_VERBOSE("reading connection data %u, connection data left %u",
			  len, conn->data_len);
	/* trying to read more than the left data */
	if (len > conn->data_len) {
		ret = conn->data_len;
		memcpy(buffer, conn->data_start, conn->data_len);
		conn->data_len = 0;
	} else {
		ret = len;
		memcpy(buffer, conn->data_start, len);
		conn->data_len -= len;
		conn->data_start += len;
	}

	if (conn->data_len == 0) {
		conn->data_start = NULL;
		kfree_skb(conn->skb);
		conn->skb = NULL;
	}
	MCDRV_DBG_VERBOSE("read %u",  ret);
	return ret;
}
Beispiel #2
0
int mc_info(uint32_t ext_info_id, uint32_t *state, uint32_t *ext_info)
{
	int ret = 0;
	union mc_fc_info fc_info;

	MCDRV_DBG_VERBOSE(mcd, "enter\n");

	memset(&fc_info, 0, sizeof(fc_info));
	fc_info.as_in.cmd = MC_FC_INFO;
	fc_info.as_in.ext_info_id = ext_info_id;

	MCDRV_DBG(mcd, "fc_info <- cmd=0x%08x, ext_info_id=0x%08x\n",
		  fc_info.as_in.cmd, fc_info.as_in.ext_info_id);

	mc_fastcall(&(fc_info.as_generic));

	MCDRV_DBG(mcd,
		  "fc_info -> r=0x%08x ret=0x%08x state=0x%08x ext_info=0x%08x",
		  fc_info.as_out.resp,
		  fc_info.as_out.ret,
		  fc_info.as_out.state,
		  fc_info.as_out.ext_info);

	ret = convert_fc_ret(fc_info.as_out.ret);

	*state  = fc_info.as_out.state;
	*ext_info = fc_info.as_out.ext_info;

	MCDRV_DBG_VERBOSE(mcd, "exit with %d/0x%08X\n", ret, ret);

	return ret;
}
size_t connection_read_data(struct connection *conn, void *buffer, uint32_t len,
			    int32_t timeout)
{
	size_t ret = 0;

	MCDRV_ASSERT(buffer != NULL);
	MCDRV_ASSERT(conn->socket_descriptor != NULL);

	MCDRV_DBG_VERBOSE(mc_kapi, "read data len = %u for PID = %u",
			  len, conn->sequence_magic);
	do {
		/*
		 * Wait until data is available or timeout
		 * msecs_to_jiffies(-1) -> wait forever for the sem
		 */
		if (down_timeout(&(conn->data_available_sem),
				 msecs_to_jiffies(timeout))) {
			MCDRV_DBG_VERBOSE(mc_kapi,
					  "Timeout reading the data sem");
			ret = -2;
			break;
		}

    /*##################################
    #mobicore_security_team_add
    ##################################*/
    /*if (mutex_lock_interruptible(&(conn->data_lock))) {
            MCDRV_DBG_ERROR(mc_kapi,
                            "interrupted reading the data sem");
            ret = -1;
            break;
    }*/
    mutex_lock(&(conn->data_lock));         
    /*##################################*/

		/* Have data, use it */
		if (conn->data_len > 0)
			ret = connection_read_data_msg(conn, buffer, len);

		mutex_unlock(&(conn->data_lock));

		/* There is still some data left */
		if (conn->data_len > 0)
			up(&conn->data_available_sem);

	} while (0);

	return ret;
}
size_t connection_write_data(struct connection *conn, void *buffer,
			     uint32_t len)
{
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh;
	int ret = 0;

	MCDRV_DBG_VERBOSE("buffer length %u from pid %u\n",
			  len,  conn->sequence_magic);
	do {
		skb = nlmsg_new(NLMSG_SPACE(len), GFP_KERNEL);
		if (!skb) {
			ret = -1;
			break;
		}

		nlh = nlmsg_put(skb, 0, conn->sequence_magic, 2,
				NLMSG_LENGTH(len), NLM_F_REQUEST);
		if (!nlh) {
			ret = -1;
			break;
		}
		memcpy(NLMSG_DATA(nlh), buffer, len);

		netlink_unicast(conn->socket_descriptor, skb,
				conn->peer_pid, MSG_DONTWAIT);
		ret = len;
	} while (0);

	if (!ret && skb != NULL)
		kfree_skb(skb);

	return ret;
}
size_t connection_read_data(struct connection *conn, void *buffer, uint32_t len,
			    int32_t timeout)
{
	size_t ret = 0;

	MCDRV_ASSERT(buffer != NULL);
	MCDRV_ASSERT(conn->socket_descriptor != NULL);

	MCDRV_DBG_VERBOSE(mc_kapi, "read data len = %u for PID = %u",
			  len, conn->sequence_magic);
	do {
		if (down_timeout(&(conn->data_available_sem),
				 msecs_to_jiffies(timeout))) {
			MCDRV_DBG_VERBOSE(mc_kapi,
					  "Timeout reading the data sem");
			ret = -2;
			break;
		}

		if (mutex_lock_interruptible(&(conn->data_lock))) {
			MCDRV_DBG_ERROR(mc_kapi,
					"interrupted reading the data sem");
			ret = -1;
			break;
		}

		
		if (conn->data_len > 0)
			ret = connection_read_data_msg(conn, buffer, len);

		mutex_unlock(&(conn->data_lock));

		
		if (conn->data_len > 0)
			up(&conn->data_available_sem);

	} while (0);

	return ret;
}
Beispiel #6
0
/* call common notify */
int mc_nsiq(void)
{
	int ret = 0;
	union fc_generic nsiq;
	MCDRV_DBG_VERBOSE(mcd, "enter\n");

	memset(&nsiq, 0, sizeof(nsiq));
	nsiq.as_in.cmd = MC_SMC_N_SIQ;
	mc_fastcall(&nsiq);
	ret = convert_fc_ret(nsiq.as_out.ret);

	return ret;
}
Beispiel #7
0
/* Call the INIT fastcall to setup MobiCore initialization */
int mc_init(uint32_t base, uint32_t nq_offset, uint32_t nq_length,
	uint32_t mcp_offset, uint32_t mcp_length)
{
	int ret = 0;
	union mc_fc_init fc_init;

	MCDRV_DBG_VERBOSE(mcd, "enter\n");

	memset(&fc_init, 0, sizeof(fc_init));

	fc_init.as_in.cmd = MC_FC_INIT;
	/* base address of mci buffer 4KB aligned */
	fc_init.as_in.base = base;
	/* notification buffer start/length [16:16] [start, length] */
	fc_init.as_in.nq_info = (nq_offset << 16) | (nq_length & 0xFFFF);
	/* mcp buffer start/length [16:16] [start, length] */
	fc_init.as_in.mcp_info = (mcp_offset << 16) | (mcp_length & 0xFFFF);

	/*
	 * Set KMOD notification queue to start of MCI
	 * mciInfo was already set up in mmap
	 */
	MCDRV_DBG(mcd,
		  "cmd=0x%08x, base=0x%08x,nq_info=0x%08x, mcp_info=0x%08x\n",
		  fc_init.as_in.cmd, fc_init.as_in.base, fc_init.as_in.nq_info,
		  fc_init.as_in.mcp_info);

	mc_fastcall(&fc_init.as_generic);

	MCDRV_DBG(mcd, "out cmd=0x%08x, ret=0x%08x\n", fc_init.as_out.resp,
		  fc_init.as_out.ret);

	ret = convert_fc_ret(fc_init.as_out.ret);

	MCDRV_DBG_VERBOSE(mcd, "exit with %d/0x%08X\n", ret, ret);

	return ret;
}
Beispiel #8
0
/* Yield to MobiCore */
int mc_yield(void)
{
	int ret = 0;
	union fc_generic yield;

	MCDRV_DBG_VERBOSE(mcd, "enter\n");

	memset(&yield, 0, sizeof(yield));
	yield.as_in.cmd = MC_SMC_N_YIELD;
	mc_fastcall(&yield);
	ret = convert_fc_ret(yield.as_out.ret);

	return ret;
}