1 /*
2 Copyright (c) 2018, MIPI Alliance, Inc.
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 
9 * Redistributions of source code must retain the above copyright
10   notice, this list of conditions and the following disclaimer.
11 
12 * Redistributions in binary form must reproduce the above copyright
13   notice, this list of conditions and the following disclaimer in
14   the documentation and/or other materials provided with the
15   distribution.
16 
17 * Neither the name of the copyright holder nor the names of its
18   contributors may be used to endorse or promote products derived
19   from this software without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 /*
35  * Contributors:
36  * Norbert Schulz (Intel Corporation) - Initial API and implementation
37  */
38 
39  /* Internal C-language API implementation */
40 
41 #include "mipi_syst.h"
42 #include "mipi_syst/message.h"
43 #include <limits.h>
44 
45 #if defined(MIPI_SYST_UNIT_TEST)
46 #define ASSERT_CHECK(x) ASSERT_EQ(x, true)
47 #else
48 #define ASSERT_CHECK(x)
49 #endif
50 
51 #if  MIPI_SYST_CONFORMANCE_LEVEL > 10
52 
53 #if !defined(MIPI_SYST_SCATTER_WRITE)
54 /**
55  * Default writer access is to call global state systh_writer pointer.
56  * Redefine this if you can avoid the function pointer overhead.
57  */
58 #define MIPI_SYST_SCATTER_WRITE(syst_handle, scatter_prog, data_ptr) \
59 	{ \
60 		(syst_handle)->systh_header->systh_writer( \
61 				(syst_handle), (scatter_prog), (data_ptr));\
62 	}
63 #endif
64 
65 /**
66  * predefined write scatter instructions defined in scatter_op table
67  */
68 enum syst_scatter_ops {
69 #if defined(MIPI_SYST_PCFG_ENABLE_ORIGIN_GUID)
70 	SCATTER_OP_GUID,
71 #endif
72 
73 #if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_RECORD)
74 	SCATTER_OP_LOC_FMT,
75 	SCATTER_OP_LOC_32,
76 	SCATTER_OP_LOC_64,
77 #endif
78 #if defined(MIPI_SYST_PCFG_LENGTH_FIELD)
79 	SCATTER_OP_LENGTH,
80 #endif
81 	SCATTER_OP_PAYLD_VAR,
82 	SCATTER_OP_CHECKSUM,
83 	SCATTER_OP_CATID_32,
84 	SCATTER_OP_CATID_64,
85 	SCATTER_OP_CATID_ARGS,
86 #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP)
87 	SCATTER_OP_CLOCK,
88 	SCATTER_OP_TS,
89 #endif
90 #if defined(MIPI_SYST_PCFG_ENABLE_BUILD_API)
91 	SCATTER_OP_VER_ID,
92 	SCATTER_OP_VER_TXT,
93 #endif
94 	SCATTER_OP_END
95 };
96 
97 /**
98  * Scatter instruction that describe the writing of SyS-T message descriptor
99  * members by the scatter write algorithm.
100  */
101 static const struct mipi_syst_scatter_prog scatter_ops[] = {
102 #if defined(MIPI_SYST_PCFG_ENABLE_ORIGIN_GUID)
103 
104 	{			/* SCATTER_OP_GUID */
105 	 MIPI_SYST_SCATTER_OP_64BIT,
106 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_guid),
107 	 2},
108 #endif
109 
110 #if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_RECORD)
111 	{			/* SCATTER_OP_LOC_FMT */
112 	 MIPI_SYST_SCATTER_OP_8BIT,
113 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_loc.el_format),
114 	 1},
115 	{			/* SCATTER_OP_LOC_32 */
116 	 MIPI_SYST_SCATTER_OP_32BIT,
117 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_loc.el_u),
118 	 1},
119 	{			/* SCATTER_OP_LOC_64 */
120 	 MIPI_SYST_SCATTER_OP_64BIT,
121 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_loc.el_u),
122 	 1},
123 #endif
124 #if defined(MIPI_SYST_PCFG_LENGTH_FIELD)
125 	{			/* SCATTER_OP_LENGTH */
126 	 MIPI_SYST_SCATTER_OP_16BIT,
127 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_len),
128 	 1},
129 #endif
130 	{			/* SCATTER_OP_PAYLD_VAR */
131 	 MIPI_SYST_SCATTER_OP_BLOB,
132 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_var),
133 	 0}
134 	,
135 	{			/* SCATTER_OP_PAYLD_CHECKSUM */
136 	 MIPI_SYST_SCATTER_OP_32BIT,
137 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_chk),
138 	 1}
139 	,
140 	{			/* SCATTER_OP_CATID_32 */
141 	 MIPI_SYST_SCATTER_OP_32BIT,
142 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_catid.id.sci_32),
143 	 1}
144 	,
145 	{			/* SCATTER_OP_CATID_64 */
146 	 MIPI_SYST_SCATTER_OP_64BIT,
147 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_catid.id.sci_64),
148 	 1}
149 	,
150 	{			/* SCATTER_OP_CATID_ARGS */
151 	 MIPI_SYST_SCATTER_OP_BLOB,
152 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_catid.param),
153 	 0}
154 	,
155 #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP)
156 	{		/* SCATTER_OP_CLOCK */
157 	 MIPI_SYST_SCATTER_OP_64BIT,
158 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_clock),
159 	 2}
160 	,
161 	{		/* SCATTER_OP_TS */
162 	 MIPI_SYST_SCATTER_OP_64BIT,
163 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_ts),
164 	 1}
165 	,
166 #endif /* defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) */
167 #if defined(MIPI_SYST_PCFG_ENABLE_BUILD_API)
168 	{ 			/* SCATTER_OP_VER_ID */
169 	 MIPI_SYST_SCATTER_OP_64BIT,
170 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_version.id),
171 	 1}
172 	,
173 	{			/* SCATTER_OP_VER_TXT */
174 	 MIPI_SYST_SCATTER_OP_BLOB,
175 	 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_version.text),
176 	 0}
177 	,
178 #endif /* defined(MIPI_SYST_PCFG_ENABLE_BUILD_API) */
179 
180 	{ /* SCATTER_OP_END */
181 	 MIPI_SYST_SCATTER_OP_END,
182 	 0,
183 	 0}
184 };
185 
186 
187 /**
188  * Add optional message components to the message descriptor
189  */
190 static
191 #if defined(MIPI_SYST_PCFG_ENABLE_INLINE)
192 MIPI_SYST_CC_INLINE
193 #endif
194 void
insert_optional_msg_components(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,mipi_syst_u16 len,struct mipi_syst_msgdsc * desc,struct mipi_syst_scatter_prog ** prog_ptr)195 insert_optional_msg_components(struct mipi_syst_handle* svh,
196 				 struct mipi_syst_msglocation* loc,
197 				 mipi_syst_u16 len,
198 				 struct mipi_syst_msgdsc *desc,
199 				 struct mipi_syst_scatter_prog **prog_ptr)
200 {
201 	struct mipi_syst_scatter_prog *prog = *prog_ptr;
202 
203 #if defined(MIPI_SYST_PCFG_ENABLE_ORIGIN_GUID)
204 	/* origin GUID  ? */
205     if (0 != desc->ed_tag.et_guid) {
206 		desc->ed_guid = svh->systh_guid;
207 		*prog++ = scatter_ops[SCATTER_OP_GUID];
208 	}
209 #endif
210 
211 #if defined(MIPI_SYST_PCFG_ENABLE_LOCATION_RECORD)
212 	/* location information ? */
213 	if ((struct mipi_syst_msglocation*) 0 != loc) {
214 		desc->ed_loc = *loc;
215 		desc->ed_tag.et_location = 1;
216 
217 		*prog++ = scatter_ops[SCATTER_OP_LOC_FMT];
218 		if (desc->ed_loc.el_format & 0x1)
219 			*prog++ = scatter_ops[SCATTER_OP_LOC_64];
220 		else
221 			*prog++ = scatter_ops[SCATTER_OP_LOC_32];
222 	}
223 #endif
224 
225 #if defined(MIPI_SYST_PCFG_LENGTH_FIELD)
226 	/* pay load length */
227 	if(0 != desc->ed_tag.et_length) {
228 		desc->ed_len = len;
229 		*prog++ = scatter_ops[SCATTER_OP_LENGTH];
230 	}
231 #endif
232 
233 #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP)
234 	if (desc->ed_tag.et_timestamp) {
235 		/* timestamp present */
236 		desc->ed_ts = MIPI_SYST_PLATFORM_CLOCK();
237 		*prog++ = scatter_ops[SCATTER_OP_TS];
238 	}
239 #endif /* defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) */
240 
241 	*prog_ptr = prog;
242 }
243 #endif
244 
245 #if defined(MIPI_SYST_PCFG_ENABLE_STRING_API)
246 
247 /**
248  * Write a string output message
249  *
250  * @param svh SyS-T handle
251  * @param loc Pointer to instrumentation location or null if no location
252  * @param type string message subtype
253  * @param severity severity level (0..7)
254  * @param len number of bytes to emit or 0 to send fixed size 32bytes
255  * @param str  pointer to UTF-8 string bytes
256  */
257 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_debug_string(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_subtype_string type,enum mipi_syst_severity severity,mipi_syst_u16 len,const char * str)258 mipi_syst_write_debug_string(struct mipi_syst_handle* svh,
259 			  struct mipi_syst_msglocation* loc,
260 			  enum mipi_syst_subtype_string type,
261 			  enum mipi_syst_severity severity,
262 			  mipi_syst_u16 len, const char *str)
263 {
264 	struct mipi_syst_msgdsc desc;
265 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
266 	struct mipi_syst_scatter_prog *prog_ptr = prog;
267 	mipi_syst_u64 errmsg;
268 
269 	if ((struct mipi_syst_handle*)0 == svh)
270 		return;
271 
272 	/* assign tag */
273 	desc.ed_tag = svh->systh_tag;
274 	desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING;
275 	desc.ed_tag.et_subtype = type;
276 	desc.ed_tag.et_severity = severity;
277 
278 	if ((const char *)0 == str) {
279 		desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM;
280 		errmsg =
281 #if defined(MIPI_SYST_BIG_ENDIAN)
282 			0x286e756c6c290000ull; /* == "(null)\0\0" */
283 #else
284 			0x0000296c6c756e28ull; /* == "(null)\0\0" */
285 #endif
286 		str = (char*)&errmsg;
287 		len = 7;
288 	}
289 	insert_optional_msg_components(svh, loc, len, &desc, &prog_ptr);
290 
291 	desc.ed_pld.data_var = (const mipi_syst_u8 *) str;
292 	*prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR];
293 	prog_ptr->sso_length = len;
294 	++prog_ptr;
295 
296 	*prog_ptr = scatter_ops[SCATTER_OP_END];
297 
298 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
299 
300 	/* call IO routine to dump out the message */
301 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
302 }
303 #endif				/* #if defined(MIPI_SYST_PCFG_ENABLE_STRING_API) */
304 
305 #if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API)
306 
307 /**
308  * Write 64-bit catalog message
309  *
310  * @param svh  SyS-T handle
311  * @param loc  Pointer to instrumentation location or null
312  * @param severity message severity level (0..7)
313  * @param catid catalog ID
314  */
315 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_catalog64_message(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u64 catid)316 mipi_syst_write_catalog64_message(struct mipi_syst_handle* svh,
317 			       struct mipi_syst_msglocation* loc,
318 			       enum mipi_syst_severity severity, mipi_syst_u64 catid)
319 {
320 	struct mipi_syst_msgdsc desc;
321 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
322 	struct mipi_syst_scatter_prog *prog_ptr = prog;
323 	mipi_syst_u16 paramlen;
324 
325 	if ((struct mipi_syst_handle*)0 == svh)
326 		return;
327 
328 	/* assign tag */
329 	desc.ed_tag = svh->systh_tag;
330 	desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG;
331 	desc.ed_tag.et_severity = severity;
332 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
333 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P64;
334 #else
335 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P32;
336 #endif
337 
338 	paramlen = (mipi_syst_u16)
339 		(svh->systh_param_count *  sizeof(mipi_syst_u32));
340 
341 	insert_optional_msg_components(
342 			svh, loc,
343 			sizeof(catid) + paramlen,
344 			&desc, &prog_ptr);
345 
346 	/* cat ID */
347 	desc.ed_pld.data_catid.id.sci_64 = catid;
348 	*prog_ptr++ = scatter_ops[SCATTER_OP_CATID_64];
349 
350 	/* parameters (if any) */
351 
352 	if (0 != paramlen) {
353 		mipi_syst_u32 *param;
354 		param = svh->systh_param;
355 		desc.ed_pld.data_catid.param = param;
356 		*prog_ptr = scatter_ops[SCATTER_OP_CATID_ARGS];
357 		prog_ptr->sso_length = paramlen;
358 		++prog_ptr;
359 #if defined(MIPI_SYST_BIG_ENDIAN)
360 		while(paramlen) {
361 			*param = MIPI_SYST_HTOLE32(*param);
362 			param++;
363 			paramlen-=sizeof(mipi_syst_u32);
364 		}
365 #endif
366 	}
367 
368 	*prog_ptr = scatter_ops[SCATTER_OP_END];
369 
370 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
371 
372 	/* call IO routine to dump out the message */
373 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
374 }
375 
376 #endif /* #if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API) */
377 
378 #if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API)
379 
380 /**
381  * Write 32-Bit catalog message
382  *
383  * @param svh  SyS-T handle
384  * @param loc  Pointer to instrumentation location or null
385  * @param severity message severity level (0..7)
386  * @param catid catalog ID
387  */
388 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_catalog32_message(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u32 catid)389 mipi_syst_write_catalog32_message(struct mipi_syst_handle* svh,
390 			       struct mipi_syst_msglocation* loc,
391 			       enum mipi_syst_severity severity, mipi_syst_u32 catid)
392 {
393 	struct mipi_syst_msgdsc desc;
394 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
395 	struct mipi_syst_scatter_prog *prog_ptr = prog;
396 	mipi_syst_u16 paramlen;
397 
398 	if ((struct mipi_syst_handle*)0 == svh)
399 		return;
400 
401 	/* assign tag */
402 	desc.ed_tag = svh->systh_tag;
403 	desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG;
404 	desc.ed_tag.et_severity = severity;
405 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
406 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P64;
407 #else
408 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P32;
409 #endif
410 
411 	paramlen = (mipi_syst_u16)
412 		(svh->systh_param_count *  sizeof(mipi_syst_u32));
413 
414 	insert_optional_msg_components(
415 			svh, loc,
416 			sizeof(catid) + paramlen,
417 			&desc, &prog_ptr);
418 
419 	/* cat ID */
420 	desc.ed_pld.data_catid.id.sci_32 = catid;
421 	*prog_ptr++ = scatter_ops[SCATTER_OP_CATID_32];
422 
423 	/* parameters (if any) */
424 
425 	if (0 != paramlen) {
426 		mipi_syst_u32 * param;
427 		param = svh->systh_param;
428 		desc.ed_pld.data_catid.param = param;
429 		*prog_ptr = scatter_ops[SCATTER_OP_CATID_ARGS];
430 		prog_ptr->sso_length = paramlen;
431 		++prog_ptr;
432 #if defined(MIPI_SYST_BIG_ENDIAN)
433 		while(paramlen) {
434 			*param = MIPI_SYST_HTOLE32(*param);
435 			param++;
436 			paramlen-=sizeof(mipi_syst_u32);
437 		}
438 #endif
439 	}
440 
441 	*prog_ptr = scatter_ops[SCATTER_OP_END];
442 
443 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
444 
445 	/* call IO routine to dump out the message */
446 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
447 }
448 
449 #endif /* #if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API) */
450 
451 #if defined(MIPI_SYST_PCFG_ENABLE_WRITE_API)
452 
453 /**
454  * Write raw data message
455  *
456  * @param svh  SyS-T handle
457  * @param loc  pointer to instrumentation location or null
458  * @param severity message severity level (0..7)
459  * @param protocol content protocol ID
460  * @param data pointer to raw data
461  * @param length number of bytes to send
462  */
463 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_raw_message(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u8 protocol,const void * data,mipi_syst_u16 length)464 mipi_syst_write_raw_message(struct mipi_syst_handle* svh,
465 			struct mipi_syst_msglocation* loc,
466 			enum mipi_syst_severity severity,
467 			mipi_syst_u8 protocol,
468 			const void *data, mipi_syst_u16 length)
469 {
470 	struct mipi_syst_msgdsc desc;
471 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
472 	struct mipi_syst_scatter_prog *prog_ptr = prog;
473 
474 	if ((struct mipi_syst_handle*)0 == svh)
475 		return;
476 
477 	/* assign tag */
478 	desc.ed_tag = svh->systh_tag;
479 	desc.ed_tag.et_type = MIPI_SYST_TYPE_RAW;
480 	desc.ed_tag.et_severity = severity;
481 	desc.ed_tag.et_subtype = protocol;
482 
483 	insert_optional_msg_components(svh, loc, length, &desc, &prog_ptr);
484 
485 	desc.ed_pld.data_var = data;
486 	*prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR];
487 	prog_ptr->sso_length = length;
488 	++prog_ptr;
489 
490 	*prog_ptr = scatter_ops[SCATTER_OP_END];
491 
492 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
493 
494 	/* call IO routine to dump out the message */
495 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
496 }
497 #endif /* defined(MIPI_SYST_PCFG_ENABLE_WRITE_API) */
498 
499 #if defined(MIPI_SYST_PCFG_ENABLE_BUILD_API)
500 
501 /**
502  * Write client build version message
503  *
504  * @param svh  SyS-T handle
505  * @param loc  pointer to instrumentation location or null
506  * @param severity message severity level (0..7)
507  * @param id 64-Bit version ID
508  * @param text pointer to UTF-8 version text
509  * @param length number of bytes to send
510  */
511 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_build_message(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u64 id,const char * text,mipi_syst_u16 length)512 mipi_syst_write_build_message(struct mipi_syst_handle* svh,
513 			struct mipi_syst_msglocation* loc,
514 			enum mipi_syst_severity severity,
515 			mipi_syst_u64 id,
516 			const char *text, mipi_syst_u16 length)
517 {
518 	struct mipi_syst_msgdsc desc;
519 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
520 	struct mipi_syst_scatter_prog *prog_ptr = prog;
521 
522 	if ((struct mipi_syst_handle*)0 == svh)
523 		return;
524 
525 	/* assign tag */
526 	desc.ed_tag = svh->systh_tag;
527 	desc.ed_tag.et_type = MIPI_SYST_TYPE_BUILD;
528 	desc.ed_tag.et_severity = severity;
529 	desc.ed_tag.et_subtype = MIPI_SYST_BUILD_ID_LONG;
530 
531 	insert_optional_msg_components(
532 		svh, loc, length + sizeof(id), &desc, &prog_ptr);
533 
534 	desc.ed_pld.data_version.id = id;
535 	*prog_ptr = scatter_ops[SCATTER_OP_VER_ID];
536 	++prog_ptr;
537 	if (0 != length) {
538 		desc.ed_pld.data_version.text = text;
539 		*prog_ptr = scatter_ops[SCATTER_OP_VER_TXT];
540 		prog_ptr->sso_length = length;
541 		++prog_ptr;
542 	}
543 	*prog_ptr = scatter_ops[SCATTER_OP_END];
544 
545 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
546 
547 	/* call IO routine to dump out the message */
548 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
549 }
550 #endif /* defined(MIPI_SYST_PCFG_ENABLE_BUILD_API) */
551 
552 #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP)
553 /**
554 * Write clock sync message
555 *
556 * @param svh SyS-T handle
557 * @param loc pointer to instrumentation location or null
558 * @param fmt clock sync message subtype
559 * @param clock_value 64-Bit clock value
560 * @param clock_freq 64-Bit clock frequency in herz
561 */
562 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_clock(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_subtype_clock fmt,mipi_syst_u64 clock_value,mipi_syst_u64 clock_freq)563 mipi_syst_write_clock(struct mipi_syst_handle* svh,
564 		struct mipi_syst_msglocation* loc,
565 		enum mipi_syst_subtype_clock fmt,
566 		mipi_syst_u64 clock_value,
567 		mipi_syst_u64 clock_freq)
568 {
569 	struct mipi_syst_msgdsc desc;
570 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
571 	struct mipi_syst_scatter_prog *prog_ptr;
572 
573 	if ((struct mipi_syst_handle*)0 == svh)
574 		return;
575 
576 	prog_ptr = prog;
577 
578 	/* assign tag */
579 	desc.ed_tag = svh->systh_tag;
580 	desc.ed_tag.et_subtype = fmt;
581 	desc.ed_tag.et_type = MIPI_SYST_TYPE_CLOCK;
582 	desc.ed_tag.et_severity = MIPI_SYST_SEVERITY_MAX;
583 
584 	insert_optional_msg_components(
585 			svh, loc,
586 			2*sizeof(mipi_syst_u64),
587 			&desc, &prog_ptr);
588 
589 	desc.ed_pld.data_clock[0] = clock_value;
590 	desc.ed_pld.data_clock[1] = clock_freq;
591 	*prog_ptr++ = scatter_ops[SCATTER_OP_CLOCK];
592 
593 	*prog_ptr = scatter_ops[SCATTER_OP_END];
594 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
595 
596 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
597 }
598 
599 #endif /* defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) */
600 
601 #if defined(MIPI_SYST_PCFG_ENABLE_PRINTF_API)
602 
603 /* printf requires stdarg from the compiler in use. It is a varargs function*/
604 
605 #include <stdarg.h>
606 #include <stddef.h>
607 
608 #ifndef NO_WCHAR
609 #include <wchar.h>
610 #endif
611 
612 #if !defined(MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE)
613 #define MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE 1024  /* Default 1Kb arg buffer */
614 #endif
615 
616 /** state IDs of the printf format string parser's finite state machine
617  */
618 enum FmtScanState {
619 	START,
620 	PLAINTEXT,
621 	PERCENT,
622 	FLAGS,
623 	WIDTH, WIDTH_NUMBER,
624 	PRECISION_DOT, PRECISION_VAL, PRECISION_NUMBER,
625 	MODIFIER,
626 	MODIFIER_HALF,
627 	MODIFIER_LONG,
628 	SPECIFIER
629 };
630 
631 /** format modifier types
632  */
633 enum Modifier {
634 	MOD_NONE, MOD_HH, MOD_H, MOD_L, MOD_LL, MOD_J, MOD_Z, MOD_T, MOD_LD
635 };
636 
637 /** parser result codes
638  *
639  */
640 enum ReturnCodes {
641 	FMT_PARSE_OK = 1,
642 	FMT_PARSE_ARG_BUFFER_TOO_SMALL = -1,
643 	FMT_PARSE_UNSUPPORTED_FORMAT   = -2
644 };
645 
646 /* Helper macro to copy an argument from the arguments into the
647  * payload buffer.
648  *
649  *  TOTYPE is the data type that gets stored in the messages's arg buffer
650  *  FROMTYPE is the data type taken from the printf stack via varags
651  */
652 #define COPY_ARG_DOUBLE(TOTYPE, FROMTYPE)				\
653   do {									\
654     union {mipi_syst_u64 v; TOTYPE d;} val;				\
655     val.d = (TOTYPE)va_arg(args, FROMTYPE);				\
656     if (argp + sizeof(TOTYPE) < argEob) {				\
657       val.v = MIPI_SYST_HTOLE64(val.v);					\
658       memcpy(argp, &val.d, sizeof(TOTYPE));				\
659       argp += sizeof(TOTYPE);						\
660     } else {								\
661       return FMT_PARSE_ARG_BUFFER_TOO_SMALL;				\
662     }									\
663   } while(0)
664 
665 #define COPY_ARG32(TOTYPE, FROMTYPE)					\
666   do {									\
667     if (argp + sizeof(TOTYPE) < argEob) {				\
668       TOTYPE val = (TOTYPE)MIPI_SYST_HTOLE32(va_arg(args, FROMTYPE)); \
669       memcpy(argp, &val, sizeof(TOTYPE));				\
670       argp += sizeof(TOTYPE);						\
671     } else {								\
672       return FMT_PARSE_ARG_BUFFER_TOO_SMALL;				\
673     }									\
674   } while(0)
675 
676 #define COPY_ARG64(TOTYPE, FROMTYPE)					\
677   do {									\
678     if (argp + sizeof(TOTYPE) < argEob) {				\
679       TOTYPE val = (TOTYPE)MIPI_SYST_HTOLE64(va_arg(args, FROMTYPE)); \
680       memcpy(argp, &val, sizeof(TOTYPE));				\
681       argp += sizeof(TOTYPE);						\
682     } else {								\
683       return FMT_PARSE_ARG_BUFFER_TOO_SMALL;				\
684     }									\
685   } while(0)
686 
687 /** Create the payload buffer for a printf format
688  *
689  * The payload of a printf message, starts with an UTF-8 string,
690  * which becomes the printf format. Depending on the format string, further
691  * parameters follow the format string using the following rules:
692  *
693  * All printf arguments follow the format string without alignment bytes added.
694  * Strings for the '%s' format specifier are embedded as UTF-8 strings with
695  * 0-byte termination into the payload.
696  * printf arguments use the binary data layout as defined in the table below.
697  *
698  * Data Type                 |  32 Bit Platform   |   64 Bit Platform
699  * --------------------------|--------------------|---------------------------
700  * int, unsigned int         |   32 Bits          |   32 Bits
701  * long, unsigned long       |   32 Bits          |   64 Bits
702  * long long, unsinged long long|64 Bits          |   64 Bits
703  * size_t                    |   32 Bits          |   64 Bits
704  * ptrdiff_t                 |   32 Bits          |   64 Bits
705  * float double, long double |   64 Bits          |   64 Bits
706  * char, unsigned char       |   32 Bits          |   32 Bits
707  * wchar_t                   |   32 Bits          |   32 Bits
708  * Addresses(pointers)       |   32 Bits          |   64 Bits
709  * Strings (char *)          |UTF-8, 0-terminated |  UTF-8, 0-terminated
710  *
711  * The format string follows the C99 definition which can contain format
712  * specifier following this pattern:
713  *
714  *             %[flags][width][.precision][length]specifier
715  *
716  * This function 'only' converts the fmt and arguments into a message payload.
717  * The actual formatting of the data into a string is done by the receiving
718  * trace decoder.
719  *
720  * @param buffer memory buffer filled with argument data
721  * @param size   # of bytes in buffer
722  * @param fmt    printf format string
723  * @param args   printf varags
724 
725  */
buildPrintfPayload(char * buffer,mipi_syst_u32 size,const char * fmt,va_list args)726 static int buildPrintfPayload(
727 	char * buffer,
728 	mipi_syst_u32 size,
729 	const char * fmt,
730 	va_list args)
731 {
732 	char * argEob;
733 	char * argp;
734 	const char * fmtp;
735 	enum FmtScanState state;
736 	enum Modifier     modifier;
737 
738 	if (0 == fmt) return FMT_PARSE_UNSUPPORTED_FORMAT;
739 
740 	argp   = buffer;
741 	argEob = buffer + size;  /* end of buffer address */
742 	fmtp   = fmt;
743 
744 	/* copy argument string to start of payload buffer
745 	*/
746 	while (argp < argEob) {
747 		if( 0 == (*argp++ = *fmtp++)) break;
748 	}
749 	if (argp == argEob) return  FMT_PARSE_ARG_BUFFER_TOO_SMALL;
750 
751 	fmtp     = fmt;
752 	state    = START;
753 	modifier = MOD_NONE;
754 
755 	/* loop over the arguments in the format and full the arg buffer
756 	*/
757 	while( *fmtp != 0 )
758 	{
759 		switch(state) {
760 		case START:
761 			modifier      = MOD_NONE;
762 
763 			state = PLAINTEXT;
764 			; /* deliberate fall through */
765 
766 		case PLAINTEXT:
767 			if (*fmtp == '%') {
768 				state = PERCENT;
769 			}
770 			break;
771 
772 		case PERCENT:
773 			if (*fmtp == '%') { /* '%%' is not a format, but the % char */
774 				state = PLAINTEXT;
775 			} else {
776 				/* arg fmt definition is starting */
777 				state = FLAGS;
778 				continue;
779 			}
780 			break;
781 
782 		case FLAGS:
783 			switch(*fmtp) {
784 			case '-':
785 			case '+':
786 			case ' ':
787 			case '#':
788 			case '0':
789 				break;
790 			default:
791 				state = WIDTH;
792 				continue;
793 			}
794 			break;
795 
796 		case WIDTH:
797 			if (*fmtp == '*') {
798 				COPY_ARG32(mipi_syst_s32, int);
799 				state = PRECISION_DOT;
800 			} else {
801 				state = WIDTH_NUMBER;
802 				continue;
803 			}
804 			break;
805 
806 		case WIDTH_NUMBER:
807 			if (*fmtp < '0' || *fmtp > '9') {  /* !isdigit */
808 				state = PRECISION_DOT;
809 				continue;
810 			}
811 			break;
812 
813 		case PRECISION_DOT:
814 			if (*fmtp == '.') {
815 				state = PRECISION_VAL;
816 			} else {
817 				state = MODIFIER;
818 				continue;
819 			}
820 			break;
821 
822 		case PRECISION_VAL:
823 			if (*fmtp == '*') {
824 				COPY_ARG32(mipi_syst_s32, int);
825 				state = MODIFIER;
826 			} else {
827 				state = PRECISION_NUMBER;
828 				continue;
829 			}
830 			break;
831 
832 		case PRECISION_NUMBER:
833 			if (*fmtp < '0' || *fmtp > '9') {  /* !isdigit */
834 				state = MODIFIER;
835 				continue;
836 			}
837 			break;
838 
839 		case MODIFIER:
840 			state = SPECIFIER;
841 
842 			switch(*fmtp){
843 			case 'h':
844 				modifier = MOD_H;
845 				state = MODIFIER_HALF;
846 				break;
847 			case 'l':
848 				modifier = MOD_L;
849 				state = MODIFIER_LONG;
850 				break;
851 			case 'j':
852 				modifier = MOD_J;
853 				break;
854 			case 'z':
855 				modifier = MOD_Z;
856 				break;
857 			case 't':
858 				modifier = MOD_T;
859 				break;
860 			case 'L':
861 				modifier = MOD_LD;
862 				break;
863 			default:
864 				continue;
865 			}
866 			break;
867 
868 		case MODIFIER_HALF:
869 			state = SPECIFIER;
870 			if (*fmtp == 'h') {
871 				modifier = MOD_HH;
872 				break;
873 			} else {
874 				continue;
875 			}
876 			break;
877 
878 
879 		case MODIFIER_LONG:
880 			state = SPECIFIER;
881 			if (*fmtp == 'l') {
882 				modifier = MOD_LL;
883 				break;
884 			} else {
885 				continue;
886 			}
887 
888 		case SPECIFIER:
889 			{
890 				switch(*fmtp) {
891 				case 'd':
892 				case 'i':
893 				case 'u':
894 				case 'o':
895 				case 'x':
896 				case 'X':
897 					switch(modifier) {
898 					case MOD_L:
899 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
900 						COPY_ARG64(mipi_syst_u64, long);
901 #else
902 						COPY_ARG32(mipi_syst_u32, unsigned long);
903 #endif
904 						break;
905 					case MOD_LL:
906 					case MOD_J:
907 						COPY_ARG64(mipi_syst_u64, unsigned long long);
908 						break;
909 					case MOD_Z:
910 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
911 						COPY_ARG64(mipi_syst_u64, size_t);
912 #else
913 						COPY_ARG32(mipi_syst_u32, size_t);
914 #endif
915 						break;
916 					case MOD_T:
917 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
918 						COPY_ARG64(mipi_syst_s64, ptrdiff_t);
919 #else
920 						COPY_ARG32(mipi_syst_s32, ptrdiff_t);
921 #endif
922 						break;
923 					default:
924 						COPY_ARG32(mipi_syst_u32, unsigned int);
925 						break;
926 					}
927 					state = START;
928 					break;
929 				case 'f':
930 				case 'F':
931 				case 'e':
932 				case 'E':
933 				case 'g':
934 				case 'G':
935 				case 'a':
936 				case 'A':
937 					if (modifier == MOD_LD) {
938 						COPY_ARG_DOUBLE(double, long double); /* only double*/
939 					} else {
940 						COPY_ARG_DOUBLE(double, double);
941 					}
942 					break;
943 				case 'c':
944 					if (modifier == MOD_L) {
945 #if WCHAR_MAX == 0xFFFFU
946 					  /*
947 					   * Every va_arg has minimal size of 4 bytes.
948 					   * Some arch has wchar_t to be 16-bit (2 bytes),
949 					   * so promote to integer or else compiler will complain.
950 					   */
951 					  COPY_ARG32(mipi_syst_u32, int);
952 #else
953 					  COPY_ARG32(mipi_syst_u32, wchar_t);
954 #endif
955 					} else {
956 					  COPY_ARG32(mipi_syst_u32, int);
957 					}
958 					break;
959 				case 'p':
960 				case 'n':
961 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
962 				  COPY_ARG64(mipi_syst_u64, void *);
963 #else
964 				  COPY_ARG32(mipi_syst_u32, void *);
965 #endif
966 				  break;
967 				case 's':
968 					{
969 						/* Embed string with 0-byte into arg buffer */
970 						const char * p;
971 						p = va_arg(args, char *);
972 						while (argp < argEob) {
973 							if (0 == (*argp++ = *p++)) {
974 								break;
975 							}
976 							if (argp == argEob) {
977 								return  FMT_PARSE_ARG_BUFFER_TOO_SMALL;
978 							}
979 						}
980 					}
981 					break;
982 
983 				default:
984 					return FMT_PARSE_UNSUPPORTED_FORMAT;
985 					break;
986 				}
987 				state = START;
988 			}
989 			break;
990 		}
991 		++fmtp;
992 	}
993 
994 	if (state == START || state == PLAINTEXT) {
995 		return (int)(argp - buffer);
996 	} else {
997 		return FMT_PARSE_UNSUPPORTED_FORMAT;
998 	}
999 }
1000 #if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API) || defined(MIPI_SYST_PCFG_ENABLE_CATID32_API)
buildCatalogPayload(mipi_syst_u8 * buffer,mipi_syst_u32 size,va_list args)1001 static int buildCatalogPayload(
1002 	mipi_syst_u8 * buffer,
1003 	mipi_syst_u32 size,
1004 	va_list args)
1005 {
1006 	mipi_syst_u8 * argEob;
1007 	mipi_syst_u8 * argp;
1008 	int    argType;
1009 
1010 	argp   = buffer;
1011 	argEob = buffer + size;  /* end of buffer address */
1012 
1013 
1014 	/* loop over the argument types
1015 	*/
1016 	for(argType = va_arg(args, int);
1017 		argType != 0;
1018 		argType = va_arg(args, int))
1019 	{
1020 		switch(argType) {
1021 		case _MIPI_SYST_CATARG_D:
1022 			COPY_ARG32(mipi_syst_u32, unsigned int);
1023 			break;
1024 		case _MIPI_SYST_CATARG_LD:
1025 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1026 			COPY_ARG64(mipi_syst_u64, long);
1027 #else
1028 			COPY_ARG32(mipi_syst_u32, unsigned long);
1029 #endif
1030 			break;
1031 
1032 		case _MIPI_SYST_CATARG_LLD:
1033 			COPY_ARG64(mipi_syst_u64, unsigned long long);
1034 			break;
1035 
1036 		case _MIPI_SYST_CATARG_ZD:
1037 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1038 			COPY_ARG64(mipi_syst_u64, size_t);
1039 #else
1040 			COPY_ARG32(mipi_syst_u32, size_t);
1041 #endif
1042 			break;
1043 
1044 		case _MIPI_SYST_CATARG_TD:
1045 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1046 			COPY_ARG64(mipi_syst_s64, ptrdiff_t);
1047 #else
1048 			COPY_ARG32(mipi_syst_s32, ptrdiff_t);
1049 #endif
1050 			break;
1051 
1052 		case _MIPI_SYST_CATARG_F:
1053 			COPY_ARG_DOUBLE(double, double);
1054 			break;
1055 		case _MIPI_SYST_CATARG_LF:
1056 			COPY_ARG_DOUBLE(double, long double);
1057 			break;
1058 		case _MIPI_SYST_CATARG_C:
1059 			COPY_ARG32(mipi_syst_u32, int);
1060 			break;
1061 		case _MIPI_SYST_CATARG_HHD:
1062 			COPY_ARG32(mipi_syst_u32, int);
1063 			break;
1064 		case _MIPI_SYST_CATARG_LC:
1065 #if defined(_WCHAR_H) && (_WCHAR_H == 1)
1066 			COPY_ARG32(mipi_syst_u32, wint_t);
1067 #else
1068 			COPY_ARG32(mipi_syst_u32, unsigned int);
1069 #endif
1070 			break;
1071 
1072 		case _MIPI_SYST_CATARG_P:
1073 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1074 			COPY_ARG64(mipi_syst_u64, void *);
1075 #else
1076 			COPY_ARG32(mipi_syst_u32, void *);
1077 #endif
1078 			break;
1079 
1080 		case _MIPI_SYST_CATARG_CSTR:
1081 			{
1082 				const char * p;
1083 				p = va_arg(args, char *);
1084 				while (argp < argEob) {
1085 					if (0 == (*argp++ = *p++)) {
1086 						break;
1087 					}
1088 					if (argp == argEob) {
1089 						return  FMT_PARSE_ARG_BUFFER_TOO_SMALL;
1090 					}
1091 				}
1092 			}
1093 			break;
1094 
1095 		default:
1096 			return FMT_PARSE_UNSUPPORTED_FORMAT;
1097 			break;
1098 		}
1099 	}
1100 
1101 	return (int)(argp - buffer);
1102 }
1103 
1104 #endif // #if defined(MIPI_SYST_PCFG_ENABLE_CATIDxx_API)
1105 
1106 /**
1107  * Write a printf message
1108  *
1109  * @param svh SyS-T handle
1110  * @param loc Pointer to instrumentation location or null if no location
1111  * @param severity severity level (0..7)
1112  * @param fmt pointer to UTF-8 string bytes
1113  * @param args variable argument list of format arguments
1114  */
1115 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_vprintf_string(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,const char * fmt,va_list args)1116 	mipi_syst_write_vprintf_string(struct mipi_syst_handle* svh,
1117 	struct mipi_syst_msglocation* loc,
1118 	enum mipi_syst_severity severity,
1119 	const char *fmt,
1120 	va_list args)
1121 {
1122 	char argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE];
1123 	int len;
1124 	struct mipi_syst_msgdsc desc;
1125 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
1126 	struct mipi_syst_scatter_prog *prog_ptr = prog;
1127 	mipi_syst_u64 errmsg;
1128 
1129 	if ((struct mipi_syst_handle*)0 == svh)
1130 		return;
1131 
1132 	/* assign tag */
1133 	desc.ed_tag = svh->systh_tag;
1134 	desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING;
1135 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1136 	desc.ed_tag.et_subtype = MIPI_SYST_STRING_PRINTF_64;
1137 #else
1138 	desc.ed_tag.et_subtype = MIPI_SYST_STRING_PRINTF_32;
1139 #endif
1140 	desc.ed_tag.et_severity = severity;
1141 
1142 	len = buildPrintfPayload(argBuf, sizeof(argBuf), fmt, args);
1143 
1144 	if (len <= 0 ) {
1145 		/* Invalid format, send up to 32 bytes from the offending format string
1146 		 *  as string message with tag "invalid parameter" instead
1147 		*/
1148 		desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM;
1149 		errmsg =
1150 #if defined(MIPI_SYST_BIG_ENDIAN)
1151 		 0x286e756c6c290000ull; /* == "(null)\0\0" */
1152 #else
1153 		 0x0000296c6c756e28ull; /* == "(null)\0\0" */
1154 #endif
1155 		fmt = fmt ? fmt : (char*)&errmsg;
1156 
1157 		for (len = 0; len < 32;)
1158 			if (0 == fmt[len++]) break;
1159 	} else {
1160 		fmt = argBuf;
1161 	}
1162 	insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr);
1163 
1164 	*prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR];
1165 	desc.ed_pld.data_var = (const mipi_syst_u8 *) fmt;
1166 	prog_ptr->sso_length = (mipi_syst_u16)len;
1167 	++prog_ptr;
1168 	*prog_ptr = scatter_ops[SCATTER_OP_END];
1169 
1170 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
1171 
1172 	/* call IO routine to dump out the message */
1173 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
1174 }
1175 
1176 /**
1177  * Write a printf message
1178  *
1179  * @param svh SyS-T handle
1180  * @param loc Pointer to instrumentation location or null if no location
1181  * @param severity severity level (0..7)
1182  * @param fmt pointer to UTF-8 string bytes
1183  * @param ... optional format arguments
1184  */
1185 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_printf_string(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,const char * fmt,...)1186 	mipi_syst_write_printf_string(struct mipi_syst_handle* svh,
1187 	struct mipi_syst_msglocation* loc,
1188 	enum mipi_syst_severity severity,
1189 	const char *fmt,
1190 	...)
1191 {
1192 	va_list args;
1193 
1194 	va_start(args, fmt);
1195 	mipi_syst_write_vprintf_string(svh, loc, severity, fmt, args);
1196 	va_end(args);
1197 }
1198 
1199 #if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API)
1200 
1201 /**
1202  * Write a printf catalog message with 64bit ID
1203  *
1204  * @param svh SyS-T handle
1205  * @param loc Pointer to instrumentation location or null if no location
1206  * @param severity severity level (0..7)
1207  * @param id  catalog id
1208  */
1209 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_printf_catalog64(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u64 id,...)1210 	mipi_syst_write_printf_catalog64(struct mipi_syst_handle* svh,
1211 	struct mipi_syst_msglocation* loc,
1212 	enum mipi_syst_severity severity,
1213 	mipi_syst_u64 id,
1214 	...)
1215 {
1216 	mipi_syst_u8 argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE+sizeof(id)];
1217 	int len;
1218 	va_list args;
1219 	struct mipi_syst_msgdsc desc;
1220 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
1221 	struct mipi_syst_scatter_prog *prog_ptr = prog;
1222 	mipi_syst_u64 errmsg;
1223 
1224 	if ((struct mipi_syst_handle*)0 == svh)
1225 		return;
1226 
1227 	/* assign tag */
1228 	desc.ed_tag = svh->systh_tag;
1229 	desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG;
1230 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1231 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P64;
1232 #else
1233 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P32;
1234 #endif
1235 	desc.ed_tag.et_severity = severity;
1236 
1237 	va_start(args, id);
1238 	len = buildCatalogPayload(argBuf+sizeof(id),
1239 	                          MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE,
1240 	                          args);
1241 	va_end(args);
1242 
1243 	if (len < 0 ) {
1244 		char * msg;
1245 		errmsg =
1246 #if defined(MIPI_SYST_BIG_ENDIAN)
1247 			0x6361746172670000ull; /* = "catarg\0\0" */
1248 #else
1249 			0x0000677261746163ull; /* = "catarg\0\0" */
1250 #endif
1251 		/* Invalid parameter list */
1252 		desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING;
1253 		desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM;
1254 		len = 0;
1255 		msg = (char*)&errmsg;
1256 		while (0 != (argBuf[len++] = *msg++));
1257 	} else {
1258 	  *(mipi_syst_u64*)argBuf = MIPI_SYST_HTOLE64(id);
1259 		len += sizeof(id);
1260 	}
1261 
1262 	insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr);
1263 
1264 	*prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR];
1265 	desc.ed_pld.data_var = (const mipi_syst_u8 *) argBuf;
1266 	prog_ptr->sso_length = (mipi_syst_u16)len;
1267 	++prog_ptr;
1268 	*prog_ptr = scatter_ops[SCATTER_OP_END];
1269 
1270 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
1271 
1272 	/* call IO routine to dump out the message */
1273 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
1274 }
1275 
1276 /**
1277  * Write a printf catalog message with 64bit ID using a prepared arg list
1278  *
1279  * @param svh SyS-T handle
1280  * @param loc Pointer to instrumentation location or null if no location
1281  * @param severity severity level (0..7)
1282  * @param args pointer to prepared argument list
1283  * @param args_sz size of @p args (in bytes)
1284  */
1285 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_catalog64_args_copy(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u64 id,mipi_syst_u8 * args,size_t args_sz)1286 	mipi_syst_write_catalog64_args_copy(struct mipi_syst_handle* svh,
1287 	struct mipi_syst_msglocation* loc,
1288 	enum mipi_syst_severity severity,
1289 	mipi_syst_u64 id,
1290 	mipi_syst_u8 *args,
1291 	size_t args_sz)
1292 {
1293 	mipi_syst_u8 argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE+sizeof(id)];
1294 	int len;
1295 	struct mipi_syst_msgdsc desc;
1296 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
1297 	struct mipi_syst_scatter_prog *prog_ptr = prog;
1298 
1299 	if ((struct mipi_syst_handle*)0 == svh)
1300 		return;
1301 
1302 	if (args_sz >= MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE)
1303 		return;
1304 
1305 	/* assign tag */
1306 	desc.ed_tag = svh->systh_tag;
1307 	desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG;
1308 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1309 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P64;
1310 #else
1311 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID64_P32;
1312 #endif
1313 	desc.ed_tag.et_severity = severity;
1314 
1315 	memcpy(argBuf+sizeof(id), args, args_sz);
1316 
1317 	*(mipi_syst_u64*)argBuf = MIPI_SYST_HTOLE64(id);
1318 
1319 	len = sizeof(id) + args_sz;
1320 
1321 	insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr);
1322 
1323 	*prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR];
1324 	desc.ed_pld.data_var = (const mipi_syst_u8 *) argBuf;
1325 	prog_ptr->sso_length = (mipi_syst_u16)len;
1326 	++prog_ptr;
1327 	*prog_ptr = scatter_ops[SCATTER_OP_END];
1328 
1329 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
1330 
1331 	/* call IO routine to dump out the message */
1332 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
1333 }
1334 #endif // #if defined(MIPI_SYST_PCFG_ENABLE_CATID64_API)
1335 #if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API)
1336 
1337 /**
1338  * Write a printf catalog message with 32bit ID
1339  *
1340  * @param svh SyS-T handle
1341  * @param loc Pointer to instrumentation location or null if no location
1342  * @param severity severity level (0..7)
1343  * @param id  catalog id
1344  */
1345 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_printf_catalog32(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u32 id,...)1346 	mipi_syst_write_printf_catalog32(struct mipi_syst_handle* svh,
1347 	struct mipi_syst_msglocation* loc,
1348 	enum mipi_syst_severity severity,
1349 	mipi_syst_u32 id,
1350 	...)
1351 {
1352 	mipi_syst_u8 argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE+sizeof(id)];
1353 	int len;
1354 	va_list args;
1355 	struct mipi_syst_msgdsc desc;
1356 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
1357 	struct mipi_syst_scatter_prog *prog_ptr = prog;
1358 	mipi_syst_u64 errmsg;
1359 
1360 	if ((struct mipi_syst_handle*)0 == svh)
1361 		return;
1362 
1363 	/* assign tag */
1364 	desc.ed_tag = svh->systh_tag;
1365 	desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG;
1366 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1367 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P64;
1368 #else
1369 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P32;
1370 #endif
1371 	desc.ed_tag.et_severity = severity;
1372 
1373 	va_start(args, id);
1374 	len = buildCatalogPayload(argBuf+sizeof(id),
1375 			MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE,
1376 			args);
1377 	va_end(args);
1378 
1379 	if (len < 0 ) {
1380 		char * msg;
1381 		errmsg =
1382 #if defined(MIPI_SYST_BIG_ENDIAN)
1383 			0x6361746172670000ull; /* = "catarg\0\0" */
1384 #else
1385 			0x0000677261746163ull; /* = "catarg\0\0" */
1386 #endif
1387 		/* Invalid parameter list */
1388 		desc.ed_tag.et_type = MIPI_SYST_TYPE_STRING;
1389 		desc.ed_tag.et_subtype = MIPI_SYST_STRING_INVALIDPARAM;
1390 		len = 0;
1391 		msg = (char*)&errmsg;
1392 		while (0 != (argBuf[len++] = *msg++));
1393 	} else {
1394 	  *(mipi_syst_u32*)argBuf = MIPI_SYST_HTOLE32(id);
1395 		len += sizeof(id);
1396 	}
1397 
1398 	insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr);
1399 
1400 	*prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR];
1401 	desc.ed_pld.data_var = (const mipi_syst_u8 *) argBuf;
1402 	prog_ptr->sso_length = (mipi_syst_u16)len;
1403 	++prog_ptr;
1404 	*prog_ptr = scatter_ops[SCATTER_OP_END];
1405 
1406 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
1407 
1408 	/* call IO routine to dump out the message */
1409 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
1410 }
1411 
1412 /**
1413  * Write a printf catalog message with 32bit ID using a prepared argument list
1414  *
1415  * @param svh SyS-T handle
1416  * @param loc Pointer to instrumentation location or null if no location
1417  * @param severity severity level (0..7)
1418  * @param id  catalog id
1419  * @param args pointer to prepared argument list
1420  * @param args_sz size of @p args (in bytes)
1421  */
1422 MIPI_SYST_EXPORT void MIPI_SYST_CALLCONV
mipi_syst_write_catalog32_args_copy(struct mipi_syst_handle * svh,struct mipi_syst_msglocation * loc,enum mipi_syst_severity severity,mipi_syst_u32 id,mipi_syst_u8 * args,size_t args_sz)1423 	mipi_syst_write_catalog32_args_copy(struct mipi_syst_handle* svh,
1424 	struct mipi_syst_msglocation* loc,
1425 	enum mipi_syst_severity severity,
1426 	mipi_syst_u32 id,
1427 	mipi_syst_u8 *args,
1428 	size_t args_sz)
1429 {
1430 	mipi_syst_u8 argBuf[MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE+sizeof(id)];
1431 	int len;
1432 	struct mipi_syst_msgdsc desc;
1433 	struct mipi_syst_scatter_prog prog[MIPI_SYST_SCATTER_PROG_LEN];
1434 	struct mipi_syst_scatter_prog *prog_ptr = prog;
1435 
1436 	if ((struct mipi_syst_handle*)0 == svh)
1437 		return;
1438 
1439 	if (args_sz >= MIPI_SYST_PCFG_PRINTF_ARGBUF_SIZE)
1440 		return;
1441 
1442 	/* assign tag */
1443 	desc.ed_tag = svh->systh_tag;
1444 	desc.ed_tag.et_type = MIPI_SYST_TYPE_CATALOG;
1445 #if defined(MIPI_SYST_PCFG_ENABLE_64BIT_ADDR)
1446 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P64;
1447 #else
1448 	desc.ed_tag.et_subtype = MIPI_SYST_CATALOG_ID32_P32;
1449 #endif
1450 	desc.ed_tag.et_severity = severity;
1451 
1452 	memcpy(argBuf+sizeof(id), args, args_sz);
1453 
1454 	*(mipi_syst_u32*)argBuf = MIPI_SYST_HTOLE32(id);
1455 
1456 	len = sizeof(id) + args_sz;
1457 
1458 	insert_optional_msg_components(svh, loc, (mipi_syst_u16)len, &desc, &prog_ptr);
1459 
1460 	*prog_ptr = scatter_ops[SCATTER_OP_PAYLD_VAR];
1461 	desc.ed_pld.data_var = (const mipi_syst_u8 *) argBuf;
1462 	prog_ptr->sso_length = (mipi_syst_u16)len;
1463 	++prog_ptr;
1464 	*prog_ptr = scatter_ops[SCATTER_OP_END];
1465 
1466 	ASSERT_CHECK(prog_ptr < &prog[MIPI_SYST_SCATTER_PROG_LEN]);
1467 
1468 	/* call IO routine to dump out the message */
1469 	MIPI_SYST_SCATTER_WRITE(svh, prog, &desc);
1470 }
1471 #endif // #if defined(MIPI_SYST_PCFG_ENABLE_CATID32_API)
1472 #endif	/* #if defined(MIPI_SYST_PCFG_ENABLE_PRINTF_API) */