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 SCATTER_OP_CLOCK,
87 #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP)
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 { /* SCATTER_OP_CLOCK */
156 MIPI_SYST_SCATTER_OP_64BIT,
157 MIPI_SYST_EVDSC_MEMBER_OFF(ed_pld.data_clock),
158 2}
159 ,
160 #if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP) /* SCATTER_OP_TS */
161 {
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) */