Sunday, April 5, 2026
Hack NATO
ret = i2c_start_send(bus, source, slave_addr);
if (ret < 0) {
printf("No ACK from device\n");
return ret;
}
mctp link set mctpi2cX up
mctp addr add <EID> dev mctpi2cX
mctp link set mctpi2cX net <NET>
systemctl restart mctpd
/* Hack: ensure async send BH runs more than once */
if (!s->async_in_progress) {
s->async_in_progress = true;
qemu_bh_schedule(s->bh);
}
i2cdetect -y <bus>
busctl call xyz.openbmc_project.MCTP \
/xyz/openbmc_project/mctp \
au.com.CodeConstruct.MCTP AssignEndpoint \
say mctpi2cX 1 0x4d
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
/* -----------------------------
Transport-layer abstraction
----------------------------- */
int start_send(int bus, uint8_t slave_addr, const uint8_t *buf, size_t len);
int complete_send(int bus);
/* -----------------------------
MCTP header structure
----------------------------- */
typedef struct {
uint8_t ver; // MCTP version (always 1)
uint8_t dest_eid; // Destination endpoint ID
uint8_t src_eid; // Source endpoint ID
uint8_t flags; // SOM/EOM/Tag/TO
} mctp_hdr_t;
/* -----------------------------
Build MCTP header
----------------------------- */
void mctp_build_header(mctp_hdr_t *h,
uint8_t dest,
uint8_t src,
bool som,
bool eom,
uint8_t tag,
bool tag_owner)
{
h->ver = 1;
h->dest_eid = dest;
h->src_eid = src;
h->flags =
((som ? 1 : 0) << 7) |
((eom ? 1 : 0) << 6) |
((tag & 0x03) << 4) |
((tag_owner ? 1 : 0) << 3);
}
/* -----------------------------
Send one MCTP packet
----------------------------- */
int mctp_send_packet(int bus,
uint8_t slave_addr,
uint8_t dest_eid,
uint8_t src_eid,
const uint8_t *payload,
size_t payload_len)
{
uint8_t frame[256];
size_t pos = 0;
/* Build header */
mctp_hdr_t hdr;
mctp_build_header(&hdr, dest_eid, src_eid,
true, true, // SOM/EOM = single-packet message
0, // Tag = 0
true); // Tag owner = requester
/* Serialize header */
frame[pos++] = hdr.ver;
frame[pos++] = hdr.dest_eid;
frame[pos++] = hdr.src_eid;
frame[pos++] = hdr.flags;
/* Copy payload */
memcpy(&frame[pos], payload, payload_len);
pos += payload_len;
/* Transport: start_send */
int ret = start_send(bus, slave_addr, frame, pos);
if (ret < 0) {
printf("ERROR: start_send failed (MCTP did not respond)\n");
return ret;
}
/* Transport: complete_send */
ret = complete_send(bus);
if (ret < 0) {
printf("ERROR: complete_send failed\n");
return ret;
}
return 0;
}
int start_send(int bus, uint8_t slave_addr, const uint8_t *buf, size_t len)
{
printf("Sending %zu bytes to slave 0x%02X on bus %d\n", len, slave_addr, bus);
/* Replace this with your I2C/SMBus write */
bool ack = true; // simulate ACK
if (!ack) {
return -1; // simulate "MCTP did not respond"
}
return 0;
}
int complete_send(int bus)
{
/* In real hardware this waits for async completion */
return 0;
}
int main(void)
{
const uint8_t msg[] = { 0xAA, 0xBB, 0xCC };
int ret = mctp_send_packet(
1, // bus
0x4D, // slave address
8, // destination EID
1, // source EID
msg,
sizeof(msg)
);
if (ret == 0)
printf("MCTP send OK\n");
else
printf("MCTP send FAILED\n");
return 0;
}



















