aboutsummaryrefslogtreecommitdiff
path: root/linux-user/arm-semi.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux-user/arm-semi.c')
-rw-r--r--linux-user/arm-semi.c42
1 files changed, 37 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;