1 /*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2013-02-26 prife first version for win32
9 */
10
11 #include <rthw.h>
12 #include <rtthread.h>
13 #include <rtm.h>
14
15 #ifdef RT_USING_MODULE
16
17 #define DBG_TAG "simulator.module.win32"
18 #define DBG_LVL DBG_INFO
19 #include <rtdbg.h>
20
rt_module_init_object_container(struct rt_module * module)21 void rt_module_init_object_container(struct rt_module *module)
22 {
23 RT_ASSERT(module != RT_NULL);
24
25 /* initialize object container - thread */
26 rt_list_init(&(module->module_object[RT_Object_Class_Thread].object_list));
27 module->module_object[RT_Object_Class_Thread].object_size = sizeof(struct rt_thread);
28 module->module_object[RT_Object_Class_Thread].type = RT_Object_Class_Thread;
29
30 #ifdef RT_USING_SEMAPHORE
31 /* initialize object container - semaphore */
32 rt_list_init(&(module->module_object[RT_Object_Class_Semaphore].object_list));
33 module->module_object[RT_Object_Class_Semaphore].object_size = sizeof(struct rt_semaphore);
34 module->module_object[RT_Object_Class_Semaphore].type = RT_Object_Class_Semaphore;
35 #endif
36
37 #ifdef RT_USING_MUTEX
38 /* initialize object container - mutex */
39 rt_list_init(&(module->module_object[RT_Object_Class_Mutex].object_list));
40 module->module_object[RT_Object_Class_Mutex].object_size = sizeof(struct rt_mutex);
41 module->module_object[RT_Object_Class_Mutex].type = RT_Object_Class_Mutex;
42 #endif
43
44 #ifdef RT_USING_EVENT
45 /* initialize object container - event */
46 rt_list_init(&(module->module_object[RT_Object_Class_Event].object_list));
47 module->module_object[RT_Object_Class_Event].object_size = sizeof(struct rt_event);
48 module->module_object[RT_Object_Class_Event].type = RT_Object_Class_Event;
49 #endif
50
51 #ifdef RT_USING_MAILBOX
52 /* initialize object container - mailbox */
53 rt_list_init(&(module->module_object[RT_Object_Class_MailBox].object_list));
54 module->module_object[RT_Object_Class_MailBox].object_size = sizeof(struct rt_mailbox);
55 module->module_object[RT_Object_Class_MailBox].type = RT_Object_Class_MailBox;
56 #endif
57
58 #ifdef RT_USING_MESSAGEQUEUE
59 /* initialize object container - message queue */
60 rt_list_init(&(module->module_object[RT_Object_Class_MessageQueue].object_list));
61 module->module_object[RT_Object_Class_MessageQueue].object_size = sizeof(struct rt_messagequeue);
62 module->module_object[RT_Object_Class_MessageQueue].type = RT_Object_Class_MessageQueue;
63 #endif
64
65 #ifdef RT_USING_MEMHEAP
66 /* initialize object container - memory heap */
67 rt_list_init(&(module->module_object[RT_Object_Class_MemHeap].object_list));
68 module->module_object[RT_Object_Class_MemHeap].object_size = sizeof(struct rt_memheap);
69 module->module_object[RT_Object_Class_MemHeap].type = RT_Object_Class_MemHeap;
70 #endif
71
72 #ifdef RT_USING_MEMPOOL
73 /* initialize object container - memory pool */
74 rt_list_init(&(module->module_object[RT_Object_Class_MemPool].object_list));
75 module->module_object[RT_Object_Class_MemPool].object_size = sizeof(struct rt_mempool);
76 module->module_object[RT_Object_Class_MemPool].type = RT_Object_Class_MemPool;
77 #endif
78
79 #ifdef RT_USING_DEVICE
80 /* initialize object container - device */
81 rt_list_init(&(module->module_object[RT_Object_Class_Device].object_list));
82 module->module_object[RT_Object_Class_Device].object_size = sizeof(struct rt_device);
83 module->module_object[RT_Object_Class_Device].type = RT_Object_Class_Device;
84 #endif
85
86 /* initialize object container - timer */
87 rt_list_init(&(module->module_object[RT_Object_Class_Timer].object_list));
88 module->module_object[RT_Object_Class_Timer].object_size = sizeof(struct rt_timer);
89 module->module_object[RT_Object_Class_Timer].type = RT_Object_Class_Timer;
90 }
91
92 #ifdef RT_USING_HOOK
93 static void (*rt_module_load_hook)(rt_module_t module);
94 static void (*rt_module_unload_hook)(rt_module_t module);
95
96 /**
97 * @addtogroup Hook
98 */
99
100 /*@{*/
101
102 /**
103 * This function will set a hook function, which will be invoked when module
104 * be loaded to system.
105 *
106 * @param hook the hook function
107 */
rt_module_load_sethook(void (* hook)(rt_module_t module))108 void rt_module_load_sethook(void (*hook)(rt_module_t module))
109 {
110 rt_module_load_hook = hook;
111 }
112
113 /**
114 * This function will set a hook function, which will be invoked when module
115 * be unloaded from system.
116 *
117 * @param hook the hook function
118 */
rt_module_unload_sethook(void (* hook)(rt_module_t module))119 void rt_module_unload_sethook(void (*hook)(rt_module_t module))
120 {
121 rt_module_unload_hook = hook;
122 }
123
124 /*@}*/
125 #endif
126
127 /**
128 * @ingroup SystemInit
129 *
130 * This function will initialize system module
131 */
rt_system_module_init(void)132 int rt_system_module_init(void)
133 {
134 return 0;
135 }
136
137 /**
138 * This function will return self module object
139 *
140 * @return the self module object
141 */
rt_module_self(void)142 rt_module_t rt_module_self(void)
143 {
144 rt_thread_t tid;
145
146 tid = rt_thread_self();
147 if (tid == RT_NULL)
148 return RT_NULL;
149
150 /* return current module */
151 return (rt_module_t)tid->parent.module_id;
152 }
153 RTM_EXPORT(rt_module_self);
154
155 /**
156 * This function will find the specified module.
157 *
158 * @param name the name of module finding
159 *
160 * @return the module
161 */
rt_module_find(const char * name)162 rt_module_t rt_module_find(const char *name)
163 {
164 struct rt_object_information *information;
165 struct rt_object *object;
166 struct rt_list_node *node;
167
168 RT_DEBUG_NOT_IN_INTERRUPT;
169
170 /* enter critical */
171 rt_enter_critical();
172
173 /* try to find device object */
174 information = rt_object_get_information(RT_Object_Class_Module);
175 RT_ASSERT(information != RT_NULL);
176
177 for (node = information->object_list.next;
178 node != &(information->object_list);
179 node = node->next)
180 {
181 object = rt_list_entry(node, struct rt_object, list);
182 if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
183 {
184 /* leave critical */
185 rt_exit_critical();
186
187 return (rt_module_t)object;
188 }
189 }
190
191 /* leave critical */
192 rt_exit_critical();
193
194 /* not found */
195 return RT_NULL;
196 }
197 RTM_EXPORT(rt_module_find);
198
199 #ifdef RT_USING_DFS
200 #include <windows.h>
201 #include <dfs_file.h>
202 #include <unistd.h>
203 #include <stdio.h>
204 #include <sys/stat.h>
205 #include <sys/statfs.h>
206 extern char * dfs_win32_dirdup(char * path);
_module_name(const char * path)207 static char* _module_name(const char *path)
208 {
209 const char *first, *end, *ptr;
210 char *name;
211 int size;
212
213 ptr = (char *)path;
214 first = ptr;
215 end = path + rt_strlen(path);
216
217 while (*ptr != '\0')
218 {
219 if (*ptr == '/')
220 first = ptr + 1;
221 if (*ptr == '.')
222 end = ptr - 1;
223
224 ptr ++;
225 }
226
227 size = end - first + 1;
228 name = rt_malloc(size);
229 rt_strncpy(name, first, size);
230 name[size] = '\0';
231
232 return name;
233 }
234
235 typedef int (*appentry_t)(void);
236 /**
237 * This function will load a module from a file
238 *
239 * @param path the full path of application module
240 *
241 * @return the module object
242 */
rt_module_open(const char * path)243 rt_module_t rt_module_open(const char *path)
244 {
245 struct dfs_filesystem *fs;
246 appentry_t fptr;
247 HINSTANCE hinstlib;
248 rt_module_t module;
249
250 char * winpath = RT_NULL;
251 char * name = RT_NULL;
252
253 RT_DEBUG_NOT_IN_INTERRUPT;
254
255 /* check parameters */
256 RT_ASSERT(path != RT_NULL);
257
258 /* app module should only in DFS_WIN32 */
259 fs = dfs_filesystem_lookup(path);
260 if ((fs == RT_NULL) || (strcmp(fs->ops->name,"wdir") != 0))
261 {
262 rt_kprintf("invalid path: %s\n", path);
263 return RT_NULL;
264 }
265
266 /* change path */
267 // len = strlen(path+1);
268 if ((winpath = dfs_win32_dirdup((char *)path)) == RT_NULL)
269 {
270 rt_kprintf("out of memory, exit");
271 return RT_NULL;
272 }
273
274 hinstlib = LoadLibrary(winpath);
275 if (hinstlib == NULL)
276 {
277 rt_kprintf("error: unable to open %s\n", winpath);
278 return RT_NULL;
279 }
280
281 fptr = (appentry_t)GetProcAddress(hinstlib, "main");
282 if (fptr == NULL)
283 {
284 rt_kprintf("error: unable to find function in %s\n", winpath);
285 FreeLibrary(hinstlib);
286 return RT_NULL;
287 }
288
289 /* get the name of the module */
290 name = _module_name(path);
291
292 /* allocate module */
293 module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
294 if (!module) return RT_NULL;
295
296 module->nref = 0;
297 module->module_entry = fptr;
298
299 /* init module object container */
300 rt_module_init_object_container(module);
301
302 /* increase module reference count */
303 module->nref ++;
304
305 if (module->module_entry != 0)
306 {
307 #ifdef RT_USING_SLAB
308 /* init module memory allocator */
309 module->mem_list = RT_NULL;
310
311 /* create page array */
312 module->page_array =
313 (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
314 module->page_cnt = 0;
315 #endif
316
317 /* create module thread */
318 module->module_thread =
319 rt_thread_create(name,
320 (void(*)(void *))module->module_entry, RT_NULL,
321 2048, RT_THREAD_PRIORITY_MAX - 2, 10);
322
323 LOG_D("thread entry %#x", module->module_entry);
324
325 /* set module id */
326 module->module_thread->parent.module_id = (void *)module;
327 module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
328
329 /* startup module thread */
330 rt_thread_startup(module->module_thread);
331 }
332 else
333 {
334 /* without entry point */
335 module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
336 }
337
338 #ifdef RT_USING_HOOK
339 if (rt_module_load_hook != RT_NULL)
340 {
341 rt_module_load_hook(module);
342 }
343 #endif
344
345 rt_free(name);
346 return module;
347 /* FreeLibrary(hinstlib); */
348 }
349
350 #if defined(RT_USING_FINSH)
351 #include <finsh.h>
352 FINSH_FUNCTION_EXPORT_ALIAS(rt_module_open, exec, exec module from a file);
353 #endif
354
355 #endif
356
357 #define RT_MODULE_ARG_MAX 8
_rt_module_split_arg(char * cmd,rt_size_t length,char * argv[])358 static int _rt_module_split_arg(char* cmd, rt_size_t length, char* argv[])
359 {
360 int argc = 0;
361 char *ptr = cmd;
362
363 while ((ptr - cmd) < length)
364 {
365 /* strip bank and tab */
366 while ((*ptr == ' ' || *ptr == '\t') && (ptr -cmd)< length)
367 *ptr++ = '\0';
368 /* check whether it's the end of line */
369 if ((ptr - cmd)>= length) break;
370
371 /* handle string with quote */
372 if (*ptr == '"')
373 {
374 argv[argc++] = ++ptr;
375
376 /* skip this string */
377 while (*ptr != '"' && (ptr-cmd) < length)
378 if (*ptr ++ == '\\') ptr ++;
379 if ((ptr - cmd) >= length) break;
380
381 /* skip '"' */
382 *ptr ++ = '\0';
383 }
384 else
385 {
386 argv[argc++] = ptr;
387 while ((*ptr != ' ' && *ptr != '\t') && (ptr - cmd) < length)
388 ptr ++;
389 }
390
391 if (argc >= RT_MODULE_ARG_MAX) break;
392 }
393
394 return argc;
395 }
396
397 /* module main thread entry */
module_main_entry(void * parameter)398 static void module_main_entry(void* parameter)
399 {
400 int argc;
401 char *argv[RT_MODULE_ARG_MAX];
402 typedef int (*main_func_t)(int argc, char** argv);
403
404 rt_module_t module = (rt_module_t) parameter;
405 if (module == RT_NULL || module->module_cmd_line == RT_NULL) return;
406
407 rt_memset(argv, 0x00, sizeof(argv));
408 argc = _rt_module_split_arg((char*)module->module_cmd_line, module->module_cmd_size, argv);
409 if (argc == 0) return ;
410
411 /* do the main function */
412 ((main_func_t)module->module_entry)(argc, argv);
413 return;
414 }
415
416 /**
417 * This function will do a executable program with main function and parameters.
418 *
419 * @param path the full path of application module
420 * @param cmd_line the command line of program
421 * @param size the size of command line of program
422 *
423 * @return the module object
424 */
rt_module_exec_cmd(const char * path,const char * cmd_line,int line_size)425 rt_module_t rt_module_exec_cmd(const char *path, const char* cmd_line, int line_size)
426 {
427 struct dfs_filesystem *fs;
428 appentry_t fptr;
429 HINSTANCE hinstlib;
430 rt_module_t module;
431
432 char * winpath = RT_NULL;
433 char * name = RT_NULL;
434 char *full_path = RT_NULL;
435
436 RT_DEBUG_NOT_IN_INTERRUPT;
437
438 /* check parameters */
439 RT_ASSERT(path != RT_NULL);
440
441 if (*path != '/')
442 {
443 full_path = dfs_normalize_path(RT_NULL, path);
444 }
445 else
446 {
447 full_path = (const char*)path;
448 }
449
450 /* app module should only in DFS_WIN32 */
451 fs = dfs_filesystem_lookup(full_path);
452 if ((fs == RT_NULL) || (strcmp(fs->ops->name,"wdir") != 0))
453 {
454 rt_kprintf("invalid path: %s\n", path);
455 goto __exit;
456 }
457
458 /* change path */
459 // len = strlen(full_path + 1);
460 if ((winpath = dfs_win32_dirdup((char *)full_path)) == RT_NULL)
461 {
462 rt_kprintf("out of memory, exit", path);
463 goto __exit;
464 }
465
466 hinstlib = LoadLibrary(winpath);
467 if (hinstlib == NULL)
468 {
469 rt_kprintf("error: unable to open %s\n", winpath);
470 goto __exit;
471 }
472
473 fptr = (appentry_t)GetProcAddress(hinstlib, "main");
474 if (fptr == NULL)
475 {
476 rt_kprintf("error: unable to find function in %s\n", winpath);
477 FreeLibrary(hinstlib);
478 goto __exit;
479 }
480
481 /* release winpath */
482 rt_free(winpath);
483
484 /* get the name of the module */
485 name = _module_name(path);
486
487 /* allocate module */
488 module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, name);
489 if (!module)
490 {
491 goto __exit;
492 }
493
494 module->nref = 0;
495 module->module_entry = fptr;
496
497 /* init module object container */
498 rt_module_init_object_container(module);
499
500 /* increase module reference count */
501 module->nref ++;
502
503 if (module->module_entry != 0)
504 {
505 /* set module argument */
506 module->module_cmd_line = (rt_uint8_t*)rt_malloc(line_size + 1);
507 rt_memcpy(module->module_cmd_line, cmd_line, line_size);
508 module->module_cmd_line[line_size] = '\0';
509 module->module_cmd_size = line_size;
510
511 #ifdef RT_USING_SLAB
512 /* init module memory allocator */
513 module->mem_list = RT_NULL;
514
515 /* create page array */
516 module->page_array =
517 (void *)rt_malloc(PAGE_COUNT_MAX * sizeof(struct rt_page_info));
518 module->page_cnt = 0;
519 #endif
520
521 /* create module thread */
522 module->module_thread = rt_thread_create(name,
523 module_main_entry, module,
524 2048, RT_THREAD_PRIORITY_MAX - 2, 10);
525
526 /* set module id */
527 module->module_thread->parent.module_id = (void *)module;
528 module->parent.flag = RT_MODULE_FLAG_WITHENTRY;
529
530 /* startup module thread */
531 rt_thread_startup(module->parent.module_thread);
532 }
533 else
534 {
535 /* without entry point */
536 module->parent.flag |= RT_MODULE_FLAG_WITHOUTENTRY;
537 }
538
539 #ifdef RT_USING_HOOK
540 if (rt_module_load_hook != RT_NULL)
541 {
542 rt_module_load_hook(module);
543 }
544 #endif
545
546 rt_free(name);
547 return module;
548
549 __exit:
550 if (full_path != path) rt_free(full_path);
551 if (name != RT_NULL) rt_free(full_path);
552 if (winpath != RT_NULL)rt_free(winpath);
553
554 return RT_NULL;
555 /* FreeLibrary(hinstlib); */
556 }
557
rt_module_destroy(rt_module_t module)558 rt_err_t rt_module_destroy(rt_module_t module)
559 {
560 return 0;
561 }
562
rt_module_unload(rt_module_t module)563 rt_err_t rt_module_unload(rt_module_t module)
564 {
565 return 0;
566 }
567
568 #endif
569