diff mbox

[v2] Add -semihosting-config ....cmdline=string.

Message ID 1416501612-2799-1-git-send-email-ilg@livius.net
State New
Headers show

Commit Message

Liviu Ionescu Nov. 20, 2014, 4:40 p.m. UTC
A new sub-option was added to -semihosting-config to define the entire
semihosting command line (cmdline=string).

This string is passed down to armv7m.c; if not defined, for
compatibility reasons, the -kernel -append values are used.

The armv7m_init() and stellaris_init() interfaces were streamlined,
to use the MachineState structure instead of separate strings.

Signed-off-by: Liviu Ionescu <ilg@livius.net>
---
 hw/arm/armv7m.c       | 14 +++++++++++++-
 hw/arm/stellaris.c    | 12 ++++--------
 include/hw/arm/arm.h  |  2 +-
 qemu-options.hx       | 10 +++++++---
 target-arm/arm-semi.c | 27 +++++++++++++++++++++++----
 vl.c                  |  5 +++++
 6 files changed, 53 insertions(+), 17 deletions(-)
 mode change 100644 => 100755 qemu-options.hx

Comments

Liviu Ionescu Nov. 20, 2014, 8:13 p.m. UTC | #1
On 20 Nov 2014, at 18:40, Liviu Ionescu <ilg@livius.net> wrote:

> A new sub-option was added to -semihosting-config to define the entire
> semihosting command line (cmdline=string).

unfortunately the use of a sub-option is not appropriate, the command line string must be allowed to include *any* character, including the ',' which is not allowed, being used by the parser.

for example 

	-semihosting-config target=native,cmdline="MessageTest --gtest_output=xml:gcm.xml,baburiba" 

triggers an error:

	Unsupported semihosting-config target=native,cmdline=MessageTest --gtest_output=xml:gcm.xml,baburiba


unless you know of an escape character, the only solution I see is to return to a separate option:

	-semihosting-cmdline "0 1 2 3"

for my use I would define a global variable and assign it, but this will probably not work for other targets.

any suggestions?


regard,

Liviu
Eric Blake Nov. 20, 2014, 8:20 p.m. UTC | #2
On 11/20/2014 01:13 PM, Liviu Ionescu wrote:
> 
> On 20 Nov 2014, at 18:40, Liviu Ionescu <ilg@livius.net> wrote:
> 
>> A new sub-option was added to -semihosting-config to define the entire
>> semihosting command line (cmdline=string).
> 
> unfortunately the use of a sub-option is not appropriate, the command line string must be allowed to include *any* character, including the ',' which is not allowed, being used by the parser.

The command line parser explicitly allows ,, as an escape for a literal
comma, rather than a separator between options, for anything converted
to use QemuOpts.

> 
> for example 
> 
> 	-semihosting-config target=native,cmdline="MessageTest --gtest_output=xml:gcm.xml,baburiba" 

Instead, try:

-semihosting-config target=native,cmdline="MessageTest
--gtest_output=xml:gcm.xml,,baburiba"
Liviu Ionescu Nov. 20, 2014, 8:39 p.m. UTC | #3
On 20 Nov 2014, at 22:20, Eric Blake <eblake@redhat.com> wrote:

> Instead, try:
> 
> -semihosting-config target=native,cmdline="MessageTest
> --gtest_output=xml:gcm.xml,,baburiba"

with double comma, the output of my custom qemu shows that the command line was properly parsed:

GNU ARM Eclipse QEMU v2.1.92 (qemu-system-gnuarmeclipse).
Board/machine: 'LM3S6965EVB'.
Core: 'cortex-m3', flash: 256 KB, RAM: 64 KB.
Image: 'qemu_osx_aep_gcc_minimal_Debug/minimal.elf'.
Command line: 'MessageTest --gtest_output=xml:gcm.xml,baburiba' (47 bytes).

however the syntax is unusual and quite non-intuitive.


regards,

Liviu
diff mbox

Patch

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index ef24ca4..9214c96 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -13,6 +13,9 @@ 
 #include "elf.h"
 #include "sysemu/qtest.h"
 #include "qemu/error-report.h"
+#include "hw/boards.h"
+
+static struct arm_boot_info armv7m_binfo;
 
 /* Bitbanded IO.  Each word corresponds to a single bit.  */
 
@@ -168,7 +171,7 @@  static void armv7m_reset(void *opaque)
 
 qemu_irq *armv7m_init(MemoryRegion *system_memory,
                       int flash_size, int sram_size,
-                      const char *kernel_filename, const char *cpu_model)
+                      MachineState *machine)
 {
     ARMCPU *cpu;
     CPUARMState *env;
@@ -184,6 +187,9 @@  qemu_irq *armv7m_init(MemoryRegion *system_memory,
     MemoryRegion *flash = g_new(MemoryRegion, 1);
     MemoryRegion *hack = g_new(MemoryRegion, 1);
 
+    const char *kernel_filename = machine->kernel_filename;
+    const char *cpu_model = machine->cpu_model;
+
     flash_size *= 1024;
     sram_size *= 1024;
 
@@ -240,6 +246,12 @@  qemu_irq *armv7m_init(MemoryRegion *system_memory,
         exit(1);
     }
 
+    /* Fill-in a minimalistic boot info, required for semihosting */
+    armv7m_binfo.kernel_filename = kernel_filename;
+    armv7m_binfo.kernel_cmdline = machine->kernel_cmdline;
+
+    env->boot_info = &armv7m_binfo;
+
     if (kernel_filename) {
         image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
                               NULL, big_endian, ELF_MACHINE, 1);
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 64bd4b4..f93326a 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -1198,7 +1198,7 @@  static stellaris_board_info stellaris_boards[] = {
   }
 };
 
-static void stellaris_init(const char *kernel_filename, const char *cpu_model,
+static void stellaris_init(MachineState *machine,
                            stellaris_board_info *board)
 {
     static const int uart_irq[] = {5, 6, 33, 34};
@@ -1223,7 +1223,7 @@  static void stellaris_init(const char *kernel_filename, const char *cpu_model,
     flash_size = ((board->dc0 & 0xffff) + 1) << 1;
     sram_size = (board->dc0 >> 18) + 1;
     pic = armv7m_init(get_system_memory(),
-                      flash_size, sram_size, kernel_filename, cpu_model);
+                      flash_size, sram_size, machine);
 
     if (board->dc1 & (1 << 16)) {
         dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000,
@@ -1335,16 +1335,12 @@  static void stellaris_init(const char *kernel_filename, const char *cpu_model,
 /* FIXME: Figure out how to generate these from stellaris_boards.  */
 static void lm3s811evb_init(MachineState *machine)
 {
-    const char *cpu_model = machine->cpu_model;
-    const char *kernel_filename = machine->kernel_filename;
-    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[0]);
+    stellaris_init(machine, &stellaris_boards[0]);
 }
 
 static void lm3s6965evb_init(MachineState *machine)
 {
-    const char *cpu_model = machine->cpu_model;
-    const char *kernel_filename = machine->kernel_filename;
-    stellaris_init(kernel_filename, cpu_model, &stellaris_boards[1]);
+    stellaris_init(machine, &stellaris_boards[1]);
 }
 
 static QEMUMachine lm3s811evb_machine = {
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index cefc9e6..a72fc9a 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -17,7 +17,7 @@ 
 /* armv7m.c */
 qemu_irq *armv7m_init(MemoryRegion *system_memory,
                       int flash_size, int sram_size,
-                      const char *kernel_filename, const char *cpu_model);
+                      MachineState *machine);
 
 /* arm_boot.c */
 struct arm_boot_info {
diff --git a/qemu-options.hx b/qemu-options.hx
old mode 100644
new mode 100755
index 3e81222..c5db4d1
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3219,14 +3219,18 @@  STEXI
 Enable semihosting mode (ARM, M68K, Xtensa only).
 ETEXI
 DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
-    "-semihosting-config [enable=on|off,]target=native|gdb|auto   semihosting configuration\n",
+    "-semihosting-config [enable=on|off,]target=native|gdb|auto[,cmdline=string]   semihosting configuration\n",
 QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32)
 STEXI
-@item -semihosting-config [enable=on|off,]target=native|gdb|auto
+@item -semihosting-config [enable=on|off,]target=native|gdb|auto[,cmdline=string]
 @findex -semihosting-config
 Enable semihosting and define where the semihosting calls will be addressed,
 to QEMU (@code{native}) or to GDB (@code{gdb}). The default is @code{auto}, which means
-@code{gdb} during debug sessions and @code{native} otherwise (ARM, M68K, Xtensa only).
+@code{gdb} during debug sessions and @code{native} otherwise. The optional
+@code{cmdline} defines the entire command line passed to the application via the
+semihosting SYS_GET_CMDLINE call, including the program name that will be
+passed as argv[0].
+(ARM, M68K, Xtensa only)
 ETEXI
 DEF("old-param", 0, QEMU_OPTION_old_param,
     "-old-param      old param mode\n", QEMU_ARCH_ARM)
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
index ebb5235..d1f14ff 100644
--- a/target-arm/arm-semi.c
+++ b/target-arm/arm-semi.c
@@ -35,6 +35,8 @@ 
 #include "qemu-common.h"
 #include "exec/gdbstub.h"
 #include "hw/arm/arm.h"
+#include "qemu/option.h"
+#include "qemu/config-file.h"
 #endif
 
 #define TARGET_SYS_OPEN        0x01
@@ -434,12 +436,23 @@  uint32_t do_arm_semihosting(CPUARMState *env)
             GET_ARG(0);
             GET_ARG(1);
             input_size = arg1;
+
             /* Compute the size of the output string.  */
 #if !defined(CONFIG_USER_ONLY)
-            output_size = strlen(ts->boot_info->kernel_filename)
+            QemuOpts *opts;
+            const char *cmdline;
+
+            opts = qemu_opts_find(qemu_find_opts("semihosting-config"), NULL);
+            cmdline = qemu_opt_get(opts, "cmdline");
+
+            if (cmdline) {
+                output_size = strlen(cmdline) + 1;
+            } else {
+                output_size = strlen(ts->boot_info->kernel_filename)
                         + 1  /* Separating space.  */
                         + strlen(ts->boot_info->kernel_cmdline)
                         + 1; /* Terminating null byte.  */
+            }
 #else
             unsigned int i;
 
@@ -470,9 +483,15 @@  uint32_t do_arm_semihosting(CPUARMState *env)
 
             /* Copy the command-line arguments.  */
 #if !defined(CONFIG_USER_ONLY)
-            pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
-            pstrcat(output_buffer, output_size, " ");
-            pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
+            if (cmdline) {
+                pstrcpy(output_buffer, output_size, cmdline);
+            } else {
+                pstrcpy(output_buffer, output_size,
+                        ts->boot_info->kernel_filename);
+                pstrcat(output_buffer, output_size, " ");
+                pstrcat(output_buffer, output_size,
+                        ts->boot_info->kernel_cmdline);
+            }
 #else
             if (output_size == 1) {
                 /* Empty command-line.  */
diff --git a/vl.c b/vl.c
index 8844983..2339d6d 100644
--- a/vl.c
+++ b/vl.c
@@ -558,6 +558,7 @@  static QemuOptsList qemu_icount_opts = {
 static QemuOptsList qemu_semihosting_config_opts = {
     .name = "semihosting-config",
     .implied_opt_name = "enable",
+    .merge_lists = true,
     .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
     .desc = {
         {
@@ -566,6 +567,9 @@  static QemuOptsList qemu_semihosting_config_opts = {
         }, {
             .name = "target",
             .type = QEMU_OPT_STRING,
+        }, {
+            .name = "cmdline",
+            .type = QEMU_OPT_STRING,
         },
         { /* end of list */ }
     },
@@ -3662,6 +3666,7 @@  int main(int argc, char **argv, char **envp)
                     } else {
                         semihosting_target = SEMIHOSTING_TARGET_AUTO;
                     }
+
                 } else {
                     fprintf(stderr, "Unsupported semihosting-config %s\n",
                             optarg);