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 <syeon.hwang@samsung.com>
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
*
* Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
*
- * Contact:
+ * Contact:
* SeokYeon Hwang <syeon.hwang@samsung.com>
* MunKyu Im <munkyu.im@samsung.com>
* GiWoong Kim <giwoong.kim@samsung.com>
#include <stdlib.h>
#include <string.h>
+#include <getopt.h>
#include "qemu/config-file.h"
#include "qemu/sockets.h"
#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"
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];
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
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)
{
}
#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;
}
--- /dev/null
+/*
+ * Emulator
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ *
+ * 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 <string.h>
+#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;
+}
--- /dev/null
+/*
+ * Emulator
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ *
+ * 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__ */