1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2019-2020 Intel Corporation. All rights reserved.
4 //
5 // Author: Jakub Dabek <jakub.dabek@linux.intel.com>
6 // Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com>
7 
8 #include <errno.h>
9 #include <rtos/alloc.h>
10 #include <rtos/timer.h>
11 #include <sof/lib/mm_heap.h>
12 #include <sof/ipc/topology.h>
13 #include <sof/ipc/msg.h>
14 #include <sof/ipc/driver.h>
15 #include <sof/schedule/edf_schedule.h>
16 #include <sof/schedule/ll_schedule.h>
17 #include <sof/schedule/schedule.h>
18 #include <rtos/spinlock.h>
19 #include <sof/audio/component_ext.h>
20 #include <rtos/clk.h>
21 #include <sof/lib/notifier.h>
22 #include <rtos/wait.h>
23 #include <arch/lib/cpu.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stddef.h>
27 #include <setjmp.h>
28 #include <stdint.h>
29 #include <cmocka.h>
30 
31 #define WEAK __attribute__((weak))
32 
33 /* global contexts */
34 WEAK struct ipc *_ipc;
35 #ifndef __ZEPHYR__
36 WEAK struct timer *platform_timer;
37 #endif
38 WEAK struct schedulers *schedulers;
39 WEAK struct sof sof;
40 WEAK struct tr_ctx buffer_tr;
41 WEAK struct tr_ctx comp_tr;
42 WEAK struct tr_ctx ipc_tr;
43 
rballoc_align(uint32_t flags,uint32_t caps,size_t bytes,uint32_t alignment)44 void WEAK *rballoc_align(uint32_t flags, uint32_t caps, size_t bytes,
45 			 uint32_t alignment)
46 {
47 	(void)flags;
48 	(void)caps;
49 
50 	return calloc(bytes, 1);
51 }
52 
rzalloc(enum mem_zone zone,uint32_t flags,uint32_t caps,size_t bytes)53 void WEAK *rzalloc(enum mem_zone zone, uint32_t flags, uint32_t caps,
54 		   size_t bytes)
55 {
56 	(void)zone;
57 	(void)flags;
58 	(void)caps;
59 
60 	return calloc(bytes, 1);
61 }
62 
rbrealloc_align(void * ptr,uint32_t flags,uint32_t caps,size_t bytes,size_t old_bytes,uint32_t alignment)63 void WEAK *rbrealloc_align(void *ptr, uint32_t flags, uint32_t caps,
64 			   size_t bytes, size_t old_bytes, uint32_t alignment)
65 {
66 	(void)flags;
67 	(void)caps;
68 	(void)old_bytes;
69 
70 	return realloc(ptr, bytes);
71 }
72 
rfree(void * ptr)73 void WEAK rfree(void *ptr)
74 {
75 	free(ptr);
76 }
77 
memcpy_s(void * dest,size_t dest_size,const void * src,size_t count)78 int WEAK memcpy_s(void *dest, size_t dest_size,
79 		  const void *src, size_t count)
80 {
81 	if (!dest || !src)
82 		return -EINVAL;
83 
84 	if ((dest >= src && (char *)dest < ((char *)src + count)) ||
85 	    (src >= dest && (char *)src < ((char *)dest + dest_size)))
86 		return -EINVAL;
87 
88 	if (count > dest_size)
89 		return -EINVAL;
90 
91 	memcpy(dest, src, count);
92 
93 	return 0;
94 }
95 
memset_s(void * dest,size_t size1,int c,size_t size2)96 int WEAK memset_s(void *dest, size_t size1,
97 		  int c, size_t size2)
98 {
99 	if (!dest)
100 		return -EINVAL;
101 
102 	memset(dest, c, size1);
103 
104 	return 0;
105 }
106 
rstrlen(const char * s)107 int WEAK rstrlen(const char *s)
108 {
109 	return strlen(s);
110 }
111 
__panic(uint32_t p,char * filename,uint32_t linenum)112 void WEAK __panic(uint32_t p, char *filename, uint32_t linenum)
113 {
114 	fail_msg("panic: %s:%d (code 0x%x)\n", filename, linenum, p);
115 	exit(EXIT_FAILURE);
116 }
117 
118 #if CONFIG_TRACE
trace_log_filtered(bool send_atomic,const void * log_entry,const struct tr_ctx * ctx,uint32_t lvl,uint32_t id_1,uint32_t id_2,int arg_count,va_list args)119 void WEAK trace_log_filtered(bool send_atomic, const void *log_entry, const struct tr_ctx *ctx,
120 			     uint32_t lvl, uint32_t id_1, uint32_t id_2, int arg_count,
121 			     va_list args)
122 {
123 	(void) send_atomic;
124 	(void) log_entry;
125 	(void) ctx;
126 	(void) lvl;
127 	(void) id_1;
128 	(void) id_2;
129 	(void) arg_count;
130 	(void) args;
131 }
132 
_log_sofdict(log_func_t sofdict_logf,bool atomic,const void * log_entry,const struct tr_ctx * ctx,const uint32_t lvl,uint32_t id_1,uint32_t id_2,int arg_count,...)133 void WEAK _log_sofdict(log_func_t sofdict_logf, bool atomic, const void *log_entry,
134 		       const struct tr_ctx *ctx, const uint32_t lvl,
135 		       uint32_t id_1, uint32_t id_2, int arg_count, ...)
136 {
137 }
138 
trace_flush_dma_to_mbox(void)139 void WEAK trace_flush_dma_to_mbox(void)
140 {
141 }
142 #endif
143 
144 #if CONFIG_LIBRARY
145 volatile void *task_context_get(void);
146 #endif
task_context_get(void)147 volatile void * WEAK task_context_get(void)
148 {
149 	return NULL;
150 }
151 
152 #ifndef __ZEPHYR__
_k_spin_lock_irq(struct k_spinlock * lock)153 uint32_t WEAK _k_spin_lock_irq(struct k_spinlock *lock)
154 {
155 	(void)lock;
156 
157 	return 0;
158 }
159 
_k_spin_unlock_irq(struct k_spinlock * lock,uint32_t flags,int line)160 void WEAK _k_spin_unlock_irq(struct k_spinlock *lock, uint32_t flags, int line)
161 {
162 	(void)lock;
163 	(void)flags;
164 	(void)line;
165 }
166 #endif
167 
platform_timer_get(struct timer * timer)168 uint64_t WEAK platform_timer_get(struct timer *timer)
169 {
170 	(void)timer;
171 
172 	return 0;
173 }
174 
175 #if !CONFIG_LIBRARY
arch_timer_get_system(struct timer * timer)176 uint64_t WEAK arch_timer_get_system(struct timer *timer)
177 {
178 	(void)timer;
179 
180 	return 0;
181 }
182 #endif
183 
184 #if CONFIG_LIBRARY
185 void WEAK arch_dump_regs_a(void *dump_buf);
186 #endif
arch_dump_regs_a(void * dump_buf)187 void WEAK arch_dump_regs_a(void *dump_buf)
188 {
189 	(void)dump_buf;
190 }
191 
heap_trace_all(int force)192 void WEAK heap_trace_all(int force)
193 {
194 	(void)force;
195 }
196 
ipc_msg_send(struct ipc_msg * msg,void * data,bool high_priority)197 void WEAK ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority)
198 {
199 	(void)msg;
200 	(void)data;
201 	(void)high_priority;
202 }
203 
platform_ipc_init(struct ipc * ipc)204 int WEAK platform_ipc_init(struct ipc *ipc)
205 {
206 	return 0;
207 }
208 
ipc_platform_do_cmd(struct ipc * ipc)209 enum task_state WEAK ipc_platform_do_cmd(struct ipc *ipc)
210 {
211 	return 0;
212 }
213 
ipc_platform_complete_cmd(struct ipc * ipc)214 void WEAK ipc_platform_complete_cmd(struct ipc *ipc)
215 {
216 }
217 
218 #if !CONFIG_LIBRARY
ipc_platform_send_msg(const struct ipc_msg * msg)219 int WEAK ipc_platform_send_msg(const struct ipc_msg *msg)
220 {
221 	return 0;
222 }
223 
wait_delay(uint64_t number_of_clks)224 void WEAK wait_delay(uint64_t number_of_clks)
225 {
226 }
227 
wait_delay_ms(uint64_t ms)228 void WEAK wait_delay_ms(uint64_t ms)
229 {
230 }
231 
wait_delay_us(uint64_t us)232 void WEAK wait_delay_us(uint64_t us)
233 {
234 }
235 
xthal_icache_region_invalidate(void * addr,unsigned size)236 void WEAK xthal_icache_region_invalidate(void *addr, unsigned size)
237 {
238 }
239 
xthal_dcache_region_invalidate(void * addr,unsigned size)240 void WEAK xthal_dcache_region_invalidate(void *addr, unsigned size)
241 {
242 }
243 
xthal_dcache_region_writeback(void * addr,unsigned size)244 void WEAK xthal_dcache_region_writeback(void *addr, unsigned size)
245 {
246 }
247 
xthal_dcache_region_writeback_inv(void * addr,unsigned size)248 void WEAK xthal_dcache_region_writeback_inv(void *addr, unsigned size)
249 {
250 }
251 #endif
252 
sof_get(void)253 struct sof * WEAK sof_get(void)
254 {
255 	return &sof;
256 }
257 
arch_schedulers_get(void)258 struct schedulers ** WEAK arch_schedulers_get(void)
259 {
260 	return &schedulers;
261 }
262 
schedule_task_init(struct task * task,const struct sof_uuid_entry * uid,uint16_t type,uint16_t priority,enum task_state (* run)(void * data),void * data,uint16_t core,uint32_t flags)263 int WEAK schedule_task_init(struct task *task,
264 			    const struct sof_uuid_entry *uid, uint16_t type,
265 			    uint16_t priority, enum task_state (*run)(void *data),
266 			    void *data, uint16_t core, uint32_t flags)
267 {
268 	(void)task;
269 	(void)uid;
270 	(void)type;
271 	(void)priority;
272 	(void)run;
273 	(void)data;
274 	(void)core;
275 	(void)flags;
276 
277 	return 0;
278 }
279 
schedule_task_init_ll(struct task * task,const struct sof_uuid_entry * uid,uint16_t type,uint16_t priority,enum task_state (* run)(void * data),void * data,uint16_t core,uint32_t flags)280 int WEAK schedule_task_init_ll(struct task *task,
281 			       const struct sof_uuid_entry *uid, uint16_t type,
282 			       uint16_t priority, enum task_state (*run)(void *data),
283 			       void *data, uint16_t core, uint32_t flags)
284 {
285 	return 0;
286 }
287 
platform_host_timestamp(struct comp_dev * host,struct sof_ipc_stream_posn * posn)288 void WEAK platform_host_timestamp(struct comp_dev *host,
289 				  struct sof_ipc_stream_posn *posn)
290 {
291 	(void)host;
292 	(void)posn;
293 }
294 
platform_dai_timestamp(struct comp_dev * dai,struct sof_ipc_stream_posn * posn)295 void WEAK platform_dai_timestamp(struct comp_dev *dai,
296 				 struct sof_ipc_stream_posn *posn)
297 {
298 	(void)dai;
299 	(void)posn;
300 }
301 
ipc_get_comp_by_id(struct ipc * ipc,uint32_t id)302 struct ipc_comp_dev * WEAK ipc_get_comp_by_id(struct ipc *ipc, uint32_t id)
303 {
304 	(void)ipc;
305 	(void)id;
306 
307 	return NULL;
308 }
309 
ipc_get_comp_by_ppl_id(struct ipc * ipc,uint16_t type,uint32_t ppl_id)310 struct ipc_comp_dev *WEAK ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type,
311 						 uint32_t ppl_id)
312 {
313 	(void)ipc;
314 	(void)type;
315 	(void)ppl_id;
316 
317 	return NULL;
318 }
319 
crc32(uint32_t base,const void * data,uint32_t bytes)320 uint32_t WEAK crc32(uint32_t base, const void *data, uint32_t bytes)
321 {
322 	return 0;
323 }
324 
comp_set_state(struct comp_dev * dev,int cmd)325 int WEAK comp_set_state(struct comp_dev *dev, int cmd)
326 {
327 	return 0;
328 }
329 
330 #ifndef __ZEPHYR__
clock_ms_to_ticks(int clock,uint64_t ms)331 uint64_t WEAK clock_ms_to_ticks(int clock, uint64_t ms)
332 {
333 	(void)clock;
334 	(void)ms;
335 
336 	return 0;
337 }
338 
clock_us_to_ticks(int clock,uint64_t us)339 uint64_t WEAK clock_us_to_ticks(int clock, uint64_t us)
340 {
341 	(void)clock;
342 	(void)us;
343 
344 	return 0;
345 }
346 
clock_ns_to_ticks(int clock,uint64_t us)347 uint64_t WEAK clock_ns_to_ticks(int clock, uint64_t us)
348 {
349 	(void)clock;
350 	(void)us;
351 
352 	return 0;
353 }
354 #endif /* __ZEPHYR__ */
355 
356 #if CONFIG_MULTICORE && !CONFIG_LIBRARY
357 
idc_send_msg(struct idc_msg * msg,uint32_t mode)358 int WEAK idc_send_msg(struct idc_msg *msg, uint32_t mode)
359 {
360 	(void)msg;
361 	(void)mode;
362 
363 	return 0;
364 }
365 
arch_cpu_is_core_enabled(int id)366 int WEAK arch_cpu_is_core_enabled(int id)
367 {
368 	return 0;
369 }
370 
371 #endif
372 
373 #if CONFIG_LIBRARY
374 /* enable trace by default in testbench */
375 int WEAK test_bench_trace = 1;
376 int WEAK debug;
377 
378 /* ... but not always in unit tests */
379 #if CONFIG_TRACE
380 /* look up subsystem class name from table */
get_trace_class(uint32_t trace_class)381 char * WEAK get_trace_class(uint32_t trace_class)
382 {
383 	(void)trace_class;
384 	/* todo: trace class is deprecated,
385 	 * uuid should be used only
386 	 */
387 	return "unknown";
388 }
389 #endif
390 
get_library_mailbox(void)391 uint8_t * WEAK get_library_mailbox(void)
392 {
393 	return NULL;
394 }
395 #endif
396 
397 /*
398  * GCC xtensa requires us to fake some of the standard C library calls
399  * as this is "bare metal" support (i.e. with no host OS implementation
400  * methods for these calls).
401  *
402  * None of these IO calls are used in the Mocks for testing.
403  */
404 #if !CONFIG_LIBRARY && !__XCC__
405 void _exit(int status);
406 unsigned int _getpid_r(void);
407 int _kill_r(int id, int sig);
408 void _sbrk_r(int id);
409 int _fstat_r(int fd, void *buf);
410 int _open_r(const char *pathname, int flags);
411 int _write_r(int fd, char *buf, int count);
412 int _read_r(int fd, char *buf, int count);
413 int _lseek_r(int fd, int count);
414 int _close_r(int fd);
415 int _isatty(int fd);
416 
_exit(int status)417 void _exit(int status)
418 {
419 	while (1);
420 }
421 
_getpid_r(void)422 unsigned int _getpid_r(void)
423 {
424 	return 0;
425 }
426 
_kill_r(int id,int sig)427 int _kill_r(int id, int sig)
428 {
429 	return 0;
430 }
431 
_sbrk_r(int id)432 void _sbrk_r(int id)
433 {
434 }
435 
_fstat_r(int fd,void * buf)436 int _fstat_r(int fd, void *buf)
437 {
438 	return 0;
439 }
440 
_open_r(const char * pathname,int flags)441 int _open_r(const char *pathname, int flags)
442 {
443 	return 0;
444 }
445 
_write_r(int fd,char * buf,int count)446 int _write_r(int fd, char *buf, int count)
447 {
448 	return 0;
449 }
450 
_read_r(int fd,char * buf,int count)451 int _read_r(int fd, char *buf, int count)
452 {
453 	return 0;
454 }
455 
_lseek_r(int fd,int count)456 int _lseek_r(int fd, int count)
457 {
458 	return 0;
459 }
460 
_close_r(int fd)461 int _close_r(int fd)
462 {
463 	return 0;
464 }
465 
_isatty(int fd)466 int _isatty(int fd)
467 {
468 	return 0;
469 }
470 
471 /* TODO: work around some linker warnings. Both will need fixed for qemu. */
472 int _start = 0;
473 int *__errno _PARAMS ((void));
474 
475 /*
476  * TODO: Math support for GCC xtensa requires a little more work to use the
477  * newlib versions. This is just to build test only today !
478  */
479 double __floatsidf(int i);
480 double __divdf3(double a, double b);
481 int __ledf2(double a, double b);
482 int __eqdf2(double a, double b);
483 
__floatsidf(int i)484 double __floatsidf(int i)
485 {
486 	return i;
487 }
488 
__divdf3(double a,double b)489 double __divdf3(double a, double b)
490 {
491 	return a / b;
492 }
493 
__ledf2(double a,double b)494 int WEAK __ledf2(double a, double b)
495 {
496 	return a <= b ? 0 : 1;
497 }
498 
__eqdf2(double a,double b)499 int WEAK __eqdf2(double a, double b)
500 {
501 	return a == b ? 0 : 1;
502 }
503 #endif
504