4 * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
7 * SeokYeon Hwang <syeon.hwang@samsung.com>
8 * MunKyu Im <munkyu.im@samsung.com>
9 * GiWoong Kim <giwoong.kim@samsung.com>
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.
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.
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,
34 #include "qemu/config-file.h"
35 #include "qemu/sockets.h"
37 #include "build_info.h"
39 #include "emul_state.h"
40 #include "guest_server.h"
41 #include "emulator_options.h"
43 #include "maru_err_table.h"
44 #include "mloop_event.h"
47 #include "skin/maruskin_server.h"
61 int thread_running = 1; /* Check if we need exit main */
64 MULTI_DEBUG_CHANNEL(tizen, main);
66 #define SUPPORT_LEGACY_ARGS
68 #define ARGS_LIMIT 128
69 #define LEN_MARU_KERNEL_CMDLINE 512
70 char maru_kernel_cmdline[LEN_MARU_KERNEL_CMDLINE];
72 char bin_path[PATH_MAX] = { 0, };
74 char tizen_target_path[PATH_MAX];
75 char tizen_target_img_path[PATH_MAX];
85 const char *get_log_path(void)
87 #ifdef SUPPORT_LEGACY_ARGS
92 char *log_path = get_variable("log_path");
94 // if "log_path" is not exist, make it first
96 char *vms_path = get_variable("vms_path");
97 char *vm_name = get_variable("vm_name");
98 if (!vms_path || !vm_name) {
102 log_path = g_strdup_printf("%s/%s/logs", vms_path, vm_name);
105 set_variable("log_path", log_path, false);
111 void emulator_add_exit_notifier(Notifier *notify)
113 qemu_add_exit_notifier(notify);
116 static void construct_main_window(int skin_argc, char *skin_argv[],
117 int qemu_argc, char *qemu_argv[])
119 INFO("construct main window\n");
121 start_skin_server(skin_argc, skin_argv, qemu_argc, qemu_argv);
123 set_emul_caps_lock_state(0);
124 set_emul_num_lock_state(0);
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);
135 static void get_host_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy)
137 get_host_proxy_os(http_proxy, https_proxy, ftp_proxy, socks_proxy);
140 static void set_bin_path(gchar * exec_argv)
142 set_bin_path_os(exec_argv);
145 gchar * get_bin_path(void)
150 static void check_vm_lock(void)
155 static void make_vm_lock(void)
160 static void remove_vm_lock(void)
165 static void emulator_notify_exit(Notifier *notifier, void *data)
170 for (i = 0; i < _qemu_argc; ++i) {
171 g_free(_qemu_argv[i]);
173 for (i = 0; i < _skin_argc; ++i) {
174 g_free(_skin_argv[i]);
178 INFO("Exit emulator...\n");
181 static Notifier emulator_exit = { .notify = emulator_notify_exit };
183 static void print_system_info(void)
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());
196 INFO("* Build date : %s\n", build_date);
198 qemu_timeval tval = { 0, };
199 if (qemu_gettimeofday(&tval) == 0) {
200 char timeinfo[64] = {0, };
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);
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);
216 print_system_info_os();
219 static void print_options_info(void)
223 fprintf(stdout, "qemu args: =========================================\n");
224 for (i = 0; i < _qemu_argc; ++i) {
225 fprintf(stdout, "%s ", _qemu_argv[i]);
227 fprintf(stdout, "\n====================================================\n");
229 fprintf(stdout, "skin args: =========================================\n");
230 for (i = 0; i < _skin_argc; ++i) {
231 fprintf(stdout, "%s ", _skin_argv[i]);
233 fprintf(stdout, "\n====================================================\n");
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)
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, };
251 qemu_add_opts(&qemu_ecs_opts);
254 start_guest_server(get_device_serial_number() + SDB_UDP_SENSOR_INDEX);
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);
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());
270 g_strlcat(kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE);
276 static void prepare_opengl_acceleration(gchar * const kernel_cmdline)
278 int capability_check_gl = 0;
281 capability_check_gl = check_gl();
283 if (capability_check_gl != 0) {
285 INFO("<WARNING> GL acceleration was disabled due to the fail of GL check!\n");
289 gchar * const tmp_str = g_strdup_printf(" yagl=%d", enable_yagl);
291 g_strlcat(kernel_cmdline, tmp_str, LEN_MARU_KERNEL_CMDLINE);
297 const gchar *prepare_maru(const gchar * const kernel_cmdline)
299 INFO("Prepare maru specified feature\n");
301 g_strlcpy(maru_kernel_cmdline, kernel_cmdline, LEN_MARU_KERNEL_CMDLINE);
303 /* Prepare basic features */
304 INFO("Prepare_basic_features\n");
305 prepare_basic_features(maru_kernel_cmdline);
307 /* Prepare GL acceleration */
309 INFO("Prepare_opengl_acceleration\n");
310 prepare_opengl_acceleration(maru_kernel_cmdline);
313 INFO("kernel command : %s\n", maru_kernel_cmdline);
315 return maru_kernel_cmdline;
318 void start_skin(void)
320 INFO("Start skin\n");
322 construct_main_window(_skin_argc, _skin_argv, _qemu_argc, _qemu_argv);
325 int qemu_main(int argc, char **argv, char **envp);
326 int legacy_emulator_main(int argc, char **argv, char **envp);
328 static int emulator_main(int argc, char *argv[], char **envp)
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);
338 // SDL_init() routes stdout and stderr to the respective files in win32.
340 freopen("CON", "w", stdout);
341 freopen("CON", "w", stderr);
344 gchar *profile = NULL;
349 _qemu_argv = g_malloc(sizeof(char*) * ARGS_LIMIT);
350 _skin_argv = g_malloc(sizeof(char*) * ARGS_LIMIT);
353 // prevent the error message for undefined options
357 static struct option long_options[] = {
358 {"conf", required_argument, 0, 'c' },
359 {"profile", required_argument, 0, 'p' },
360 {"additional", required_argument, 0, 'a' },
364 c = getopt_long(argc, argv, "c:p:a:", long_options, NULL);
371 set_variable(argv[optind - 1], argv[optind], true);
374 set_variable("conf", optarg, true);
375 conf = g_strdup(optarg);
378 set_variable("profile", optarg, true);
379 profile = g_strdup(optarg);
382 // TODO: additional options should be accepted
383 set_variable("additional", optarg, true);
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]));
399 // load profile configurations
401 _qemu_argv[_qemu_argc++] = g_strdup(argv[0]);
403 set_bin_path(_qemu_argv[0]);
405 if (!load_profile_default(conf, profile)) {
409 // set emulator resolution
411 char *resolution = get_variable("resolution");
413 fprintf(stderr, "[resolution] is required.\n");
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);
423 set_emul_resolution(g_ascii_strtoull(splitted[0], NULL, 0),
424 g_ascii_strtoull(splitted[1], NULL, 0));
426 g_strfreev(splitted);
429 // assemble arguments for qemu and skin
430 if (!assemble_profile_args(&_qemu_argc, _qemu_argv,
431 &_skin_argc, _skin_argv)) {
436 INFO("Start emulator...\n");
438 emulator_add_exit_notifier(&emulator_exit);
442 print_options_info();
444 INFO("socket initialize...\n");
447 INFO("qemu main start...\n");
448 qemu_main(_qemu_argc, _qemu_argv, envp);
456 static void* main_thread(void* args)
460 argv = (char**) args;
462 emulator_main(argc, argv, NULL);
468 int main(int argc, char *argv[])
471 QemuThread main_thread_id;
474 qemu_thread_create(&main_thread_id, "main_thread", main_thread, (void *)args, QEMU_THREAD_DETACHED);
475 ns_event_loop(&thread_running);
479 #elif defined (CONFIG_LINUX)
480 int main(int argc, char *argv[], char **envp)
482 maru_register_exception_handler();
483 return emulator_main(argc, argv, envp);
486 int main(int argc, char *argv[])
488 maru_register_exception_handler();
489 return emulator_main(argc, argv, NULL);