xref: /openbmc/libpldm/src/transport/transport.c (revision c1b66f420912dd659a4159ebd176af18347958f4)
1 #include "libpldm/transport.h"
2 #include "base.h"
3 #include "libpldm/requester/pldm.h"
4 #include "transport.h"
5 
6 #ifdef PLDM_HAS_POLL
7 #include <poll.h>
8 #endif
9 #include <stdlib.h>
10 #include <unistd.h>
11 
12 #ifndef PLDM_HAS_POLL
13 struct pollfd {
14 	int fd;	       /* file descriptor */
15 	short events;  /* requested events */
16 	short revents; /* returned events */
17 };
18 
19 static inline int poll(struct pollfd *fds __attribute__((unused)),
20 		       int nfds __attribute__((unused)),
21 		       int timeout __attribute__((unused)))
22 {
23 	return 0;
24 }
25 #endif
26 
27 pldm_requester_rc_t pldm_transport_poll(struct pldm_transport *transport,
28 					int timeout)
29 {
30 	struct pollfd pollfd;
31 	int rc = 0;
32 	if (!transport) {
33 		return PLDM_REQUESTER_INVALID_SETUP;
34 	}
35 	if (!transport->init_pollfd) {
36 		return PLDM_REQUESTER_SUCCESS;
37 	}
38 
39 	transport->init_pollfd(transport, &pollfd);
40 	rc = poll(&pollfd, 1, timeout);
41 	if (rc < 0) {
42 		return PLDM_REQUESTER_POLL_FAIL;
43 	}
44 
45 	return PLDM_REQUESTER_SUCCESS;
46 }
47 
48 pldm_requester_rc_t pldm_transport_send_msg(struct pldm_transport *transport,
49 					    pldm_tid_t tid,
50 					    const void *pldm_req_msg,
51 					    size_t req_msg_len)
52 {
53 	if (!transport || !pldm_req_msg) {
54 		return PLDM_REQUESTER_INVALID_SETUP;
55 	}
56 
57 	if (req_msg_len < sizeof(struct pldm_msg_hdr)) {
58 		return PLDM_REQUESTER_NOT_REQ_MSG;
59 	}
60 
61 	const struct pldm_msg_hdr *hdr = pldm_req_msg;
62 	if (!hdr->request) {
63 		return PLDM_REQUESTER_NOT_REQ_MSG;
64 	}
65 
66 	return transport->send(transport, tid, pldm_req_msg, req_msg_len);
67 }
68 
69 pldm_requester_rc_t pldm_transport_recv_msg(struct pldm_transport *transport,
70 					    pldm_tid_t tid,
71 					    void **pldm_resp_msg,
72 					    size_t *resp_msg_len)
73 {
74 	if (!transport || !resp_msg_len) {
75 		return PLDM_REQUESTER_INVALID_SETUP;
76 	}
77 
78 	pldm_requester_rc_t rc =
79 	    transport->recv(transport, tid, pldm_resp_msg, resp_msg_len);
80 	if (rc != PLDM_REQUESTER_SUCCESS) {
81 		return rc;
82 	}
83 
84 	struct pldm_msg_hdr *hdr = *pldm_resp_msg;
85 	if (hdr->request || hdr->datagram) {
86 		free(*pldm_resp_msg);
87 		*pldm_resp_msg = NULL;
88 		return PLDM_REQUESTER_NOT_RESP_MSG;
89 	}
90 
91 	uint8_t pldm_rc = 0;
92 	if (*resp_msg_len < (sizeof(struct pldm_msg_hdr) + sizeof(pldm_rc))) {
93 		free(*pldm_resp_msg);
94 		*pldm_resp_msg = NULL;
95 		return PLDM_REQUESTER_RESP_MSG_TOO_SMALL;
96 	}
97 
98 	return PLDM_REQUESTER_SUCCESS;
99 }
100 
101 pldm_requester_rc_t
102 pldm_transport_send_recv_msg(struct pldm_transport *transport, pldm_tid_t tid,
103 			     const void *pldm_req_msg, size_t req_msg_len,
104 			     void **pldm_resp_msg, size_t *resp_msg_len)
105 
106 {
107 	if (!resp_msg_len) {
108 		return PLDM_REQUESTER_INVALID_SETUP;
109 	}
110 
111 	pldm_requester_rc_t rc =
112 	    pldm_transport_send_msg(transport, tid, pldm_req_msg, req_msg_len);
113 	if (rc != PLDM_REQUESTER_SUCCESS) {
114 		return rc;
115 	}
116 
117 	while (1) {
118 		rc = pldm_transport_poll(transport, -1);
119 		if (rc != PLDM_REQUESTER_SUCCESS) {
120 			break;
121 		}
122 		rc = pldm_transport_recv_msg(transport, tid, pldm_resp_msg,
123 					     resp_msg_len);
124 		if (rc == PLDM_REQUESTER_SUCCESS) {
125 			break;
126 		}
127 	}
128 
129 	return rc;
130 }
131