blob: 332e94952a94e4e683364cb8c41ce35ac6375038 [file] [log] [blame]
Andrew Jeffery0247c732020-02-06 11:48:52 +10301/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10303#ifdef HAVE_CONFIG_H
Andrew Jeffery0247c732020-02-06 11:48:52 +10304#include "config.h"
Andrew Jeffery2cda40f2020-02-28 15:26:20 +10305#endif
6
Andrew Jefferydf5f6b92020-05-12 21:39:06 +09307#include "astlpc.c"
8
9#ifdef pr_fmt
10#undef pr_fmt
11#define pr_fmt(x) "test: " x
12#endif
13
Andrew Jeffery0247c732020-02-06 11:48:52 +103014#include "libmctp-astlpc.h"
15#include "libmctp-log.h"
Przemyslaw Czarnowskiff25d7e2020-03-26 11:39:37 +010016#include "container_of.h"
Andrew Jeffery0247c732020-02-06 11:48:52 +103017
18#ifdef NDEBUG
19#undef NDEBUG
20#endif
21
Andrew Jeffery0247c732020-02-06 11:48:52 +103022#include <assert.h>
Andrew Jeffery91f09ed2020-05-22 20:52:26 +093023#include <limits.h>
Andrew Jeffery0247c732020-02-06 11:48:52 +103024#include <stdint.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
Andrew Jeffery91f09ed2020-05-22 20:52:26 +093029#ifndef ARRAY_SIZE
30#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
31#endif
32
Andrew Jeffery0247c732020-02-06 11:48:52 +103033struct mctp_binding_astlpc_mmio {
34 struct mctp_binding_astlpc astlpc;
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093035 bool bmc;
Andrew Jeffery0247c732020-02-06 11:48:52 +103036
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093037 uint8_t (*kcs)[2];
Andrew Jeffery0247c732020-02-06 11:48:52 +103038
39 size_t lpc_size;
40 uint8_t *lpc;
41};
42
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +093043struct astlpc_endpoint {
44 struct mctp_binding_astlpc_mmio mmio;
45 struct mctp_binding_astlpc *astlpc;
46 struct mctp *mctp;
47};
48
49struct astlpc_test {
50 struct astlpc_endpoint bmc;
51 struct astlpc_endpoint host;
52 uint8_t kcs[2];
53 uint8_t *lpc_mem;
54
55 void *msg;
56 uint8_t count;
57};
58
59#define binding_to_mmio(b) \
Andrew Jeffery0247c732020-02-06 11:48:52 +103060 container_of(b, struct mctp_binding_astlpc_mmio, astlpc)
61
Andrew Jeffery53ea1472020-05-23 21:06:24 +093062static int mctp_astlpc_mmio_kcs_read(void *data,
63 enum mctp_binding_astlpc_kcs_reg reg,
64 uint8_t *val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103065{
66 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
67
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093068 *val = (*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103069
Andrew Jefferyd3c0bf02020-05-28 15:28:40 +093070 mctp_prdebug("%s: 0x%hhx from %s", __func__, *val,
71 reg ? "status" : "data");
Andrew Jeffery0247c732020-02-06 11:48:52 +103072
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093073 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
74 uint8_t flag = mmio->bmc ? KCS_STATUS_IBF : KCS_STATUS_OBF;
75 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] &= ~flag;
76 }
Andrew Jeffery0247c732020-02-06 11:48:52 +103077
78 return 0;
79}
80
Andrew Jeffery53ea1472020-05-23 21:06:24 +093081static int mctp_astlpc_mmio_kcs_write(void *data,
82 enum mctp_binding_astlpc_kcs_reg reg,
83 uint8_t val)
Andrew Jeffery0247c732020-02-06 11:48:52 +103084{
85 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093086 uint8_t *regp;
Andrew Jeffery0247c732020-02-06 11:48:52 +103087
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093088 assert(reg == MCTP_ASTLPC_KCS_REG_DATA ||
89 reg == MCTP_ASTLPC_KCS_REG_STATUS);
Andrew Jeffery0247c732020-02-06 11:48:52 +103090
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093091 if (reg == MCTP_ASTLPC_KCS_REG_DATA) {
92 uint8_t flag = mmio->bmc ? KCS_STATUS_OBF : KCS_STATUS_IBF;
93 (*mmio->kcs)[MCTP_ASTLPC_KCS_REG_STATUS] |= flag;
94 }
95
96 regp = &(*mmio->kcs)[reg];
Andrew Jeffery0247c732020-02-06 11:48:52 +103097 if (reg == MCTP_ASTLPC_KCS_REG_STATUS)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +093098 *regp = (val & ~0xbU) | (val & *regp & 1);
Andrew Jeffery0247c732020-02-06 11:48:52 +103099 else
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930100 *regp = val;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030101
Andrew Jefferyd3c0bf02020-05-28 15:28:40 +0930102 mctp_prdebug("%s: 0x%hhx to %s", __func__, val,
103 reg ? "status" : "data");
Andrew Jeffery0247c732020-02-06 11:48:52 +1030104
105 return 0;
106}
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030107int mctp_astlpc_mmio_lpc_read(void *data, void *buf, long offset, size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030108{
109 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
110
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930111 mctp_prdebug("%s: %zu bytes from 0x%lx", __func__, len, offset);
112
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030113 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030114 assert(offset + len < mmio->lpc_size);
115
116 memcpy(buf, mmio->lpc + offset, len);
117
Andrew Jeffery0247c732020-02-06 11:48:52 +1030118 return 0;
119}
120
Andrew Jeffery55fb90b2020-05-12 13:54:37 +0930121int mctp_astlpc_mmio_lpc_write(void *data, const void *buf, long offset,
122 size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030123{
124 struct mctp_binding_astlpc_mmio *mmio = binding_to_mmio(data);
125
Andrew Jeffery1dbf0212020-05-12 13:53:50 +0930126 mctp_prdebug("%s: %zu bytes to 0x%lx", __func__, len, offset);
127
Andrew Jeffery06b2cd82020-03-17 23:12:27 +1030128 assert(offset >= 0L);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030129 assert(offset + len < mmio->lpc_size);
130
131 memcpy(mmio->lpc + offset, buf, len);
132
Andrew Jeffery0247c732020-02-06 11:48:52 +1030133 return 0;
134}
135
Andrew Jefferyb93b6112020-06-05 14:13:44 +0930136#define __unused __attribute__((unused))
137
138static void rx_message(uint8_t eid __unused, void *data __unused, void *msg,
139 size_t len)
Andrew Jeffery0247c732020-02-06 11:48:52 +1030140{
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930141 struct astlpc_test *test = data;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030142
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930143 mctp_prdebug("MCTP message received: msg: %p, len %zd", msg, len);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030144
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930145 assert(len > 0);
146 assert(msg);
147 assert(test);
148 assert(test->msg);
149 assert(!memcmp(test->msg, msg, len));
150
151 test->count++;
Andrew Jeffery0247c732020-02-06 11:48:52 +1030152}
153
Andrew Jeffery55fb90b2020-05-12 13:54:37 +0930154static const struct mctp_binding_astlpc_ops astlpc_direct_mmio_ops = {
155 .kcs_read = mctp_astlpc_mmio_kcs_read,
156 .kcs_write = mctp_astlpc_mmio_kcs_write,
157};
158
159static const struct mctp_binding_astlpc_ops astlpc_indirect_mmio_ops = {
Andrew Jeffery0247c732020-02-06 11:48:52 +1030160 .kcs_read = mctp_astlpc_mmio_kcs_read,
161 .kcs_write = mctp_astlpc_mmio_kcs_write,
162 .lpc_read = mctp_astlpc_mmio_lpc_read,
163 .lpc_write = mctp_astlpc_mmio_lpc_write,
164};
165
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930166static int endpoint_init(struct astlpc_endpoint *ep, mctp_eid_t eid,
167 uint8_t mode, uint8_t (*kcs)[2], void *lpc_mem)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930168{
169 /*
170 * Configure the direction of the KCS interface so we know whether to
171 * set or clear IBF or OBF on writes or reads.
172 */
173 ep->mmio.bmc = (mode == MCTP_BINDING_ASTLPC_MODE_BMC);
174
175 ep->mctp = mctp_init();
176 assert(ep->mctp);
177
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930178 /* Inject KCS registers */
179 ep->mmio.kcs = kcs;
180
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930181 /* Initialise the binding */
Andrew Jeffery129ef932020-05-22 16:24:19 +0930182 ep->astlpc = mctp_astlpc_init(mode, MCTP_BTU, lpc_mem,
Andrew Jeffery55fb90b2020-05-12 13:54:37 +0930183 &astlpc_direct_mmio_ops, &ep->mmio);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930184
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930185 return mctp_register_bus(ep->mctp, &ep->astlpc->binding, eid);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930186}
187
188static void endpoint_destroy(struct astlpc_endpoint *ep)
189{
190 mctp_astlpc_destroy(ep->astlpc);
191 mctp_destroy(ep->mctp);
192}
193
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930194static void network_init(struct astlpc_test *ctx)
195{
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930196 int rc;
197
Andrew Jeffery55fb90b2020-05-12 13:54:37 +0930198 ctx->lpc_mem = calloc(1, 1 * 1024 * 1024);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930199 assert(ctx->lpc_mem);
200
201 /* BMC initialisation */
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930202 rc = endpoint_init(&ctx->bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC,
203 &ctx->kcs, ctx->lpc_mem);
204 assert(!rc);
Andrew Jeffery3f325072020-05-28 09:19:51 +0930205 assert(ctx->kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930206
207 /* Host initialisation */
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930208 rc = endpoint_init(&ctx->host, 9, MCTP_BINDING_ASTLPC_MODE_HOST,
209 &ctx->kcs, ctx->lpc_mem);
210 assert(!rc);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930211
212 /* BMC processes host channel init request, alerts host */
213 mctp_astlpc_poll(ctx->bmc.astlpc);
Andrew Jeffery3f325072020-05-28 09:19:51 +0930214 assert(ctx->kcs[MCTP_ASTLPC_KCS_REG_STATUS] &
215 KCS_STATUS_CHANNEL_ACTIVE);
216 assert(ctx->kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930217
218 /* Host dequeues channel init result */
219 mctp_astlpc_poll(ctx->host.astlpc);
220}
221
222static void network_destroy(struct astlpc_test *ctx)
223{
224 endpoint_destroy(&ctx->bmc);
225 endpoint_destroy(&ctx->host);
226 free(ctx->lpc_mem);
227}
228
Andrew Jeffery129ef932020-05-22 16:24:19 +0930229static void astlpc_assert_tx_packet(struct astlpc_endpoint *src,
230 const void *expected, size_t len)
231{
232 const size_t tx_body = src->astlpc->layout.tx.offset + 4 + 4;
233 const void *test = ((char *)src->astlpc->lpc_map) + tx_body;
234 assert(!memcmp(test, expected, len));
235}
236
Andrew Jefferye756de82020-05-22 12:30:58 +0930237static void astlpc_test_packetised_message_bmc_to_host(void)
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930238{
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930239 struct astlpc_test ctx = { 0 };
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930240 uint8_t msg[2 * MCTP_BTU];
Andrew Jeffery0247c732020-02-06 11:48:52 +1030241 int rc;
242
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930243 /* Test harness initialisation */
244
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930245 network_init(&ctx);
246
Andrew Jeffery0247c732020-02-06 11:48:52 +1030247 memset(&msg[0], 0x5a, MCTP_BTU);
248 memset(&msg[MCTP_BTU], 0xa5, MCTP_BTU);
249
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930250 ctx.msg = &msg[0];
251 ctx.count = 0;
252 mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030253
254 /* BMC sends a message */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930255 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
Andrew Jeffery0247c732020-02-06 11:48:52 +1030256 assert(rc == 0);
Andrew Jefferyd5e3cd72020-05-12 22:10:22 +0930257
Andrew Jeffery129ef932020-05-22 16:24:19 +0930258 /* Host receives the first packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930259 mctp_astlpc_poll(ctx.host.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030260
Andrew Jeffery0247c732020-02-06 11:48:52 +1030261 /* BMC dequeues ownership hand-over and sends the queued packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930262 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030263 assert(rc == 0);
264
Andrew Jeffery129ef932020-05-22 16:24:19 +0930265 /* Host receives the next packet */
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930266 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
267 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030268
Andrew Jeffery129ef932020-05-22 16:24:19 +0930269 astlpc_assert_tx_packet(&ctx.bmc, &msg[MCTP_BTU], MCTP_BTU);
Andrew Jeffery0247c732020-02-06 11:48:52 +1030270
Andrew Jeffery5a7c2db2020-05-22 20:13:42 +0930271 /* Host receives final packet */
272 mctp_astlpc_poll(ctx.host.astlpc);
273 assert(ctx.count == 1);
274
Andrew Jefferycb5d55c2020-05-22 13:26:27 +0930275 network_destroy(&ctx);
Andrew Jefferye756de82020-05-22 12:30:58 +0930276}
277
Andrew Jefferyec9a0062020-05-22 21:21:55 +0930278static void astlpc_test_simple_message_host_to_bmc(void)
279{
280 struct astlpc_test ctx = { 0 };
281 uint8_t msg[MCTP_BTU];
282 int rc;
283
284 /* Test harness initialisation */
285
286 network_init(&ctx);
287
288 memset(&msg[0], 0xa5, MCTP_BTU);
289
290 ctx.msg = &msg[0];
291 ctx.count = 0;
292 mctp_set_rx_all(ctx.bmc.mctp, rx_message, &ctx);
293
294 /* Host sends the single-packet message */
295 rc = mctp_message_tx(ctx.host.mctp, 8, msg, sizeof(msg));
296 assert(rc == 0);
297 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
298 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
299
300 astlpc_assert_tx_packet(&ctx.host, &msg[0], MCTP_BTU);
301
302 /* BMC receives the single-packet message */
303 mctp_astlpc_poll(ctx.bmc.astlpc);
304 assert(ctx.count == 1);
305
306 /* BMC returns Tx area ownership to Host */
307 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF));
308 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
309 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
310
311 /* Host dequeues ownership hand-over and sends the queued packet */
312 rc = mctp_astlpc_poll(ctx.host.astlpc);
313 assert(rc == 0);
314
315 network_destroy(&ctx);
316}
317
Andrew Jeffery8f3eb722020-05-22 20:23:49 +0930318static void astlpc_test_simple_message_bmc_to_host(void)
319{
320 struct astlpc_test ctx = { 0 };
321 uint8_t msg[MCTP_BTU];
322 int rc;
323
324 /* Test harness initialisation */
325
326 network_init(&ctx);
327
328 memset(&msg[0], 0x5a, MCTP_BTU);
329
330 ctx.msg = &msg[0];
331 ctx.count = 0;
332 mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
333
334 /* BMC sends the single-packet message */
335 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
336 assert(rc == 0);
337 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
338 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x01);
339
340 astlpc_assert_tx_packet(&ctx.bmc, &msg[0], MCTP_BTU);
341
342 /* Host receives the single-packet message */
343 mctp_astlpc_poll(ctx.host.astlpc);
344 assert(ctx.count == 1);
345
346 /* Host returns Rx area ownership to BMC */
347 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
348 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x02);
349 assert(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
350
351 /* BMC dequeues ownership hand-over and sends the queued packet */
352 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
353 assert(rc == 0);
354
355 network_destroy(&ctx);
356}
357
Andrew Jefferyf1cdb162020-05-23 21:25:21 +0930358static void astlpc_test_host_before_bmc(void)
359{
360 struct mctp_binding_astlpc_mmio mmio = { 0 };
361 struct mctp_binding_astlpc *astlpc;
362 uint8_t kcs[2] = { 0 };
363 struct mctp *mctp;
364 int rc;
365
366 mctp = mctp_init();
367 assert(mctp);
368
369 /* Inject KCS registers */
370 mmio.kcs = &kcs;
371
372 /* Initialise the binding */
373 astlpc = mctp_astlpc_init(MCTP_BINDING_ASTLPC_MODE_HOST, MCTP_BTU, NULL,
Andrew Jeffery55fb90b2020-05-12 13:54:37 +0930374 &astlpc_direct_mmio_ops, &mmio);
Andrew Jefferyf1cdb162020-05-23 21:25:21 +0930375
376 /* Register the binding to trigger the start-up sequence */
377 rc = mctp_register_bus(mctp, &astlpc->binding, 8);
378
379 /* Start-up should fail as we haven't initialised the BMC */
380 assert(rc < 0);
381
382 mctp_astlpc_destroy(astlpc);
383 mctp_destroy(mctp);
384}
385
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930386static void astlpc_test_bad_version(void)
387{
388 assert(0 ==
389 mctp_astlpc_negotiate_version(ASTLPC_VER_BAD, ASTLPC_VER_CUR,
390 ASTLPC_VER_MIN, ASTLPC_VER_CUR));
391 assert(0 ==
392 mctp_astlpc_negotiate_version(ASTLPC_VER_MIN, ASTLPC_VER_BAD,
393 ASTLPC_VER_MIN, ASTLPC_VER_CUR));
394 assert(0 ==
395 mctp_astlpc_negotiate_version(ASTLPC_VER_MIN, ASTLPC_VER_CUR,
396 ASTLPC_VER_BAD, ASTLPC_VER_CUR));
397 assert(0 ==
398 mctp_astlpc_negotiate_version(ASTLPC_VER_MIN, ASTLPC_VER_CUR,
399 ASTLPC_VER_MIN, ASTLPC_VER_BAD));
400 assert(0 == mctp_astlpc_negotiate_version(
401 ASTLPC_VER_CUR + 1, ASTLPC_VER_CUR, ASTLPC_VER_MIN,
402 ASTLPC_VER_CUR + 1));
403 assert(0 == mctp_astlpc_negotiate_version(
404 ASTLPC_VER_MIN, ASTLPC_VER_CUR + 1,
405 ASTLPC_VER_CUR + 1, ASTLPC_VER_CUR));
406}
407
408static void astlpc_test_incompatible_versions(void)
409{
410 assert(0 == mctp_astlpc_negotiate_version(
411 ASTLPC_VER_CUR, ASTLPC_VER_CUR, ASTLPC_VER_CUR + 1,
412 ASTLPC_VER_CUR + 1));
413 assert(0 == mctp_astlpc_negotiate_version(
414 ASTLPC_VER_CUR + 1, ASTLPC_VER_CUR + 1,
415 ASTLPC_VER_CUR, ASTLPC_VER_CUR));
416}
417
418static void astlpc_test_choose_bmc_ver_cur(void)
419{
420 assert(2 == mctp_astlpc_negotiate_version(1, 2, 2, 3));
421}
422
423static void astlpc_test_choose_host_ver_cur(void)
424{
425 assert(2 == mctp_astlpc_negotiate_version(2, 3, 1, 2));
426}
427
428static void astlpc_test_version_host_fails_negotiation(void)
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930429{
430 struct astlpc_endpoint bmc, host;
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930431 struct mctp_lpcmap_hdr *hdr;
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930432 uint8_t kcs[2] = { 0 };
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930433 void *lpc_mem;
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930434 int rc;
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930435
436 /* Test harness initialisation */
Andrew Jeffery55fb90b2020-05-12 13:54:37 +0930437 lpc_mem = calloc(1, 1 * 1024 * 1024);
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930438 assert(lpc_mem);
439
Andrew Jeffery8f3eb722020-05-22 20:23:49 +0930440 /* BMC initialisation */
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930441 rc = endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs,
442 lpc_mem);
443 assert(!rc);
444
445 /* Now the BMC is initialised, break its version announcement */
446 hdr = lpc_mem;
447 hdr->bmc_ver_cur = ASTLPC_VER_BAD;
448
449 /* Host initialisation */
450 rc = endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs,
451 lpc_mem);
452 assert(rc < 0);
453
454 endpoint_destroy(&bmc);
455 endpoint_destroy(&host);
456 free(lpc_mem);
457}
458
459static void astlpc_test_version_bmc_fails_negotiation(void)
460{
461 struct astlpc_endpoint bmc, host;
462 struct mctp_lpcmap_hdr *hdr;
463 uint8_t kcs[2] = { 0 };
464 void *lpc_mem;
465 int rc;
466
467 /* Test harness initialisation */
468 lpc_mem = calloc(1, 1 * 1024 * 1024);
469 assert(lpc_mem);
470
471 /* BMC initialisation */
472 rc = endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs,
473 lpc_mem);
474 assert(!rc);
475
476 /* Host initialisation */
477 rc = endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs,
478 lpc_mem);
479 assert(!rc);
480
481 /* Now the host is initialised, break its version announcement */
482 hdr = lpc_mem;
483 hdr->host_ver_cur = ASTLPC_VER_BAD;
484
485 /* Poll the BMC to detect the broken host version */
486 mctp_astlpc_poll(bmc.astlpc);
487 assert(!(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE));
488
489 /* Poll the host so it detects failed negotiation */
490 rc = mctp_astlpc_poll(host.astlpc);
491 assert(rc < 0);
492
493 endpoint_destroy(&bmc);
494 endpoint_destroy(&host);
495 free(lpc_mem);
496}
497
498static void astlpc_test_simple_init(void)
499{
500 struct astlpc_endpoint bmc, host;
501 uint8_t kcs[2] = { 0 };
502 void *lpc_mem;
503 int rc;
504
505 /* Test harness initialisation */
506 lpc_mem = calloc(1, 1 * 1024 * 1024);
507 assert(lpc_mem);
508
509 /* BMC initialisation */
510 rc = endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs,
511 lpc_mem);
512 assert(!rc);
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930513
514 /* Verify the BMC binding was initialised */
515 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_BMC_READY);
516
Andrew Jeffery8f3eb722020-05-22 20:23:49 +0930517 /* Host initialisation */
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930518 rc = endpoint_init(&host, 9, MCTP_BINDING_ASTLPC_MODE_HOST, &kcs,
519 lpc_mem);
520 assert(!rc);
Andrew Jefferyf1a21312020-05-22 12:48:21 +0930521
522 /* Host sends channel init command */
523 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_IBF);
524 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0x00);
525
526 /* BMC receives host channel init request */
527 mctp_astlpc_poll(bmc.astlpc);
528
529 /* BMC sends init response */
530 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF);
531 assert(kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_CHANNEL_ACTIVE);
532 assert(kcs[MCTP_ASTLPC_KCS_REG_DATA] == 0xff);
533
534 /* Host dequeues data */
535 mctp_astlpc_poll(host.astlpc);
536
537 endpoint_destroy(&bmc);
538 endpoint_destroy(&host);
539 free(lpc_mem);
540}
541
Andrew Jeffery55fb90b2020-05-12 13:54:37 +0930542static void astlpc_test_simple_indirect_message_bmc_to_host(void)
543{
544 struct astlpc_test ctx = { 0 };
545 uint8_t kcs[2] = { 0 };
546 uint8_t msg[MCTP_BTU];
547 int rc;
548
549 ctx.lpc_mem = calloc(1, LPC_WIN_SIZE);
550 assert(ctx.lpc_mem);
551
552 /* Test message data */
553 memset(&msg[0], 0x5a, MCTP_BTU);
554
555 /* Manually set up the network so we can inject the indirect ops */
556
557 /* BMC initialisation */
558 ctx.bmc.mmio.bmc = true;
559 ctx.bmc.mctp = mctp_init();
560 assert(ctx.bmc.mctp);
561 ctx.bmc.mmio.kcs = &kcs;
562 ctx.bmc.mmio.lpc = ctx.lpc_mem;
563 ctx.bmc.mmio.lpc_size = LPC_WIN_SIZE;
564 ctx.bmc.astlpc =
565 mctp_astlpc_init(MCTP_BINDING_ASTLPC_MODE_BMC, MCTP_BTU, NULL,
566 &astlpc_indirect_mmio_ops, &ctx.bmc.mmio);
567 mctp_register_bus(ctx.bmc.mctp, &ctx.bmc.astlpc->binding, 8);
568
569 /* Host initialisation */
570 ctx.host.mmio.bmc = false;
571 ctx.host.mctp = mctp_init();
572 assert(ctx.host.mctp);
573 ctx.host.mmio.kcs = &kcs;
574 ctx.host.mmio.lpc = ctx.lpc_mem;
575 ctx.host.mmio.lpc_size = LPC_WIN_SIZE;
576 ctx.host.astlpc =
577 mctp_astlpc_init(MCTP_BINDING_ASTLPC_MODE_HOST, MCTP_BTU, NULL,
578 &astlpc_indirect_mmio_ops, &ctx.host.mmio);
579 mctp_register_bus(ctx.host.mctp, &ctx.host.astlpc->binding, 9);
580
581 /* BMC processes host channel init request, alerts host */
582 mctp_astlpc_poll(ctx.bmc.astlpc);
583
584 /* Host dequeues channel init result */
585 mctp_astlpc_poll(ctx.host.astlpc);
586
587 ctx.msg = &msg[0];
588 ctx.count = 0;
589 mctp_set_rx_all(ctx.host.mctp, rx_message, &ctx);
590
591 /* BMC sends the single-packet message */
592 rc = mctp_message_tx(ctx.bmc.mctp, 9, msg, sizeof(msg));
593 assert(rc == 0);
594
595 /* Host receives the single-packet message */
596 rc = mctp_astlpc_poll(ctx.host.astlpc);
597 assert(rc == 0);
598 assert(ctx.count == 1);
599
600 /* BMC dequeues ownership hand-over and sends the queued packet */
601 rc = mctp_astlpc_poll(ctx.bmc.astlpc);
602 assert(rc == 0);
603
604 /* Can still tear-down the network in the normal fashion */
605 network_destroy(&ctx);
606}
607
Andrew Jefferyd0f5da02020-05-28 09:12:55 +0930608static void astlpc_test_host_tx_bmc_gone(void)
609{
610 struct astlpc_test ctx = { 0 };
611 uint8_t unwritten[MCTP_BTU];
612 uint8_t msg[MCTP_BTU];
613 int rc;
614
615 /* Test harness initialisation */
616
617 network_init(&ctx);
618
619 memset(&msg[0], 0x5a, sizeof(msg));
620 memset(&unwritten[0], 0, sizeof(unwritten));
621
622 ctx.msg = &msg[0];
623 ctx.count = 0;
624
625 /* Clear bmc-ready */
626 endpoint_destroy(&ctx.bmc);
627
628 /* Host detects that the BMC is disabled */
629 mctp_astlpc_poll(ctx.host.astlpc);
630
631 /* Host attempts to send the single-packet message, but is prevented */
632 rc = mctp_message_tx(ctx.host.mctp, 8, msg, sizeof(msg));
633 assert(rc == 0);
634 assert(!(ctx.kcs[MCTP_ASTLPC_KCS_REG_STATUS] & KCS_STATUS_OBF));
635 astlpc_assert_tx_packet(&ctx.host, &unwritten[0], MCTP_BTU);
636
637 /* BMC comes back */
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930638 rc = endpoint_init(&ctx.bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &ctx.kcs,
639 ctx.lpc_mem);
640 assert(!rc);
Andrew Jefferyd0f5da02020-05-28 09:12:55 +0930641 mctp_set_rx_all(ctx.bmc.mctp, rx_message, &ctx);
642
643 /* Host triggers channel init */
644 mctp_astlpc_poll(ctx.host.astlpc);
645
646 /* BMC handles channel init */
647 mctp_astlpc_poll(ctx.bmc.astlpc);
648
649 /* Host completes channel init, flushing the Tx queue */
650 mctp_astlpc_poll(ctx.host.astlpc);
651
652 /* BMC receives the single-packet message */
653 mctp_astlpc_poll(ctx.bmc.astlpc);
654 assert(ctx.count == 1);
655
656 network_destroy(&ctx);
657}
658
Andrew Jefferyf3d94dc2020-05-28 10:50:18 +0930659static void astlpc_test_poll_not_ready(void)
660{
661 struct astlpc_endpoint bmc;
662 uint8_t kcs[2] = { 0 };
663 void *lpc_mem;
664 int rc;
665
666 /* Test harness initialisation */
667 lpc_mem = calloc(1, 1 * 1024 * 1024);
668 assert(lpc_mem);
669
670 /* BMC initialisation */
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930671 rc = endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs,
672 lpc_mem);
673 assert(!rc);
Andrew Jefferyf3d94dc2020-05-28 10:50:18 +0930674
675 /* Check for a command despite none present */
676 rc = mctp_astlpc_poll(bmc.astlpc);
677
678 /* Make sure it doesn't fail */
679 assert(rc == 0);
680
681 endpoint_destroy(&bmc);
682 free(lpc_mem);
683}
684
Andrew Jeffery67655e82020-05-28 10:51:27 +0930685static void astlpc_test_undefined_command(void)
686{
687 struct astlpc_endpoint bmc;
688 uint8_t kcs[2] = { 0 };
689 void *lpc_mem;
690 int rc;
691
692 /* Test harness initialisation */
693 lpc_mem = calloc(1, 1 * 1024 * 1024);
694 assert(lpc_mem);
695
696 /* BMC initialisation */
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930697 rc = endpoint_init(&bmc, 8, MCTP_BINDING_ASTLPC_MODE_BMC, &kcs,
698 lpc_mem);
699 assert(!rc);
Andrew Jeffery67655e82020-05-28 10:51:27 +0930700
701 /* 0x5a isn't legal in v1 or v2 */
702 kcs[MCTP_ASTLPC_KCS_REG_DATA] = 0x5a;
703 kcs[MCTP_ASTLPC_KCS_REG_STATUS] |= KCS_STATUS_IBF;
704
705 /* Check for a command despite none present */
706 rc = mctp_astlpc_poll(bmc.astlpc);
707
708 /* Make sure it doesn't fail, bad command should be discarded */
709 assert(rc == 0);
710
711 endpoint_destroy(&bmc);
712 free(lpc_mem);
713}
714
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930715/* clang-format off */
716#define TEST_CASE(test) { #test, test }
717static const struct {
718 const char *name;
719 void (*test)(void);
720} astlpc_tests[] = {
721 TEST_CASE(astlpc_test_simple_init),
Andrew Jeffery4e8264b2020-05-23 20:34:33 +0930722 TEST_CASE(astlpc_test_bad_version),
723 TEST_CASE(astlpc_test_incompatible_versions),
724 TEST_CASE(astlpc_test_choose_bmc_ver_cur),
725 TEST_CASE(astlpc_test_choose_host_ver_cur),
726 TEST_CASE(astlpc_test_version_host_fails_negotiation),
727 TEST_CASE(astlpc_test_version_bmc_fails_negotiation),
Andrew Jefferyf1cdb162020-05-23 21:25:21 +0930728 TEST_CASE(astlpc_test_host_before_bmc),
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930729 TEST_CASE(astlpc_test_simple_message_bmc_to_host),
Andrew Jefferyec9a0062020-05-22 21:21:55 +0930730 TEST_CASE(astlpc_test_simple_message_host_to_bmc),
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930731 TEST_CASE(astlpc_test_packetised_message_bmc_to_host),
Andrew Jefferyd0f5da02020-05-28 09:12:55 +0930732 TEST_CASE(astlpc_test_simple_indirect_message_bmc_to_host),
733 TEST_CASE(astlpc_test_host_tx_bmc_gone),
Andrew Jefferyf3d94dc2020-05-28 10:50:18 +0930734 TEST_CASE(astlpc_test_poll_not_ready),
Andrew Jeffery67655e82020-05-28 10:51:27 +0930735 TEST_CASE(astlpc_test_undefined_command),
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930736};
737/* clang-format on */
738
739#ifndef BUILD_ASSERT
740#define BUILD_ASSERT(x) \
741 do { \
742 (void)sizeof(char[0 - (!(x))]); \
743 } while (0)
744#endif
745
Andrew Jefferye756de82020-05-22 12:30:58 +0930746int main(void)
747{
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930748 size_t i;
749
Andrew Jefferye756de82020-05-22 12:30:58 +0930750 mctp_set_log_stdio(MCTP_LOG_DEBUG);
751
Andrew Jeffery91f09ed2020-05-22 20:52:26 +0930752 BUILD_ASSERT(ARRAY_SIZE(astlpc_tests) < SIZE_MAX);
753 for (i = 0; i < ARRAY_SIZE(astlpc_tests); i++) {
754 mctp_prlog(MCTP_LOG_DEBUG, "begin: %s", astlpc_tests[i].name);
755 astlpc_tests[i].test();
756 mctp_prlog(MCTP_LOG_DEBUG, "end: %s\n", astlpc_tests[i].name);
757 }
Andrew Jeffery11b7e922020-03-10 23:37:09 +1030758
Andrew Jeffery0247c732020-02-06 11:48:52 +1030759 return 0;
760}