src/plugins/serial/serial_terminal.c
static int
serial_term_build_msg(const struct ipmi_intf * intf,
		const struct ipmi_rq * req, uint8_t * msg, size_t max_len,
		struct serial_term_request_ctx * ctx, int * msg_len)
{
	uint8_t * data = msg, seq;
	struct serial_term_hdr * term_hdr = (struct serial_term_hdr *) msg;
	struct ipmi_send_message_rq * outer_rq = NULL;
	struct ipmi_send_message_rq * inner_rq = NULL;
	int bridging_level = ipmi_intf_get_bridging_level(intf);

	/* check overall packet length */
	if(req->msg.data_len + 3 + bridging_level * 8 > max_len) {
		lprintf(LOG_ERR, "ipmitool: Message data is too long");
		return -1;
	}

	/* allocate new sequence number */
	seq = serial_term_alloc_seq() << 2;

	/* check for bridging */
	if (bridging_level) {
		/* compose terminal message header */
		term_hdr->netFn = 0x18;
		term_hdr->seq = seq;
		term_hdr->cmd = 0x34;

		/* set pointer to send message request data */
		outer_rq = (struct ipmi_send_message_rq *) (term_hdr + 1);

		if (bridging_level == 2) {
			/* compose the outer send message request */
			outer_rq->channel = intf->transit_channel | 0x40;
			outer_rq->msg.rsSA = intf->transit_addr;
			outer_rq->msg.netFn = 0x18;
			outer_rq->msg.csum1 = -(outer_rq->msg.rsSA + outer_rq->msg.netFn);
			outer_rq->msg.rqSA = intf->my_addr;
			outer_rq->msg.rqSeq = seq;
			outer_rq->msg.cmd = 0x34;

			/* inner request is further */
			inner_rq = (outer_rq + 1);
		} else {
			/* there is only one header */
			inner_rq = outer_rq;
		}

		/* compose the inner send message request */
		inner_rq->channel = intf->target_channel | 0x40;
		inner_rq->msg.rsSA = intf->target_addr;
		inner_rq->msg.netFn = (req->msg.netfn << 2) | req->msg.lun;
		inner_rq->msg.csum1 = -(inner_rq->msg.rsSA + inner_rq->msg.netFn);
		inner_rq->msg.rqSA = intf->my_addr;
		inner_rq->msg.rqSeq = seq;
		inner_rq->msg.cmd = req->msg.cmd;

		/* check if interface is the system one */
		if (is_system) {
			/* need response to LUN 2 */
			outer_rq->msg.rqSeq |= 2;

			/* do not track response */
			outer_rq->channel &= ~0x40;

			/* restore BMC SA if bridging not to primary IPMB channel */
			if (outer_rq->channel) {
				outer_rq->msg.rqSA = IPMI_BMC_SLAVE_ADDR;
			}
		}

		/* fill the second context */
		ctx[1].netFn = outer_rq->msg.netFn;
		ctx[1].sa = outer_rq->msg.rsSA;
		ctx[1].seq = outer_rq->msg.rqSeq;
		ctx[1].cmd = outer_rq->msg.cmd;

		/* move write pointer */
		msg = (uint8_t *)(inner_rq + 1);
	} else {
		/* compose terminal message header */
		term_hdr->netFn = (req->msg.netfn << 2) | req->msg.lun;
		term_hdr->seq = seq;
		term_hdr->cmd = req->msg.cmd;

		/* move write pointer */
		msg = (uint8_t *)(term_hdr + 1);
	}

	/* fill the first context */
	ctx[0].netFn = term_hdr->netFn;
	ctx[0].seq = term_hdr->seq;
	ctx[0].cmd = term_hdr->cmd;

	/* write request data */
	memcpy(msg, req->msg.data, req->msg.data_len);

	/* move write pointer */
	msg += req->msg.data_len;

	if (bridging_level) {
		/* write inner message checksum */
		*msg++ = ipmi_csum(&inner_rq->msg.rqSA, req->msg.data_len + 3);

		/* check for double bridging */
		if (bridging_level == 2) {
			/* write outer message checksum */
			*msg++ = ipmi_csum(&outer_rq->msg.rqSA, 4);
		}
	}


	/* save message length */
	*msg_len = msg - data;

	/* return bridging level */
	return bridging_level;
}
/*
 *	Build IPMB message to be transmitted
 */
Build IPMB message to be transmitted
Build IPMB message to be transmitted
static int
serial_term_build_msg(const struct ipmi_intf * intf,
		const struct ipmi_rq * req, uint8_t * msg, size_t max_len,
		struct serial_term_request_ctx * ctx, int * msg_len)
{
	uint8_t * data = msg, seq;
	struct serial_term_hdr * term_hdr = (struct serial_term_hdr *) msg;
	struct ipmi_send_message_rq * outer_rq = NULL;
	struct ipmi_send_message_rq * inner_rq = NULL;
	int bridging_level = ipmi_intf_get_bridging_level(intf);
	if(req->msg.data_len + 3 + bridging_level * 8 > max_len) {
		lprintf(LOG_ERR, "ipmitool: Message data is too long");
		return -1;
	}
	seq = serial_term_alloc_seq() << 2;
	if (bridging_level) {
		term_hdr->netFn = 0x18;
		term_hdr->seq = seq;
		term_hdr->cmd = 0x34;
		outer_rq = (struct ipmi_send_message_rq *) (term_hdr + 1);
		if (bridging_level == 2) {
			outer_rq->channel = intf->transit_channel | 0x40;
			outer_rq->msg.rsSA = intf->transit_addr;
			outer_rq->msg.netFn = 0x18;
			outer_rq->msg.csum1 = -(outer_rq->msg.rsSA + outer_rq->msg.netFn);
			outer_rq->msg.rqSA = intf->my_addr;
			outer_rq->msg.rqSeq = seq;
			outer_rq->msg.cmd = 0x34;
			inner_rq = (outer_rq + 1);
		} else {
			inner_rq = outer_rq;
		}
		inner_rq->channel = intf->target_channel | 0x40;
		inner_rq->msg.rsSA = intf->target_addr;
		inner_rq->msg.netFn = (req->msg.netfn << 2) | req->msg.lun;
		inner_rq->msg.csum1 = -(inner_rq->msg.rsSA + inner_rq->msg.netFn);
		inner_rq->msg.rqSA = intf->my_addr;
		inner_rq->msg.rqSeq = seq;
		inner_rq->msg.cmd = req->msg.cmd;
		if (is_system) {
			outer_rq->msg.rqSeq |= 2;
			outer_rq->channel &= ~0x40;
			if (outer_rq->channel) {
				outer_rq->msg.rqSA = IPMI_BMC_SLAVE_ADDR;
			}
		}
		ctx[1].netFn = outer_rq->msg.netFn;
		ctx[1].sa = outer_rq->msg.rsSA;
		ctx[1].seq = outer_rq->msg.rqSeq;
		ctx[1].cmd = outer_rq->msg.cmd;
		msg = (uint8_t *)(inner_rq + 1);
	} else {
		term_hdr->netFn = (req->msg.netfn << 2) | req->msg.lun;
		term_hdr->seq = seq;
		term_hdr->cmd = req->msg.cmd;
		msg = (uint8_t *)(term_hdr + 1);
	}
	ctx[0].netFn = term_hdr->netFn;
	ctx[0].seq = term_hdr->seq;
	ctx[0].cmd = term_hdr->cmd;
	memcpy(msg, req->msg.data, req->msg.data_len);
	msg += req->msg.data_len;
	if (bridging_level) {
		*msg++ = ipmi_csum(&inner_rq->msg.rqSA, req->msg.data_len + 3);
		if (bridging_level == 2) {
			*msg++ = ipmi_csum(&outer_rq->msg.rqSA, 4);
		}
	}
	*msg_len = msg - data;
	return bridging_level;
}
static int serial_term_build_msg ( const struct ipmi_intf * intf , const struct ipmi_rq * req , uint8_t * msg , size_t max_len , struct serial_term_request_ctx * ctx , int * msg_len ) { uint8_t * data = msg , seq ; struct serial_term_hdr * term_hdr = ( struct serial_term_hdr * ) msg ; struct ipmi_send_message_rq * outer_rq = NULL ; struct ipmi_send_message_rq * inner_rq = NULL ; int bridging_level = ipmi_intf_get_bridging_level ( intf ) ; if ( req -> msg . data_len + 3 + bridging_level * 8 > max_len ) { lprintf ( LOG_ERR , " " ) ; return -1 ; } seq = serial_term_alloc_seq ( ) << 2 ; if ( bridging_level ) { term_hdr -> netFn = 0x18 ; term_hdr -> seq = seq ; term_hdr -> cmd = 0x34 ; outer_rq = ( struct ipmi_send_message_rq * ) ( term_hdr + 1 ) ; if ( bridging_level == 2 ) { outer_rq -> channel = intf -> transit_channel | 0x40 ; outer_rq -> msg . rsSA = intf -> transit_addr ; outer_rq -> msg . netFn = 0x18 ; outer_rq -> msg . csum1 = - ( outer_rq -> msg . rsSA + outer_rq -> msg . netFn ) ; outer_rq -> msg . rqSA = intf -> my_addr ; outer_rq -> msg . rqSeq = seq ; outer_rq -> msg . cmd = 0x34 ; inner_rq = ( outer_rq + 1 ) ; } else { inner_rq = outer_rq ; } inner_rq -> channel = intf -> target_channel | 0x40 ; inner_rq -> msg . rsSA = intf -> target_addr ; inner_rq -> msg . netFn = ( req -> msg . netfn << 2 ) | req -> msg . lun ; inner_rq -> msg . csum1 = - ( inner_rq -> msg . rsSA + inner_rq -> msg . netFn ) ; inner_rq -> msg . rqSA = intf -> my_addr ; inner_rq -> msg . rqSeq = seq ; inner_rq -> msg . cmd = req -> msg . cmd ; if ( is_system ) { outer_rq -> msg . rqSeq |= 2 ; outer_rq -> channel &= ~ 0x40 ; if ( outer_rq -> channel ) { outer_rq -> msg . rqSA = IPMI_BMC_SLAVE_ADDR ; } } ctx [ 1 ] . netFn = outer_rq -> msg . netFn ; ctx [ 1 ] . sa = outer_rq -> msg . rsSA ; ctx [ 1 ] . seq = outer_rq -> msg . rqSeq ; ctx [ 1 ] . cmd = outer_rq -> msg . cmd ; msg = ( uint8_t * ) ( inner_rq + 1 ) ; } else { term_hdr -> netFn = ( req -> msg . netfn << 2 ) | req -> msg . lun ; term_hdr -> seq = seq ; term_hdr -> cmd = req -> msg . cmd ; msg = ( uint8_t * ) ( term_hdr + 1 ) ; } ctx [ 0 ] . netFn = term_hdr -> netFn ; ctx [ 0 ] . seq = term_hdr -> seq ; ctx [ 0 ] . cmd = term_hdr -> cmd ; memcpy ( msg , req -> msg . data , req -> msg . data_len ) ; msg += req -> msg . data_len ; if ( bridging_level ) { * msg ++ = ipmi_csum ( & inner_rq -> msg . rqSA , req -> msg . data_len + 3 ) ; if ( bridging_level == 2 ) { * msg ++ = ipmi_csum ( & outer_rq -> msg . rqSA , 4 ) ; } } * msg_len = msg - data ; return bridging_level ; }
Build IPMB message to be transmitted
Build IPMB message to be transmitted
/* check overall packet length */ /* allocate new sequence number */ /* check for bridging */ /* compose terminal message header */ /* set pointer to send message request data */ /* compose the outer send message request */ /* inner request is further */ /* there is only one header */ /* compose the inner send message request */ /* check if interface is the system one */ /* need response to LUN 2 */ /* do not track response */ /* restore BMC SA if bridging not to primary IPMB channel */ /* fill the second context */ /* move write pointer */ /* compose terminal message header */ /* move write pointer */ /* fill the first context */ /* write request data */ /* move write pointer */ /* write inner message checksum */ /* check for double bridging */ /* write outer message checksum */ /* save message length */ /* return bridging level */