Software APIs
ujson_ottf.h
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_TEST_FRAMEWORK_UJSON_OTTF_H_
6 #define OPENTITAN_SW_DEVICE_LIB_TESTING_TEST_FRAMEWORK_UJSON_OTTF_H_
7 #include <stdint.h>
8 
9 #include "sw/device/lib/base/status.h"
11 #include "sw/device/lib/ujson/ujson.h"
12 
13 // Make sure not to derive implementation from this header.
14 #if defined(UJSON_SERDE_IMPL) && UJSON_SERDE_IMPL == 1
15 #define OLD_UJSON_SERDE_IMPL
16 #undef UJSON_SERDE_IMPL
17 #define UJSON_SERDE_IMPL 0
18 #endif
19 #include "sw/device/lib/testing/json/ottf.h"
20 #ifdef OLD_UJSON_SERDE_IMPL
21 #undef UJSON_SERDE_IMPL
22 #define UJSON_SERDE_IMPL 1
23 #endif
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /**
30  * Initializes and returns a ujson context linked to the OTTF console.
31  *
32  * @return An initialized ujson_t context.
33  */
34 ujson_t ujson_ottf_console(void);
35 
36 /**
37  * Deserialize a ujson message with a CRC.
38  * This macro will deserialize the message and then deserialize the CRC and
39  * check that it matches the CRC of the message. The CRC is itself deserialize
40  * as the ujson structure `ottf_crc_t`.
41  *
42  * @param deser_fn_ A pointer to the deserialization function generated by
43  * ujson_derive.
44  * @param uj_ctx_ A `ujson_t` representing the IO context.
45  * @param data_ A pointer to the data to send.
46  *
47  */
48 #define UJSON_WITH_CRC(deser_fn_, uj_ctx_, data_) \
49  ({ \
50  ujson_crc32_reset(uj_ctx_); \
51  status_t err = deser_fn_(uj_ctx_, data_); \
52  uint32_t msg_crc = ujson_crc32_finish(uj_ctx_); \
53  ottf_crc_t crc; \
54  if (status_ok(err)) { \
55  err = ujson_deserialize_ottf_crc_t(uj_ctx_, &crc); \
56  if (status_ok(err) && msg_crc != crc.crc) { \
57  err = DATA_LOSS(); \
58  } \
59  } \
60  err; \
61  })
62 
63 /**
64  * Add a CRC to the response.
65  * Should not be used directly.
66  * It is used by other macros such as `RESP_ERR`.
67  *
68  * @param uj_ctx_ A `ujson_t` representing the IO context.
69  */
70 #define RESP_CRC(uj_ctx_) \
71  ({ \
72  uint32_t crc = ujson_crc32_finish(uj_ctx_); \
73  TRY(ujson_putbuf(uj_ctx_, " CRC:", 5)); \
74  TRY(ujson_serialize_uint32_t(uj_ctx_, &crc)); \
75  TRY(ujson_putbuf(uj_ctx_, "\n", 1)); \
76  OK_STATUS(); \
77  })
78 
79 /**
80  * Respond with an OK result and JSON encoded data.
81  *
82  * @param responder_ A ujson serializer function for `data_`.
83  * @param uj_ctx_ A `ujson_t` representing the IO context.
84  * @param data_ A pointer to the data to send.
85  */
86 #define RESP_OK(responder_, uj_ctx_, data_) \
87  ({ \
88  TRY(ujson_putbuf(uj_ctx_, "RESP_OK:", 8)); \
89  ujson_crc32_reset(uj_ctx_); \
90  TRY(responder_(uj_ctx_, data_)); \
91  RESP_CRC(uj_ctx_); \
92  OK_STATUS(); \
93  })
94 
95 /**
96  * Respond with an OK result and JSON encoded OK_STATUS object.
97  *
98  * @param uj_ctx_ A `ujson_t` representing the IO context.
99  * @param args... An optional integer to be reported in the status.
100  */
101 #define RESP_OK_STATUS(uj_ctx_, ...) \
102  ({ \
103  status_t sts = OK_STATUS(__VA_ARGS__); \
104  RESP_OK(ujson_serialize_status_t, uj_ctx_, &sts); \
105  sts; \
106  })
107 
108 /**
109  * Respond with an ERR result and JSON encoded `status_t`.
110  *
111  * @param uj_ctx_ A `ujson_t` representing the IO context.
112  * @param expr_ An expression of type `status_t`.
113  */
114 #define RESP_ERR(uj_ctx_, expr_) \
115  do { \
116  status_t sts = expr_; \
117  if (!status_ok(sts)) { \
118  TRY(ujson_putbuf(uj_ctx_, "RESP_ERR:", 9)); \
119  TRY(ujson_serialize_status_t(uj_ctx_, &sts)); \
120  RESP_CRC(uj_ctx_); \
121  } \
122  } while (0)
123 
124 #ifdef __cplusplus
125 }
126 #endif
127 #endif // OPENTITAN_SW_DEVICE_LIB_TESTING_TEST_FRAMEWORK_UJSON_OTTF_H_