From: SeokYeon Hwang Date: Sun, 15 Jun 2014 10:01:58 +0000 (+0900) Subject: emulator: new emulator options are introduced X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.1~228^2^2~144^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4f16ca498b8640f29df201bbb09a8f88d2c00ff6;p=sdk%2Femulator%2Fqemu.git emulator: new emulator options are introduced It is experimental feature for now. This feature need [profile].profile configuration file. That file may be provided another way. Change-Id: I2bf663eb604b62d7de0e5c603571a7239e0ff235 Signed-off-by: SeokYeon Hwang --- diff --git a/tizen/src/Makefile.tizen b/tizen/src/Makefile.tizen index 61cb45d7ea..63559d2537 100644 --- a/tizen/src/Makefile.tizen +++ b/tizen/src/Makefile.tizen @@ -31,7 +31,7 @@ GL_CFLAGS := -Wall -g -O2 -fno-strict-aliasing endif # maru loader -obj-y += emulator.o emul_state.o maru_err_table.o +obj-y += emulator.o emulator_options.o emul_state.o maru_err_table.o # osutil obj-y += osutil.o diff --git a/tizen/src/emul_state.h b/tizen/src/emul_state.h index 62fe4eb77d..c275522198 100644 --- a/tizen/src/emul_state.h +++ b/tizen/src/emul_state.h @@ -3,7 +3,7 @@ * * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * - * Contact: + * Contact: * SeokYeon Hwang * MunKyu Im * GiWoong Kim diff --git a/tizen/src/emulator.c b/tizen/src/emulator.c index 76be5fa51f..856b0857ad 100644 --- a/tizen/src/emulator.c +++ b/tizen/src/emulator.c @@ -32,6 +32,7 @@ #include #include +#include #include "qemu/config-file.h" #include "qemu/sockets.h" @@ -41,6 +42,7 @@ #include "emul_state.h" #include "guest_debug.h" #include "guest_server.h" +#include "emulator_options.h" #include "hw/maru_camera_common.h" #include "hw/maru_virtio_touchscreen.h" #include "check_gl.h" @@ -95,6 +97,8 @@ gchar maru_kernel_cmdline[LEN_MARU_KERNEL_CMDLINE]; gchar bin_path[PATH_MAX] = { 0, }; gchar log_path[PATH_MAX] = { 0, }; +gchar *vm_path; + char tizen_target_path[PATH_MAX]; char tizen_target_img_path[PATH_MAX]; @@ -175,65 +179,6 @@ static void make_vm_lock(void) make_vm_lock_os(); } -static void set_image_and_log_path(char *qemu_argv) -{ - int i, j = 0; - int name_len = 0; - int prefix_len = 0; - int suffix_len = 0; - int max = 0; - char *path = malloc(PATH_MAX); - name_len = strlen(qemu_argv); - prefix_len = strlen(IMAGE_PATH_PREFIX); - suffix_len = strlen(IMAGE_PATH_SUFFIX); - max = name_len - suffix_len; - for (i = prefix_len , j = 0; i < max; i++) { - path[j++] = qemu_argv[i]; - } - path[j] = '\0'; - if (!g_path_is_absolute(path)) { - strcpy(tizen_target_path, g_get_current_dir()); - } else { - strcpy(tizen_target_path, g_path_get_dirname(path)); - } - - set_emul_vm_name(g_path_get_basename(tizen_target_path)); - strcpy(tizen_target_img_path, path); - free(path); - - strcpy(log_path, tizen_target_path); - strcat(log_path, LOGS_SUFFIX); -#ifdef CONFIG_WIN32 - if (access(g_win32_locale_filename_from_utf8(log_path), R_OK) != 0) { - g_mkdir(g_win32_locale_filename_from_utf8(log_path), 0755); - } -#else - if (access(log_path, R_OK) != 0) { - if (g_mkdir(log_path, 0755) < 0) { - fprintf(stderr, "failed to create log directory %s\n", log_path); - } - } -#endif - strcat(log_path, LOGFILE); -} - -static void redir_output(void) -{ - FILE *fp; - - fp = freopen(log_path, "a+", stdout); - if (fp == NULL) { - fprintf(stderr, "log file open error\n"); - } - - fp = freopen(log_path, "a+", stderr); - if (fp == NULL) { - fprintf(stderr, "log file open error\n"); - } - setvbuf(stdout, NULL, _IOLBF, BUFSIZ); - setvbuf(stderr, NULL, _IOLBF, BUFSIZ); -} - static void print_system_info(void) { #define DIV 1024 @@ -359,6 +304,65 @@ void start_skin(void) int qemu_main(int argc, char **argv, char **envp); #ifdef SUPPORT_LEGACY_ARGS +static void set_image_and_log_path(char *qemu_argv) +{ + int i, j = 0; + int name_len = 0; + int prefix_len = 0; + int suffix_len = 0; + int max = 0; + char *path = malloc(PATH_MAX); + name_len = strlen(qemu_argv); + prefix_len = strlen(IMAGE_PATH_PREFIX); + suffix_len = strlen(IMAGE_PATH_SUFFIX); + max = name_len - suffix_len; + for (i = prefix_len , j = 0; i < max; i++) { + path[j++] = qemu_argv[i]; + } + path[j] = '\0'; + if (!g_path_is_absolute(path)) { + strcpy(tizen_target_path, g_get_current_dir()); + } else { + strcpy(tizen_target_path, g_path_get_dirname(path)); + } + + set_emul_vm_name(g_path_get_basename(tizen_target_path)); + strcpy(tizen_target_img_path, path); + free(path); + + strcpy(log_path, tizen_target_path); + strcat(log_path, LOGS_SUFFIX); +#ifdef CONFIG_WIN32 + if (access(g_win32_locale_filename_from_utf8(log_path), R_OK) != 0) { + g_mkdir(g_win32_locale_filename_from_utf8(log_path), 0755); + } +#else + if (access(log_path, R_OK) != 0) { + if (g_mkdir(log_path, 0755) < 0) { + fprintf(stderr, "failed to create log directory %s\n", log_path); + } + } +#endif + strcat(log_path, LOGFILE); +} + +static void redir_output(void) +{ + FILE *fp; + + fp = freopen(log_path, "a+", stdout); + if (fp == NULL) { + fprintf(stderr, "log file open error\n"); + } + + fp = freopen(log_path, "a+", stderr); + if (fp == NULL) { + fprintf(stderr, "log file open error\n"); + } + setvbuf(stdout, NULL, _IOLBF, BUFSIZ); + setvbuf(stderr, NULL, _IOLBF, BUFSIZ); +} + // deprecated static void extract_qemu_info(int qemu_argc, char **qemu_argv) { @@ -498,6 +502,122 @@ static int emulator_main(int argc, char *argv[], char **envp) } #endif + gchar *profile = NULL; + int c = 0; + + _qemu_argv = g_malloc(sizeof(char*) * 256); + _skin_argv = g_malloc(sizeof(char*) * 256); + + // parse arguments + // prevent the error message for undefined options + opterr = 0; + + while (c != -1) { + static struct option long_options[] = { + {"profile", required_argument, 0, 'p' }, + {"additional", required_argument, 0, 'a' }, + {0, 0, 0, 0 } + }; + + c = getopt_long(argc, argv, "p:v:", long_options, NULL); + + if (c == -1) + break; + + switch (c) { + case '?': + set_variable(argv[optind - 1], argv[optind], true); + break; + case 'p': + set_variable("profile", optarg, true); + profile = g_strdup(optarg); + break; + case 'a': + // TODO: additional options should be accepted + set_variable("additional", optarg, true); + c = -1; + break; + default: + break; + } + } + + if (!profile) { + fprintf(stderr, "Usage: %s {-p|--profile} profile\n", argv[0]); + + return -1; + } + + // load profile configurations + _qemu_argc = 0; + _qemu_argv[_qemu_argc++] = g_strdup(argv[0]); + + set_bin_path(_qemu_argv[0]); + + if (!load_profile_default(profile)) { + return -1; + } + + // set emulator resolution + { + char *resolution = get_variable("resolution"); + if (!resolution) { + fprintf(stderr, "[resolution] is required.\n"); + } + char **splitted = g_strsplit(resolution, "x", 2); + if (!splitted[0] || !splitted[1]) { + fprintf(stderr, "resolution value [%s] is weird. Please use format \"WIDTHxHEIGHT\"\n", resolution); + } + set_emul_resolution(g_ascii_strtoull(splitted[0], NULL, 0), + g_ascii_strtoull(splitted[1], NULL, 0)); + g_strfreev(splitted); + } + + // assemble arguments for qemu and skin + if (!assemble_profile_args(&_qemu_argc, _qemu_argv, + &_skin_argc, _skin_argv)) { + return -1; + } + + + INFO("Emulator start !!!\n"); + atexit(maru_atexit); + + print_system_info(); + + INFO("Prepare running...\n"); + INFO("tizen_target_img_path: %s\n", tizen_target_img_path); + + int i; + + fprintf(stdout, "qemu args: =========================================\n"); + for (i = 0; i < _qemu_argc; ++i) { + fprintf(stdout, "%s ", _qemu_argv[i]); + } + fprintf(stdout, "\nqemu args: =========================================\n"); + + fprintf(stdout, "skin args: =========================================\n"); + for (i = 0; i < _skin_argc; ++i) { + fprintf(stdout, "%s ", _skin_argv[i]); + } + fprintf(stdout, "\nskin args: =========================================\n"); + + INFO("socket initialize\n"); + socket_init(); + + INFO("qemu main start!\n"); + qemu_main(_qemu_argc, _qemu_argv, envp); + + for (i = 0; i < _qemu_argc; ++i) { + g_free(_qemu_argv[i]); + } + for (i = 0; i < _skin_argc; ++i) { + g_free(_skin_argv[i]); + } + reset_variables(); + + exit_emulator(); + return 0; } diff --git a/tizen/src/emulator_options.c b/tizen/src/emulator_options.c new file mode 100644 index 0000000000..bbfadf4e8d --- /dev/null +++ b/tizen/src/emulator_options.c @@ -0,0 +1,339 @@ +/* + * Emulator + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include "qemu/queue.h" + +#include "maru_common.h" +#include "emulator_options.h" +#include "emulator.h" + +#define LINE_LIMIT 1024 +#define TOKEN_LIMIT 128 +#define OPTION_LIMIT 256 + +struct variable { + gchar *name; + gchar *value; + QTAILQ_ENTRY(variable) entry; +}; + +static QTAILQ_HEAD(, variable) variables = + QTAILQ_HEAD_INITIALIZER(variables); + +struct emulator_opts { + int num; + char *options[OPTION_LIMIT]; +}; + +static struct emulator_opts default_qemu_opts; +static struct emulator_opts default_skin_opts; + +void set_variable(const char * const arg1, const char * const arg2, + bool override) +{ + char *name = NULL; + char *value = NULL; + struct variable *var = NULL; + int i; + + // strip '-' + for (i = 0; i < strlen(arg1); ++i) { + if (arg1[i] != '-') + break; + } + + name = g_strdup(arg1 + i); + if(!arg2) { + value = g_strdup(""); + } else { + value = g_strdup(arg2); + } + + QTAILQ_FOREACH(var, &variables, entry) { + if (!g_strcmp0(name, var->name)) { + if(!override) + return; + + g_free(name); + g_free(var->value); + + var->value = value; + + return; + } + } + + var = g_malloc(sizeof(*var)); + + + var->name = name; + var->value = value; + QTAILQ_INSERT_TAIL(&variables, var, entry); +} + +char *get_variable(const char * const name) +{ + struct variable *var = NULL; + + QTAILQ_FOREACH(var, &variables, entry) { + if (!g_strcmp0(name, var->name)) { + return var->value; + } + } + + return NULL; +} + +void reset_variables(void) +{ + struct variable *var = NULL; + + QTAILQ_FOREACH(var, &variables, entry) { + QTAILQ_REMOVE(&variables, var, entry); + g_free(var->name); + g_free(var->value); + } +} + +static void reset_default_opts(void) +{ + int i = 0; + + for (i = 0; i < default_qemu_opts.num; ++i) { + g_free(default_qemu_opts.options[i]); + } + for (i = 0; i < default_skin_opts.num; ++i) { + g_free(default_skin_opts.options[i]); + } +} + +bool load_profile_default(const char * const profile) +{ + int classification = 0; + char str[LINE_LIMIT]; + char *filename; + FILE *file = NULL; + + filename = g_strdup_printf("%s/%s.profile", get_bin_path(), profile); + + file = fopen(filename, "r"); + if (!file) { + fprintf(stderr, + "Profile configuration file [%s] is not found.\n", filename); + g_free(filename); + return false; + } + g_free(filename); + + struct emulator_opts *default_opts = NULL; + + while (fgets(str, LINE_LIMIT, file)) { + int i = 0; + + while (str[i] && str[i] != '#') { + // tokenize + char token[TOKEN_LIMIT] = { '\0', }; + int start_index = -1; + bool in_quote = false; + + do { + if (!str[i] || + (!in_quote && + (str[i] == ' ' || str[i] == '\t' || str[i] == '#' + || str[i] == '\r' || str[i] == '\n')) || + (in_quote && str[i] == '"')) { + if (start_index != -1) { + g_strlcpy(token, str + start_index, + i - start_index + 1); + } + } + else { + if (start_index < 0) { + if (str[i] == '"') { + in_quote = true; + ++i; + } + start_index = i; + } + } + } while(str[i++] && !token[0]); + + if (!token[0]) { + break; + } + + // detect label + if (!g_strcmp0(token, "[[DEFAULT_VARIABLES]]")) { + classification = 0; + continue; + } + else if (!g_strcmp0(token, "[[SKIN_OPTIONS]]")) { + default_opts = &default_skin_opts; + classification = 1; + continue; + } + else if (!g_strcmp0(token, "[[QEMU_OPTIONS]]")) { + default_opts = &default_qemu_opts; + classification = 2; + continue; + } + + // process line + switch (classification) { + case 0: // default variables + { + gchar **splitted = g_strsplit(token, "=", 2); + if (splitted[0] && splitted[1]) { + set_variable(g_strdup(splitted[0]), g_strdup(splitted[1]), + false); + } + g_strfreev(splitted); + + break; + } + case 1: // skin options + case 2: // qemu options + default_opts->options[default_opts->num++] = g_strdup(token); + + break; + } + } + } + + return true; +} + +static bool assemble_args(int *argc, char **argv, + struct emulator_opts *default_opts) { + int i = 0; + + for (i = 0; i < default_opts->num; ++i) { + int j = 0; + char *str; + int start_index = -1; + int end_index = -1; + void *arg; + + str = default_opts->options[i]; + + // conditional arguments + for (j = 0; str[j]; ++j) { + if(str[j] == '[') { + start_index = j; + } + else if(str[j] == ']') { + end_index = j; + } + } + if (start_index != -1 && end_index != -1) { + char cond[TOKEN_LIMIT]; + + g_strlcpy(cond, str + start_index + 1, end_index - start_index); + g_strstrip(cond); + if (strlen(cond) > 0) { + if ((cond[0] == '!' && get_variable(g_strstrip(cond + 1))) || + (cond[0] != '!' && !get_variable(cond))) { + continue; + } + } + g_strlcpy(str, str + end_index + 1, strlen(str)); + g_strstrip(str); + } + + // fill variables + start_index = -1; + end_index = -1; + + for (j = 0; str[j]; ++j) { + if(str[j] == '$' && str[j + 1] && str[j + 1] == '{') { + start_index = j++; + } + else if(str[j] == '}') { + end_index = j; + } + } + + if (start_index != -1 && end_index != -1) { + char name[TOKEN_LIMIT]; + char *value = NULL; + int length; + + g_strlcpy(name, str + start_index + 2, end_index - start_index - 1); + + // search stored variables + value = get_variable(name); + + // if there is no name in stored variables, + // try to search environment variables + if(!value) { + value = getenv(name); + } + + if(!value) { + fprintf(stderr, "[%s] is not set." + " Please input value using commandline argument" + " \"--%s\" or profile default file or envirionment" + " variable.\n", name, name); + value = (char *)""; + } + + length = start_index + strlen(value) + (strlen(str) - end_index); + arg = g_malloc(length); + + g_strlcpy(arg, str, start_index + 1); + g_strlcat(arg, value, length); + g_strlcat(arg, str + end_index + 1, length); + + argv[(*argc)++] = arg; + } + else { + argv[(*argc)++] = g_strdup(str); + } + } + + return true; +} + +bool assemble_profile_args(int *qemu_argc, char **qemu_argv, + int *skin_argc, char **skin_argv) +{ + if (!assemble_args(qemu_argc, qemu_argv, + &default_qemu_opts)) { + reset_default_opts(); + return false; + } + if (!assemble_args(skin_argc, skin_argv, + &default_skin_opts)) { + reset_default_opts(); + return false; + } + + reset_default_opts(); + return true; +} diff --git a/tizen/src/emulator_options.h b/tizen/src/emulator_options.h new file mode 100644 index 0000000000..c4f370c788 --- /dev/null +++ b/tizen/src/emulator_options.h @@ -0,0 +1,39 @@ +/* + * Emulator + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#ifndef __EMULATOR_OPTIONS_H__ +#define __EMULATOR_OPTIONS_H__ + +void set_variable(const char * const arg1, const char * const arg2, bool override); +char *get_variable(const char * const name); +void reset_variables(void); +bool load_profile_default(const char * const profile); +bool assemble_profile_args(int *qemu_argc, char **qemu_argv, + int *skin_argc, char **skin_argv); + +#endif /* __EMULATOR_OPTIONS_H__ */