emulator: fix compile errors on Windows.
[sdk/emulator/qemu.git] / tizen / src / emulator.c
1 /*
2  * Emulator
3  *
4  * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * SeokYeon Hwang <syeon.hwang@samsung.com>
8  * MunKyu Im <munkyu.im@samsung.com>
9  * GiWoong Kim <giwoong.kim@samsung.com>
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24  * MA 02110-1301, USA.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31 #include <stdlib.h>
32 #include <getopt.h>
33
34 #include "qemu/config-file.h"
35 #include "qemu/sockets.h"
36
37 #include "build_info.h"
38 #include "emulator.h"
39 #include "emul_state.h"
40 #include "guest_server.h"
41 #include "emulator_options.h"
42 #include "check_gl.h"
43 #include "maru_err_table.h"
44 #include "mloop_event.h"
45 #include "osutil.h"
46 #include "sdb.h"
47 #include "skin/maruskin_server.h"
48 #include "debug_ch.h"
49 #include "ecs/ecs.h"
50
51 #ifdef CONFIG_SDL
52 #include <SDL.h>
53 #endif
54
55 #ifdef CONFIG_WIN32
56 #include <libgen.h>
57 #endif
58
59 #ifdef CONFIG_DARWIN
60 #include "ns_event.h"
61 int thread_running = 1; /* Check if we need exit main */
62 #endif
63
64 MULTI_DEBUG_CHANNEL(tizen, main);
65
66 #define SUPPORT_LEGACY_ARGS
67
68 #define ARGS_LIMIT  128
69 #define LEN_MARU_KERNEL_CMDLINE 512
70 char maru_kernel_cmdline[LEN_MARU_KERNEL_CMDLINE];
71
72 char bin_path[PATH_MAX] = { 0, };
73
74 char tizen_target_path[PATH_MAX];
75 char tizen_target_img_path[PATH_MAX];
76
77 int enable_yagl = 0;
78 int enable_spice = 0;
79
80 int _skin_argc;
81 char **_skin_argv;
82 int _qemu_argc;
83 char **_qemu_argv;
84
85 const char *get_log_path(void)
86 {
87 #ifdef SUPPORT_LEGACY_ARGS
88     if (log_path[0]) {
89         return log_path;
90     }
91 #endif
92     char *log_path = get_variable("log_path");
93
94     // if "log_path" is not exist, make it first
95     if (!log_path) {
96         char *vms_path = get_variable("vms_path");
97         char *vm_name = get_variable("vm_name");
98         if (!vms_path || !vm_name) {
99             log_path = NULL;
100         }
101         else {
102             log_path = g_strdup_printf("%s/%s/logs", vms_path, vm_name);
103         }
104
105         set_variable("log_path", log_path, false);
106     }
107
108     return log_path;
109 }
110
111 void emulator_add_exit_notifier(Notifier *notify)
112 {
113     qemu_add_exit_notifier(notify);
114 }
115
116 static void construct_main_window(int skin_argc, char *skin_argv[],
117                                 int qemu_argc, char *qemu_argv[])
118 {
119     INFO("construct main window\n");
120
121     start_skin_server(skin_argc, skin_argv, qemu_argc, qemu_argv);
122
123     set_emul_caps_lock_state(0);
124     set_emul_num_lock_state(0);
125
126     /* the next line checks for debugging and etc.. */
127     if (get_emul_skin_enable()) {
128         if (0 > start_skin_client(skin_argc, skin_argv)) {
129             maru_register_exit_msg(MARU_EXIT_SKIN_SERVER_FAILED, NULL);
130             exit(-1);
131         }
132     }
133 }
134
135 static void get_host_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy)
136 {
137     get_host_proxy_os(http_proxy, https_proxy, ftp_proxy, socks_proxy);
138 }
139
140 static void set_bin_path(gchar * exec_argv)
141 {
142     set_bin_path_os(exec_argv);
143 }
144
145 gchar * get_bin_path(void)
146 {
147     return bin_path;
148 }
149
150 static void check_vm_lock(void)
151 {
152     check_vm_lock_os();
153 }
154
155 static void make_vm_lock(void)
156 {
157     make_vm_lock_os();
158 }
159
160 static void remove_vm_lock(void)
161 {
162     remove_vm_lock_os();
163 }
164
165 static void emulator_notify_exit(Notifier *notifier, void *data)
166 {
167     remove_vm_lock();
168
169     int i;
170     for (i = 0; i < _qemu_argc; ++i) {
171         g_free(_qemu_argv[i]);
172     }
173     for (i = 0; i < _skin_argc; ++i) {
174         g_free(_skin_argv[i]);
175     }
176     reset_variables();
177
178     INFO("Exit emulator...\n");
179 }
180
181 static Notifier emulator_exit = { .notify = emulator_notify_exit };
182
183 static void print_system_info(void)
184 {
185 #define DIV 1024
186
187     INFO("* Board name : %s\n", build_version);
188     INFO("* Package %s\n", pkginfo_version);
189     INFO("* Package %s\n", pkginfo_maintainer);
190     INFO("* Git Head : %s\n", pkginfo_githead);
191     INFO("* %s\n", latest_gittag);
192     INFO("* User name : %s\n", g_get_real_name());
193     INFO("* Host name : %s\n", g_get_host_name());
194
195     /* time stamp */
196     INFO("* Build date : %s\n", build_date);
197
198     qemu_timeval tval = { 0, };
199     if (qemu_gettimeofday(&tval) == 0) {
200         char timeinfo[64] = {0, };
201
202         time_t ti = tval.tv_sec;
203         struct tm *tm_time = localtime(&ti);
204         strftime(timeinfo, sizeof(timeinfo), "%Y-%m-%d %H:%M:%S", tm_time);
205         INFO("* Current time : %s\n", timeinfo);
206     }
207
208 #ifdef CONFIG_SDL
209     /* Gets the version of the dynamically linked SDL library */
210     INFO("* Host sdl version : (%d, %d, %d)\n",
211             SDL_Linked_Version()->major,
212             SDL_Linked_Version()->minor,
213             SDL_Linked_Version()->patch);
214 #endif
215
216     print_system_info_os();
217 }
218
219 static void print_options_info(void)
220 {
221     int i;
222
223     fprintf(stdout, "qemu args: =========================================\n");
224     for (i = 0; i < _qemu_argc; ++i) {
225         fprintf(stdout, "%s ", _qemu_argv[i]);
226     }
227     fprintf(stdout, "\n====================================================\n");
228
229     fprintf(stdout, "skin args: =========================================\n");
230     for (i = 0; i < _skin_argc; ++i) {
231         fprintf(stdout, "%s ", _skin_argv[i]);
232     }
233     fprintf(stdout, "\n====================================================\n");
234 }
235
236 #define PROXY_BUFFER_LEN  128
237 #define DEFAULT_QEMU_DNS_IP "10.0.2.3"
238 static void prepare_basic_features(gchar * const kernel_cmdline)
239 {
240     char http_proxy[PROXY_BUFFER_LEN] ={ 0, },
241         https_proxy[PROXY_BUFFER_LEN] = { 0, },
242         ftp_proxy[PROXY_BUFFER_LEN] = { 0, },
243         socks_proxy[PROXY_BUFFER_LEN] = { 0, },
244         dns[PROXY_BUFFER_LEN] = { 0, };
245
246     set_base_port();
247
248     check_vm_lock();
249     make_vm_lock();
250
251     qemu_add_opts(&qemu_ecs_opts);
252     start_ecs();
253
254     start_guest_server(get_device_serial_number() + SDB_UDP_SENSOR_INDEX);
255
256     mloop_ev_init();
257
258     sdb_setup();
259
260     get_host_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy);
261     /* using "DNS" provided by default QEMU */
262     g_strlcpy(dns, DEFAULT_QEMU_DNS_IP, strlen(DEFAULT_QEMU_DNS_IP) + 1);
263
264     gchar * const tmp_str = g_strdup_printf(" sdb_port=%d,"
265         " http_proxy=%s https_proxy=%s ftp_proxy=%s socks_proxy=%s"
266         " dns1=%s vm_resolution=%dx%d", get_emul_vm_base_port(),
267         http_proxy, https_proxy, ftp_proxy, socks_proxy, dns,
268         get_emul_resolution_width(), get_emul_resolution_height());
269
270     g_strlcat(kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE);
271
272     g_free(tmp_str);
273 }
274
275 #ifdef CONFIG_YAGL
276 static void prepare_opengl_acceleration(gchar * const kernel_cmdline)
277 {
278     int capability_check_gl = 0;
279
280     if (enable_yagl) {
281         capability_check_gl = check_gl();
282
283         if (capability_check_gl != 0) {
284             enable_yagl = 0;
285             INFO("<WARNING> GL acceleration was disabled due to the fail of GL check!\n");
286         }
287     }
288
289     gchar * const tmp_str = g_strdup_printf(" yagl=%d", enable_yagl);
290
291     g_strlcat(kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE);
292
293     g_free(tmp_str);
294 }
295 #endif
296
297 const gchar *prepare_maru(const gchar * const kernel_cmdline)
298 {
299     INFO("Prepare maru specified feature\n");
300
301     g_strlcpy(maru_kernel_cmdline, kernel_cmdline, LEN_MARU_KERNEL_CMDLINE);
302
303     /* Prepare basic features */
304     INFO("Prepare_basic_features\n");
305     prepare_basic_features(maru_kernel_cmdline);
306
307     /* Prepare GL acceleration */
308 #ifdef CONFIG_YAGL
309     INFO("Prepare_opengl_acceleration\n");
310     prepare_opengl_acceleration(maru_kernel_cmdline);
311 #endif
312
313     INFO("kernel command : %s\n", maru_kernel_cmdline);
314
315     return maru_kernel_cmdline;
316 }
317
318 void start_skin(void)
319 {
320     INFO("Start skin\n");
321
322     construct_main_window(_skin_argc, _skin_argv, _qemu_argc, _qemu_argv);
323 }
324
325 int qemu_main(int argc, char **argv, char **envp);
326 int legacy_emulator_main(int argc, char **argv, char **envp);
327
328 static int emulator_main(int argc, char *argv[], char **envp)
329 {
330 #ifdef SUPPORT_LEGACY_ARGS
331     // for compatibilities...
332     if (argc > 2 && !g_strcmp0("--skin-args", argv[1])) {
333         return legacy_emulator_main(argc, argv, envp);
334     }
335 #endif
336
337 #ifdef CONFIG_WIN32
338     // SDL_init() routes stdout and stderr to the respective files in win32.
339     // So we revert it.
340     freopen("CON", "w", stdout);
341     freopen("CON", "w", stderr);
342 #endif
343
344     gchar *profile = NULL;
345     gchar *conf = NULL;
346
347     int c = 0;
348
349     _qemu_argv = g_malloc(sizeof(char*) * ARGS_LIMIT);
350     _skin_argv = g_malloc(sizeof(char*) * ARGS_LIMIT);
351
352     // parse arguments
353     // prevent the error message for undefined options
354     opterr = 0;
355
356     while (c != -1) {
357         static struct option long_options[] = {
358             {"conf",        required_argument,  0,  'c' },
359             {"profile",     required_argument,  0,  'p' },
360             {"additional",  required_argument,  0,  'a' },
361             {0,             0,                  0,  0   }
362         };
363
364         c = getopt_long(argc, argv, "c:p:a:", long_options, NULL);
365
366         if (c == -1)
367             break;
368
369         switch (c) {
370         case '?':
371             set_variable(argv[optind - 1], argv[optind], true);
372             break;
373         case 'c':
374             set_variable("conf", optarg, true);
375             conf = g_strdup(optarg);
376             break;
377         case 'p':
378             set_variable("profile", optarg, true);
379             profile = g_strdup(optarg);
380             break;
381         case 'a':
382             // TODO: additional options should be accepted
383             set_variable("additional", optarg, true);
384             c = -1;
385             break;
386         default:
387             break;
388         }
389     }
390
391     if (!profile && !conf) {
392         fprintf(stderr, "Usage: %s {-c|--conf} conf_file ...\n"
393                         "       %s {-p|--profile} profile ...\n",
394                         basename(argv[0]), basename(argv[0]));
395
396         return -1;
397     }
398
399     // load profile configurations
400     _qemu_argc = 0;
401     _qemu_argv[_qemu_argc++] = g_strdup(argv[0]);
402
403     set_bin_path(_qemu_argv[0]);
404
405     if (!load_profile_default(conf, profile)) {
406         return -1;
407     }
408
409     // set emulator resolution
410     {
411         char *resolution = get_variable("resolution");
412         if (!resolution) {
413             fprintf(stderr, "[resolution] is required.\n");
414             return -1;
415         }
416         char **splitted = g_strsplit(resolution, "x", 2);
417         if (!splitted[0] || !splitted[1]) {
418             fprintf(stderr, "resolution value [%s] is weird. Please use format \"WIDTHxHEIGHT\"\n", resolution);
419             g_strfreev(splitted);
420             return -1;
421         }
422         else {
423             set_emul_resolution(g_ascii_strtoull(splitted[0], NULL, 0),
424                             g_ascii_strtoull(splitted[1], NULL, 0));
425         }
426         g_strfreev(splitted);
427     }
428
429     // assemble arguments for qemu and skin
430     if (!assemble_profile_args(&_qemu_argc, _qemu_argv,
431                         &_skin_argc, _skin_argv)) {
432         return -1;
433     }
434
435
436     INFO("Start emulator...\n");
437     atexit(maru_atexit);
438     emulator_add_exit_notifier(&emulator_exit);
439
440     print_system_info();
441
442     print_options_info();
443
444     INFO("socket initialize...\n");
445     socket_init();
446
447     INFO("qemu main start...\n");
448     qemu_main(_qemu_argc, _qemu_argv, envp);
449
450     return 0;
451 }
452
453 #ifdef CONFIG_DARWIN
454 int g_argc;
455
456 static void* main_thread(void* args)
457 {
458     char** argv;
459     int argc = g_argc;
460     argv = (char**) args;
461
462     emulator_main(argc, argv, NULL);
463
464     thread_running = 0;
465     pthread_exit(NULL);
466 }
467
468 int main(int argc, char *argv[])
469 {
470     char** args;
471     QemuThread main_thread_id;
472     g_argc = argc;
473     args = argv;
474     qemu_thread_create(&main_thread_id, "main_thread", main_thread, (void *)args, QEMU_THREAD_DETACHED);
475     ns_event_loop(&thread_running);
476
477     return 0;
478 }
479 #elif defined (CONFIG_LINUX)
480 int main(int argc, char *argv[], char **envp)
481 {
482     maru_register_exception_handler();
483     return emulator_main(argc, argv, envp);
484 }
485 #else // WIN32
486 int main(int argc, char *argv[])
487 {
488     maru_register_exception_handler();
489     return emulator_main(argc, argv, NULL);
490 }
491 #endif
492