2 * hl_api.c -- high-level Hostlink IO API.
4 * Copyright (c) 2024 Synopsys Inc.
6 * The authors hereby grant permission to use, copy, modify, distribute,
7 * and license this software and its documentation for any purpose, provided
8 * that existing copyright notices are retained in all copies and that this
9 * notice is included verbatim in any distributions. No written agreement,
10 * license, or royalty fee is required for any of the authorized uses.
11 * Modifications to this software may be copyrighted by their authors
12 * and need not follow the licensing terms described here, provided that
13 * the new terms are clearly indicated on the first page of each file where
24 /* Parameter types. */
32 /* Used internally to pass user hostlink parameters to _hl_message(). */
33 struct _hl_user_info
{
40 * Main function to send a message using hostlink.
42 * syscall - one of HL_SYSCALL_* defines from hl_api.h.
44 * user - parameters and return value for _user_hostlink implementation.
46 * uint32 vendor_id - user-defined vendor ID. ID 1025 is reserved for
48 * uint32 opcode - operation code for user-defined hostlink.
49 * char format[] - argument string in the same format as for
50 * _hl_message() function, see below.
52 * format - argument and return values format string [(i4sp)*:?(i4sp)*], where
53 * characters before ':' is arguments and after is return values.
54 * Supported format characters:
55 * i or 4 - uint32 value, pack_int will be used;
56 * s - char * data, pack_str will be used;
57 * p - void * data, pack_ptr will be used.
59 * ap - argument values and pointers to the output values. Must be in sync
61 * For hostlink message argument:
62 * i or 4 - uint32 value;
63 * s - char * pointer to the NUL-teminated string;
64 * p - void * pointer to the buffer and uint32 buffer length.
66 * i or 4 - uint32 * pointer to uint32 to return;
67 * s - char * pointer to buffer to return, it must have enough
68 * space to store returned data.
69 * You can get packed buffer length with _hl_get_ptr_len();
70 * p - void * pointer and uint32 * length pointer to store
71 * returned data along with length. Buffer must be enough
72 * to store returned data.
73 * You can get packed buffer length with _hl_get_ptr_len();
75 * return - pointer to the hostlink buffer after output values.
77 static volatile __uncached
char *
78 _hl_message_va (uint32_t syscall
, struct _hl_user_info
*user
,
79 const char *format
, va_list ap
)
81 const char *f
= format
;
82 volatile __uncached
char *p
= _hl_payload ();
85 p
= _hl_pack_int (p
, syscall
);
87 if (syscall
== HL_SYSCALL_USER
)
89 p
= _hl_pack_int (p
, user
->vendor_id
);
90 p
= _hl_pack_int (p
, user
->opcode
);
91 p
= _hl_pack_str (p
, format
);
110 p
= _hl_pack_int (p
, va_arg (ap
, uint32_t));
113 p
= _hl_pack_str (p
, va_arg (ap
, char *));
116 ptr
= va_arg (ap
, void *);
117 len
= va_arg (ap
, uint32_t);
118 p
= _hl_pack_ptr (p
, ptr
, len
);
132 if (syscall
== HL_SYSCALL_USER
&& p
)
133 p
= _hl_unpack_int (p
, &user
->result
);
146 p
= _hl_unpack_int (p
, va_arg (ap
, uint32_t *));
149 p
= _hl_unpack_str (p
, va_arg (ap
, char *));
152 ptr
= va_arg (ap
, void *);
153 plen
= va_arg (ap
, uint32_t *);
154 p
= _hl_unpack_ptr (p
, ptr
, plen
);
169 * Pack integer value (uint32) to provided buffer.
171 * uint16 type (PAT_INT = 3)
175 volatile __uncached
char *
176 _hl_pack_int (volatile __uncached
char *p
, uint32_t x
)
178 volatile __uncached
uint16_t *type
= (volatile __uncached
uint16_t *) p
;
179 volatile __uncached
uint16_t *size
= (volatile __uncached
uint16_t *)
181 volatile __uncached
uint32_t *val
= (volatile __uncached
uint32_t *)
183 const uint32_t payload_used
= 8;
185 if (_hl_payload_left (p
) < payload_used
)
192 return p
+ payload_used
;
196 * Pack data (pointer and legth) to provided buffer.
198 * uint16 type (PAT_STRING = 4)
199 * uint16 size (length)
202 volatile __uncached
char *
203 _hl_pack_ptr (volatile __uncached
char *p
, const void *s
, uint16_t len
)
205 volatile __uncached
uint16_t *type
= (volatile __uncached
uint16_t *) p
;
206 volatile __uncached
uint16_t *size
= (volatile __uncached
uint16_t *)
208 volatile __uncached
char *buf
= p
+ 4;
209 const uint32_t payload_used
= 4 + ALIGN (len
, 4);
211 if (_hl_payload_left (p
) < payload_used
)
217 /* _vdmemcpy(buf, s, len); */
218 for (uint16_t i
= 0; i
< len
; i
++)
219 buf
[i
] = ((const char *) s
)[i
];
221 return p
+ payload_used
;
225 * Pack NUL-terminated string to provided buffer.
227 * uint16 type (PAT_STRING = 4)
228 * uint16 size (length)
231 volatile __uncached
char *
232 _hl_pack_str (volatile __uncached
char *p
, const char *s
)
234 return _hl_pack_ptr (p
, s
, strlen (s
) + 1);
237 /* Unpack integer value (uint32_t) from a buffer. */
238 volatile __uncached
char *
239 _hl_unpack_int (volatile __uncached
char *p
, uint32_t *x
)
241 volatile __uncached
uint16_t *type
= (volatile __uncached
uint16_t *) p
;
242 volatile __uncached
uint16_t *size
= (volatile __uncached
uint16_t *)
244 volatile __uncached
uint32_t *val
= (volatile __uncached
uint32_t *)
246 const uint32_t payload_used
= 8;
248 if (_hl_payload_left (p
) < payload_used
|| *type
!= PAT_INT
|| *size
!= 4)
254 return p
+ payload_used
;
257 /* Unpack data from a buffer. */
258 volatile __uncached
char *
259 _hl_unpack_ptr (volatile __uncached
char *p
, void *s
, uint32_t *plen
)
261 volatile __uncached
uint16_t *type
= (volatile __uncached
uint16_t *) p
;
262 volatile __uncached
uint16_t *size
= (volatile __uncached
uint16_t *)
264 volatile __uncached
char *buf
= p
+ 4;
265 uint32_t payload_used
;
268 if (_hl_payload_left (p
) < 4 || *type
!= PAT_STRING
)
272 payload_used
= 4 + ALIGN (len
, 4);
274 if (_hl_payload_left (p
) < payload_used
)
280 /* _vsmemcpy(s, buf, len); */
283 for (uint32_t i
= 0; i
< len
; i
++)
284 ((char *) s
)[i
] = buf
[i
];
287 return p
+ payload_used
;
291 * Unpack data from a buffer.
293 * No difference compared to _hl_unpack_ptr, except that this function
294 * does not return a length.
296 volatile __uncached
char *
297 _hl_unpack_str (volatile __uncached
char *p
, char *s
)
299 return _hl_unpack_ptr (p
, s
, NULL
);
302 /* Return length of packed data (PAT_STRING) if it is on top of the buffer. */
304 _hl_get_ptr_len (volatile __uncached
char *p
)
306 volatile __uncached
uint16_t *type
= (volatile __uncached
uint16_t *) p
;
307 volatile __uncached
uint16_t *size
= (volatile __uncached
uint16_t *)
310 if (_hl_payload_left (p
) < 4 || *type
!= PAT_STRING
)
316 /* Public version of _hl_message_va(). */
317 volatile __uncached
char *
318 _hl_message (uint32_t syscall
, const char *format
, ...)
321 volatile __uncached
char *p
;
323 va_start (ap
, format
);
325 p
= _hl_message_va (syscall
, 0, format
, ap
);
333 * API to call user-defined hostlink. See description of user argument in
337 _user_hostlink (uint32_t vendor
, uint32_t opcode
, const char *format
, ...)
340 struct _hl_user_info ui
= { .vendor_id
= vendor
,
343 va_start (ap
, format
);
345 _hl_message_va (HL_SYSCALL_USER
, &ui
, format
, ap
);