aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-11-19 20:29:35 +0000
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>2006-11-19 20:29:35 +0000
commit38d0662a4cf196cc059c9e27f634b13fb24fce2d (patch)
treebd4c37654250a2fe94a30d42f8bdc4b29b9cd474
parent1be9e1dc569eb3817441baf60d26648c5dcef12d (diff)
Arm semihosted commandline support (Wolfgang Schildbach).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2216 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--linux-user/arm-semi.c42
-rw-r--r--linux-user/linuxload.c2
-rw-r--r--linux-user/qemu.h1
3 files changed, 40 insertions, 5 deletions
diff --git a/linux-user/arm-semi.c b/linux-user/arm-semi.c
index 250d5b75cc..b182eb4080 100644
--- a/linux-user/arm-semi.c
+++ b/linux-user/arm-semi.c
@@ -77,7 +77,8 @@ static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
return code;
}
-#define ARG(n) tget32(args + n * 4)
+#define ARG(n) tget32(args + (n) * 4)
+#define SET_ARG(n, val) tput32(args + (n) * 4,val)
uint32_t do_arm_semihosting(CPUState *env)
{
target_ulong args;
@@ -158,10 +159,41 @@ uint32_t do_arm_semihosting(CPUState *env)
case SYS_ERRNO:
return ts->swi_errno;
case SYS_GET_CMDLINE:
- /* XXX: Not implemented. */
- s = (char *)g2h(ARG(0));
- *s = 0;
- return -1;
+ /* Build a commandline from the original argv. */
+ {
+ char **arg = ts->info->host_argv;
+ int len = ARG(1);
+ /* lock the buffer on the ARM side */
+ char *cmdline_buffer = (char*)lock_user(ARG(0), len, 0);
+
+ s = cmdline_buffer;
+ while (*arg && len > 2) {
+ int n = strlen(*arg);
+
+ if (s != cmdline_buffer) {
+ *(s++) = ' ';
+ len--;
+ }
+ if (n >= len)
+ n = len - 1;
+ memcpy(s, *arg, n);
+ s += n;
+ len -= n;
+ arg++;
+ }
+ /* Null terminate the string. */
+ *s = 0;
+ len = s - cmdline_buffer;
+
+ /* Unlock the buffer on the ARM side. */
+ unlock_user(cmdline_buffer, ARG(0), len);
+
+ /* Adjust the commandline length argument. */
+ SET_ARG(1, len);
+
+ /* Return success if commandline fit into buffer. */
+ return *arg ? -1 : 0;
+ }
case SYS_HEAPINFO:
{
uint32_t *ptr;
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index ef5409b95f..2d20c000db 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -162,6 +162,8 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
retval = prepare_binprm(&bprm);
+ infop->host_argv = argv;
+
if(retval>=0) {
if (bprm.buf[0] == 0x7f
&& bprm.buf[1] == 'E'
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index d35455de33..f894dde084 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -29,6 +29,7 @@ struct image_info {
unsigned long entry;
target_ulong code_offset;
target_ulong data_offset;
+ char **host_argv;
int personality;
};