1/*  This file is part of the program psim.
2
3    Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19    */
20
21
22#ifndef _EMUL_NETBSD_C_
23#define _EMUL_NETBSD_C_
24
25
26/* Note: this module is called via a table.  There is no benefit in
27   making it inline */
28
29#include "emul_generic.h"
30#include "emul_netbsd.h"
31
32#ifdef HAVE_STRING_H
33#include <string.h>
34#else
35#ifdef HAVE_STRINGS_H
36#include <strings.h>
37#endif
38#endif
39
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <stdio.h>
43#include <signal.h>
44#include <fcntl.h>
45#include <errno.h>
46#include <sys/param.h>
47#include <sys/time.h>
48
49#ifdef HAVE_GETRUSAGE
50#ifndef HAVE_SYS_RESOURCE_H
51#undef HAVE_GETRUSAGE
52#endif
53#endif
54
55#ifdef HAVE_GETRUSAGE
56#include <sys/resource.h>
57int getrusage();
58#endif
59
60#if HAVE_SYS_IOCTL_H
61#include <sys/ioctl.h>
62#endif
63
64#if HAVE_DIRENT_H
65# include <dirent.h>
66# define NAMLEN(dirent) strlen((dirent)->d_name)
67#else
68# define dirent direct
69# define NAMLEN(dirent) (dirent)->d_namlen
70# if HAVE_SYS_NDIR_H
71#  include <sys/ndir.h>
72# endif
73# if HAVE_SYS_DIR_H
74#  include <sys/dir.h>
75# endif
76# if HAVE_NDIR_H
77#  include <ndir.h>
78# endif
79#endif
80
81#ifdef HAVE_UNISTD_H
82#undef MAXPATHLEN		/* sys/param.h might define this also */
83#include <unistd.h>
84#endif
85
86#ifdef HAVE_STDLIB_H
87#include <stdlib.h>
88#endif
89
90#define WITH_NetBSD_HOST (NetBSD >= 199306)
91#if WITH_NetBSD_HOST /* here NetBSD as that is what we're emulating */
92#include <sys/syscall.h> /* FIXME - should not be including this one */
93#include <sys/sysctl.h>
94#include <sys/mount.h>
95extern int getdirentries(int fd, char *buf, int nbytes, long *basep);
96
97/* NetBSD post 2.0 has the statfs system call (if COMPAT_20), but does
98   not have struct statfs.  In this case don't implement fstatfs.
99   FIXME: Should implement fstatvfs.  */
100#ifndef HAVE_STRUCT_STATFS
101#undef HAVE_FSTATFS
102#endif
103
104#else
105
106/* If this is not netbsd, don't allow fstatfs or getdirentries at this time */
107#undef HAVE_FSTATFS
108#undef HAVE_GETDIRENTRIES
109#endif
110
111#if (BSD < 199306) /* here BSD as just a bug */
112extern int errno;
113#endif
114
115#ifndef STATIC_INLINE_EMUL_NETBSD
116#define STATIC_INLINE_EMUL_NETBSD STATIC_INLINE
117#endif
118
119
120#if WITH_NetBSD_HOST
121#define SYS(X) ASSERT(call == (SYS_##X))
122#else
123#define SYS(X)
124#endif
125
126#if WITH_NetBSD_HOST && (PATH_MAX != 1024)
127#error "PATH_MAX not 1024"
128#elif !defined(PATH_MAX)
129#define PATH_MAX 1024
130#endif
131
132
133/* EMULATION
134
135   NetBSD - Emulation of user programs for NetBSD/PPC
136
137   DESCRIPTION
138
139   */
140
141
142/* NetBSD's idea of what is needed to implement emulations */
143
144struct _os_emul_data {
145  device *vm;
146  emul_syscall *syscalls;
147};
148
149
150
151STATIC_INLINE_EMUL_NETBSD void
152write_stat(unsigned_word addr,
153	   struct stat buf,
154	   cpu *processor,
155	   unsigned_word cia)
156{
157  H2T(buf.st_dev);
158  H2T(buf.st_ino);
159  H2T(buf.st_mode);
160  H2T(buf.st_nlink);
161  H2T(buf.st_uid);
162  H2T(buf.st_gid);
163  H2T(buf.st_size);
164  H2T(buf.st_atime);
165  /* H2T(buf.st_spare1); */
166  H2T(buf.st_mtime);
167  /* H2T(buf.st_spare2); */
168  H2T(buf.st_ctime);
169  /* H2T(buf.st_spare3); */
170#ifdef AC_STRUCT_ST_RDEV
171  H2T(buf.st_rdev);
172#endif
173#ifdef AC_STRUCT_ST_BLKSIZE
174  H2T(buf.st_blksize);
175#endif
176#ifdef AC_STRUCT_ST_BLOCKS
177  H2T(buf.st_blocks);
178#endif
179#if WITH_NetBSD_HOST
180  H2T(buf.st_flags);
181  H2T(buf.st_gen);
182#endif
183  emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
184}
185
186
187#ifdef HAVE_FSTATFS
188STATIC_INLINE_EMUL_NETBSD void
189write_statfs(unsigned_word addr,
190	     struct statfs buf,
191	     cpu *processor,
192	     unsigned_word cia)
193{
194  H2T(buf.f_type);
195  H2T(buf.f_flags);
196  H2T(buf.f_bsize);
197  H2T(buf.f_iosize);
198  H2T(buf.f_blocks);
199  H2T(buf.f_bfree);
200  H2T(buf.f_bavail);
201  H2T(buf.f_files);
202  H2T(buf.f_ffree);
203  H2T(buf.f_fsid.val[0]);
204  H2T(buf.f_fsid.val[1]);
205  H2T(buf.f_owner);
206  /* f_spare[4]; */
207  /* f_fstypename[MFSNAMELEN]; */
208  /* f_mntonname[MNAMELEN]; */
209  /* f_mntfromname[MNAMELEN]; */
210  emul_write_buffer(&buf, addr, sizeof(buf), processor, cia);
211}
212#endif
213
214
215STATIC_INLINE_EMUL_NETBSD void
216write_timeval(unsigned_word addr,
217	      struct timeval t,
218	      cpu *processor,
219	      unsigned_word cia)
220{
221  H2T(t.tv_sec);
222  H2T(t.tv_usec);
223  emul_write_buffer(&t, addr, sizeof(t), processor, cia);
224}
225
226#ifdef HAVE_GETTIMEOFDAY
227STATIC_INLINE_EMUL_NETBSD void
228write_timezone(unsigned_word addr,
229	       struct timezone tz,
230	       cpu *processor,
231	       unsigned_word cia)
232{
233  H2T(tz.tz_minuteswest);
234  H2T(tz.tz_dsttime);
235  emul_write_buffer(&tz, addr, sizeof(tz), processor, cia);
236}
237#endif
238
239#ifdef HAVE_GETDIRENTRIES
240STATIC_INLINE_EMUL_NETBSD void
241write_direntries(unsigned_word addr,
242		 char *buf,
243		 int nbytes,
244		 cpu *processor,
245		 unsigned_word cia)
246{
247  while (nbytes > 0) {
248    struct dirent *out;
249    struct dirent *in = (struct dirent*)buf;
250    ASSERT(in->d_reclen <= nbytes);
251    out = (struct dirent*)zalloc(in->d_reclen);
252    memcpy(out/*dest*/, in/*src*/, in->d_reclen);
253    H2T(out->d_fileno);
254    H2T(out->d_reclen);
255    H2T(out->d_type);
256    H2T(out->d_namlen);
257    emul_write_buffer(out, addr, in->d_reclen, processor, cia);
258    nbytes -= in->d_reclen;
259    addr += in->d_reclen;
260    buf += in->d_reclen;
261    free(out);
262  }
263}
264#endif
265
266
267#ifdef HAVE_GETRUSAGE
268STATIC_INLINE_EMUL_NETBSD void
269write_rusage(unsigned_word addr,
270	     struct rusage rusage,
271	     cpu *processor,
272	     unsigned_word cia)
273{
274  H2T(rusage.ru_utime.tv_sec); /* user time used */
275  H2T(rusage.ru_utime.tv_usec);
276  H2T(rusage.ru_stime.tv_sec); /* system time used */
277  H2T(rusage.ru_stime.tv_usec);
278  H2T(rusage.ru_maxrss);          /* integral max resident set size */
279  H2T(rusage.ru_ixrss);           /* integral shared text memory size */
280  H2T(rusage.ru_idrss);           /* integral unshared data size */
281  H2T(rusage.ru_isrss);           /* integral unshared stack size */
282  H2T(rusage.ru_minflt);          /* page reclaims */
283  H2T(rusage.ru_majflt);          /* page faults */
284  H2T(rusage.ru_nswap);           /* swaps */
285  H2T(rusage.ru_inblock);         /* block input operations */
286  H2T(rusage.ru_oublock);         /* block output operations */
287  H2T(rusage.ru_msgsnd);          /* messages sent */
288  H2T(rusage.ru_msgrcv);          /* messages received */
289  H2T(rusage.ru_nsignals);        /* signals received */
290  H2T(rusage.ru_nvcsw);           /* voluntary context switches */
291  H2T(rusage.ru_nivcsw);          /* involuntary context switches */
292  emul_write_buffer(&rusage, addr, sizeof(rusage), processor, cia);
293}
294#endif
295
296static void
297do_exit(os_emul_data *emul,
298	unsigned call,
299	const int arg0,
300	cpu *processor,
301	unsigned_word cia)
302{
303  int status = (int)cpu_registers(processor)->gpr[arg0];
304  SYS(exit);
305  if (WITH_TRACE && ppc_trace[trace_os_emul])
306    printf_filtered ("%d)\n", status);
307
308  cpu_halt(processor, cia, was_exited, status);
309}
310
311
312static void
313do_read(os_emul_data *emul,
314	unsigned call,
315	const int arg0,
316	cpu *processor,
317	unsigned_word cia)
318{
319  void *scratch_buffer;
320  int d = (int)cpu_registers(processor)->gpr[arg0];
321  unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
322  int nbytes = cpu_registers(processor)->gpr[arg0+2];
323  int status;
324  SYS(read);
325
326  if (WITH_TRACE && ppc_trace[trace_os_emul])
327    printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
328
329  /* get a tempoary bufer */
330  scratch_buffer = zalloc(nbytes);
331
332  /* check if buffer exists by reading it */
333  emul_read_buffer(scratch_buffer, buf, nbytes, processor, cia);
334
335  /* read */
336#if 0
337  if (d == 0) {
338    status = fread (scratch_buffer, 1, nbytes, stdin);
339    if (status == 0 && ferror (stdin))
340      status = -1;
341  }
342#endif
343  status = read (d, scratch_buffer, nbytes);
344
345  emul_write_status(processor, status, errno);
346  if (status > 0)
347    emul_write_buffer(scratch_buffer, buf, status, processor, cia);
348
349  free(scratch_buffer);
350}
351
352
353static void
354do_write(os_emul_data *emul,
355	 unsigned call,
356	 const int arg0,
357	 cpu *processor,
358	 unsigned_word cia)
359{
360  void *scratch_buffer = NULL;
361  int d = (int)cpu_registers(processor)->gpr[arg0];
362  unsigned_word buf = cpu_registers(processor)->gpr[arg0+1];
363  int nbytes = cpu_registers(processor)->gpr[arg0+2];
364  int status;
365  SYS(write);
366
367  if (WITH_TRACE && ppc_trace[trace_os_emul])
368    printf_filtered ("%d, 0x%lx, %d", d, (long)buf, nbytes);
369
370  /* get a tempoary bufer */
371  scratch_buffer = zalloc(nbytes); /* FIXME - nbytes == 0 */
372
373  /* copy in */
374  emul_read_buffer(scratch_buffer, buf, nbytes,
375		   processor, cia);
376
377  /* write */
378  status = write(d, scratch_buffer, nbytes);
379  emul_write_status(processor, status, errno);
380  free(scratch_buffer);
381
382  flush_stdoutput();
383}
384
385
386static void
387do_open(os_emul_data *emul,
388	unsigned call,
389	const int arg0,
390	cpu *processor,
391	unsigned_word cia)
392{
393  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
394  char path_buf[PATH_MAX];
395  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
396  int flags = (int)cpu_registers(processor)->gpr[arg0+1];
397  int mode = (int)cpu_registers(processor)->gpr[arg0+2];
398  int hostflags;
399  int status;
400
401  if (WITH_TRACE && ppc_trace[trace_os_emul])
402    printf_filtered ("0x%lx [%s], 0x%x, 0x%x", (long)path_addr, path, flags, mode);
403
404  SYS(open);
405
406  /* Do some translation on 'flags' to match it to the host's version.  */
407  /* These flag values were taken from the NetBSD 1.4 header files.  */
408  if ((flags & 3) == 0)
409    hostflags = O_RDONLY;
410  else if ((flags & 3) == 1)
411    hostflags = O_WRONLY;
412  else
413    hostflags = O_RDWR;
414  if (flags & 0x00000008)
415    hostflags |= O_APPEND;
416  if (flags & 0x00000200)
417    hostflags |= O_CREAT;
418  if (flags & 0x00000400)
419    hostflags |= O_TRUNC;
420  if (flags & 0x00000800)
421    hostflags |= O_EXCL;
422
423  /* Can't combine these statements, cuz open sets errno. */
424  status = open(path, hostflags, mode);
425  emul_write_status(processor, status, errno);
426}
427
428
429static void
430do_close(os_emul_data *emul,
431	 unsigned call,
432	 const int arg0,
433	 cpu *processor,
434	 unsigned_word cia)
435{
436  int d = (int)cpu_registers(processor)->gpr[arg0];
437  int status;
438
439  if (WITH_TRACE && ppc_trace[trace_os_emul])
440    printf_filtered ("%d", d);
441
442  SYS(close);
443
444  /* Can't combine these statements, cuz close sets errno. */
445  status = close(d);
446  emul_write_status(processor, status, errno);
447}
448
449
450static void
451do_break(os_emul_data *emul,
452	 unsigned call,
453	 const int arg0,
454	 cpu *processor,
455	 unsigned_word cia)
456{
457  /* just pass this onto the `vm' device */
458  unsigned_word new_break = cpu_registers(processor)->gpr[arg0];
459  int status;
460
461  if (WITH_TRACE && ppc_trace[trace_os_emul])
462    printf_filtered ("0x%lx", (long)cpu_registers(processor)->gpr[arg0]);
463
464  SYS(break);
465  status = device_ioctl(emul->vm,
466			processor,
467			cia,
468			device_ioctl_break,
469			new_break); /*ioctl-data*/
470  emul_write_status(processor, 0, status);
471}
472
473
474#ifndef HAVE_GETPID
475#define do_getpid 0
476#else
477static void
478do_getpid(os_emul_data *emul,
479	  unsigned call,
480	  const int arg0,
481	  cpu *processor,
482	  unsigned_word cia)
483{
484  SYS(getpid);
485  emul_write_status(processor, (int)getpid(), 0);
486}
487#endif
488
489#ifndef HAVE_GETUID
490#define do_getuid 0
491#else
492static void
493do_getuid(os_emul_data *emul,
494	  unsigned call,
495	  const int arg0,
496	  cpu *processor,
497	  unsigned_word cia)
498{
499  SYS(getuid);
500  emul_write_status(processor, (int)getuid(), 0);
501}
502#endif
503
504#ifndef HAVE_GETEUID
505#define do_geteuid 0
506#else
507static void
508do_geteuid(os_emul_data *emul,
509	   unsigned call,
510	   const int arg0,
511	   cpu *processor,
512	   unsigned_word cia)
513{
514  SYS(geteuid);
515  emul_write_status(processor, (int)geteuid(), 0);
516}
517#endif
518
519#ifndef HAVE_KILL
520#define do_kill 0
521#else
522static void
523do_kill(os_emul_data *emul,
524	unsigned call,
525	const int arg0,
526	cpu *processor,
527	unsigned_word cia)
528{
529  pid_t pid = cpu_registers(processor)->gpr[arg0];
530  int sig = cpu_registers(processor)->gpr[arg0+1];
531
532  if (WITH_TRACE && ppc_trace[trace_os_emul])
533    printf_filtered ("%d, %d", (int)pid, sig);
534
535  SYS(kill);
536  printf_filtered("SYS_kill at 0x%lx - more to this than just being killed\n",
537		  (long)cia);
538  cpu_halt(processor, cia, was_signalled, sig);
539}
540#endif
541
542#ifndef HAVE_DUP
543#define do_dup 0
544#else
545static void
546do_dup(os_emul_data *emul,
547       unsigned call,
548       const int arg0,
549       cpu *processor,
550       unsigned_word cia)
551{
552  int oldd = cpu_registers(processor)->gpr[arg0];
553  int status = dup(oldd);
554  int err = errno;
555
556  if (WITH_TRACE && ppc_trace[trace_os_emul])
557    printf_filtered ("%d", oldd);
558
559  SYS(dup);
560  emul_write_status(processor, status, err);
561}
562#endif
563
564#ifndef HAVE_GETEGID
565#define do_getegid 0
566#else
567static void
568do_getegid(os_emul_data *emul,
569	   unsigned call,
570	   const int arg0,
571	   cpu *processor,
572	   unsigned_word cia)
573{
574  SYS(getegid);
575  emul_write_status(processor, (int)getegid(), 0);
576}
577#endif
578
579#ifndef HAVE_GETGID
580#define do_getgid 0
581#else
582static void
583do_getgid(os_emul_data *emul,
584	  unsigned call,
585	  const int arg0,
586	  cpu *processor,
587	  unsigned_word cia)
588{
589  SYS(getgid);
590  emul_write_status(processor, (int)getgid(), 0);
591}
592#endif
593
594#ifndef HAVE_SIGPROCMASK
595#define do_sigprocmask 0
596#else
597static void
598do_sigprocmask(os_emul_data *emul,
599	       unsigned call,
600	       const int arg0,
601	       cpu *processor,
602	       unsigned_word cia)
603{
604  natural_word how = cpu_registers(processor)->gpr[arg0];
605  unsigned_word set = cpu_registers(processor)->gpr[arg0+1];
606  unsigned_word oset = cpu_registers(processor)->gpr[arg0+2];
607#ifdef SYS_sigprocmask
608  SYS(sigprocmask);
609#endif
610
611  if (WITH_TRACE && ppc_trace[trace_os_emul])
612    printf_filtered ("%ld, 0x%ld, 0x%ld", (long)how, (long)set, (long)oset);
613
614  emul_write_status(processor, 0, 0);
615  cpu_registers(processor)->gpr[4] = set;
616}
617#endif
618
619#ifndef HAVE_IOCTL
620#define do_ioctl 0
621#else
622static void
623do_ioctl(os_emul_data *emul,
624	 unsigned call,
625	 const int arg0,
626	 cpu *processor,
627	 unsigned_word cia)
628{
629  int d = cpu_registers(processor)->gpr[arg0];
630  unsigned request = cpu_registers(processor)->gpr[arg0+1];
631  unsigned_word argp_addr = cpu_registers(processor)->gpr[arg0+2];
632
633#if !WITH_NetBSD_HOST
634  cpu_registers(processor)->gpr[arg0] = 0; /* just succeed */
635#else
636  unsigned dir = request & IOC_DIRMASK;
637  int status;
638  SYS(ioctl);
639  /* what we haven't done */
640  if (dir & IOC_IN /* write into the io device */
641      || dir & IOC_OUT
642      || !(dir & IOC_VOID))
643    error("do_ioctl() read or write of parameter not implemented\n");
644  status = ioctl(d, request, NULL);
645  emul_write_status(processor, status, errno);
646#endif
647
648  if (WITH_TRACE && ppc_trace[trace_os_emul])
649    printf_filtered ("%d, 0x%x, 0x%lx", d, request, (long)argp_addr);
650}
651#endif
652
653#ifndef HAVE_UMASK
654#define do_umask 0
655#else
656static void
657do_umask(os_emul_data *emul,
658	 unsigned call,
659	 const int arg0,
660	 cpu *processor,
661	 unsigned_word cia)
662{
663  int mask = cpu_registers(processor)->gpr[arg0];
664
665  if (WITH_TRACE && ppc_trace[trace_os_emul])
666    printf_filtered ("0%o", mask);
667
668  SYS(umask);
669  emul_write_status(processor, umask(mask), 0);
670}
671#endif
672
673#ifndef HAVE_DUP2
674#define do_dup2 0
675#else
676static void
677do_dup2(os_emul_data *emul,
678	unsigned call,
679	const int arg0,
680	cpu *processor,
681	unsigned_word cia)
682{
683  int oldd = cpu_registers(processor)->gpr[arg0];
684  int newd = cpu_registers(processor)->gpr[arg0+1];
685  int status = dup2(oldd, newd);
686  int err = errno;
687
688  if (WITH_TRACE && ppc_trace[trace_os_emul])
689    printf_filtered ("%d, %d", oldd, newd);
690
691  SYS(dup2);
692  emul_write_status(processor, status, err);
693}
694#endif
695
696#ifndef HAVE_FCNTL
697#define do_fcntl 0
698#else
699static void
700do_fcntl(os_emul_data *emul,
701	 unsigned call,
702	 const int arg0,
703	 cpu *processor,
704	 unsigned_word cia)
705{
706  int fd = cpu_registers(processor)->gpr[arg0];
707  int cmd = cpu_registers(processor)->gpr[arg0+1];
708  int arg = cpu_registers(processor)->gpr[arg0+2];
709  int status;
710
711  if (WITH_TRACE && ppc_trace[trace_os_emul])
712    printf_filtered ("%d, %d, %d", fd, cmd, arg);
713
714  SYS(fcntl);
715  status = fcntl(fd, cmd, arg);
716  emul_write_status(processor, status, errno);
717}
718#endif
719
720#ifndef HAVE_GETTIMEOFDAY
721#define do_gettimeofday 0
722#else
723static void
724do_gettimeofday(os_emul_data *emul,
725		unsigned call,
726		const int arg0,
727		cpu *processor,
728		unsigned_word cia)
729{
730  unsigned_word t_addr = cpu_registers(processor)->gpr[arg0];
731  unsigned_word tz_addr = cpu_registers(processor)->gpr[arg0+1];
732  struct timeval t;
733  struct timezone tz;
734  int status = gettimeofday((t_addr != 0 ? &t : NULL),
735			    (tz_addr != 0 ? &tz : NULL));
736  int err = errno;
737
738  if (WITH_TRACE && ppc_trace[trace_os_emul])
739    printf_filtered ("0x%lx, 0x%lx", (long)t_addr, (long)tz_addr);
740
741  SYS(__gettimeofday50);
742  emul_write_status(processor, status, err);
743  if (status == 0) {
744    if (t_addr != 0)
745      write_timeval(t_addr, t, processor, cia);
746    if (tz_addr != 0)
747      write_timezone(tz_addr, tz, processor, cia);
748  }
749}
750#endif
751
752#ifndef HAVE_GETRUSAGE
753#define do_getrusage 0
754#else
755static void
756do_getrusage(os_emul_data *emul,
757	     unsigned call,
758	     const int arg0,
759	     cpu *processor,
760	     unsigned_word cia)
761{
762  int who = cpu_registers(processor)->gpr[arg0];
763  unsigned_word rusage_addr = cpu_registers(processor)->gpr[arg0+1];
764  struct rusage rusage;
765  int status = getrusage(who, (rusage_addr != 0 ? &rusage : NULL));
766  int err = errno;
767
768  if (WITH_TRACE && ppc_trace[trace_os_emul])
769    printf_filtered ("%d, 0x%lx", who, (long)rusage_addr);
770
771  SYS(__getrusage50);
772  emul_write_status(processor, status, err);
773  if (status == 0) {
774    if (rusage_addr != 0)
775      write_rusage(rusage_addr, rusage, processor, cia);
776  }
777}
778#endif
779
780
781#ifndef HAVE_FSTATFS
782#define do_fstatfs 0
783#else
784static void
785do_fstatfs(os_emul_data *emul,
786	   unsigned call,
787	   const int arg0,
788	   cpu *processor,
789	   unsigned_word cia)
790{
791  int fd = cpu_registers(processor)->gpr[arg0];
792  unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
793  struct statfs buf;
794  int status;
795
796  if (WITH_TRACE && ppc_trace[trace_os_emul])
797    printf_filtered ("%d, 0x%lx", fd, (long)buf_addr);
798
799  SYS(fstatfs);
800  status = fstatfs(fd, (buf_addr == 0 ? NULL : &buf));
801  emul_write_status(processor, status, errno);
802  if (status == 0) {
803    if (buf_addr != 0)
804      write_statfs(buf_addr, buf, processor, cia);
805  }
806}
807#endif
808
809#ifndef HAVE_STAT
810#define do_stat 0
811#else
812static void
813do_stat(os_emul_data *emul,
814	unsigned call,
815	const int arg0,
816	cpu *processor,
817	unsigned_word cia)
818{
819  char path_buf[PATH_MAX];
820  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
821  unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
822  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
823  struct stat buf;
824  int status;
825#ifdef SYS_stat
826  SYS(stat);
827#endif
828  status = stat(path, &buf);
829  emul_write_status(processor, status, errno);
830  if (status == 0)
831    write_stat(stat_buf_addr, buf, processor, cia);
832}
833#endif
834
835#ifndef HAVE_FSTAT
836#define do_fstat 0
837#else
838static void
839do_fstat(os_emul_data *emul,
840	 unsigned call,
841	 const int arg0,
842	 cpu *processor,
843	 unsigned_word cia)
844{
845  int fd = cpu_registers(processor)->gpr[arg0];
846  unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
847  struct stat buf;
848  int status;
849#ifdef SYS_fstat
850  SYS(fstat);
851#endif
852  /* Can't combine these statements, cuz fstat sets errno. */
853  status = fstat(fd, &buf);
854  emul_write_status(processor, status, errno);
855  write_stat(stat_buf_addr, buf, processor, cia);
856}
857#endif
858
859#ifndef HAVE_LSTAT
860#define do_lstat 0
861#else
862static void
863do_lstat(os_emul_data *emul,
864	 unsigned call,
865	 const int arg0,
866	 cpu *processor,
867	 unsigned_word cia)
868{
869  char path_buf[PATH_MAX];
870  unsigned_word path_addr = cpu_registers(processor)->gpr[arg0];
871  char *path = emul_read_string(path_buf, path_addr, PATH_MAX, processor, cia);
872  unsigned_word stat_buf_addr = cpu_registers(processor)->gpr[arg0+1];
873  struct stat buf;
874  int status;
875#ifdef SYS_lstat
876  SYS(lstat);
877#endif
878  /* Can't combine these statements, cuz lstat sets errno. */
879  status = lstat(path, &buf);
880  emul_write_status(processor, status, errno);
881  write_stat(stat_buf_addr, buf, processor, cia);
882}
883#endif
884
885#ifndef HAVE_GETDIRENTRIES
886#define do_getdirentries 0
887#else
888static void
889do_getdirentries(os_emul_data *emul,
890		 unsigned call,
891		 const int arg0,
892		 cpu *processor,
893		 unsigned_word cia)
894{
895  int fd = cpu_registers(processor)->gpr[arg0];
896  unsigned_word buf_addr = cpu_registers(processor)->gpr[arg0+1];
897  char *buf;
898  int nbytes = cpu_registers(processor)->gpr[arg0+2];
899  unsigned_word basep_addr = cpu_registers(processor)->gpr[arg0+3];
900  long basep;
901  int status;
902#ifdef SYS_getdirentries
903  SYS(getdirentries);
904#endif
905  if (buf_addr != 0 && nbytes >= 0)
906    buf = zalloc(nbytes);
907  else
908    buf = NULL;
909  status = getdirentries(fd,
910			 (buf_addr == 0 ? NULL : buf),
911			 nbytes,
912			 (basep_addr == 0 ? NULL : &basep));
913  emul_write_status(processor, status, errno);
914  if (basep_addr != 0)
915    emul_write_word(basep_addr, basep, processor, cia);
916  if (status > 0)
917    write_direntries(buf_addr, buf, status, processor, cia);
918  if (buf != NULL)
919    free(buf);
920}
921#endif
922
923
924static void
925do___syscall(os_emul_data *emul,
926	     unsigned call,
927	     const int arg0,
928	     cpu *processor,
929	     unsigned_word cia)
930{
931  SYS(__syscall);
932  emul_do_system_call(emul,
933		      emul->syscalls,
934		      cpu_registers(processor)->gpr[arg0],
935		      arg0 + 1,
936		      processor,
937		      cia);
938}
939
940#ifndef HAVE_LSEEK
941#define do_lseek 0
942#else
943static void
944do_lseek(os_emul_data *emul,
945	 unsigned call,
946	 const int arg0,
947	 cpu *processor,
948	 unsigned_word cia)
949{
950  int fildes = cpu_registers(processor)->gpr[arg0];
951  off_t offset = emul_read_gpr64(processor, arg0+2);
952  int whence = cpu_registers(processor)->gpr[arg0+4];
953  off_t status;
954  SYS(lseek);
955  status = lseek(fildes, offset, whence);
956  if (status == -1)
957    emul_write_status(processor, -1, errno);
958  else {
959    emul_write_status(processor, 0, 0); /* success */
960    emul_write_gpr64(processor, 3, status);
961  }
962}
963#endif
964
965static void
966do___sysctl(os_emul_data *emul,
967	    unsigned call,
968	    const int arg0,
969	    cpu *processor,
970	    unsigned_word cia)
971{
972  /* call the arguments by their real name */
973  unsigned_word name = cpu_registers(processor)->gpr[arg0];
974  natural_word namelen = cpu_registers(processor)->gpr[arg0+1];
975  unsigned_word oldp = cpu_registers(processor)->gpr[arg0+2];
976  unsigned_word oldlenp = cpu_registers(processor)->gpr[arg0+3];
977  natural_word oldlen;
978  natural_word mib;
979  natural_word int_val;
980  SYS(__sysctl);
981
982  /* pluck out the management information base id */
983  if (namelen < 1)
984    error("system_call()SYS___sysctl bad name[0]\n");
985  mib = vm_data_map_read_word(cpu_data_map(processor),
986			      name,
987			      processor,
988			      cia);
989  name += sizeof(mib);
990
991  /* see what to do with it ... */
992  switch ((int)mib) {
993  case 6/*CTL_HW*/:
994#if WITH_NetBSD_HOST && (CTL_HW != 6)
995#  error "CTL_HW"
996#endif
997    if (namelen < 2)
998      error("system_call()SYS___sysctl - CTL_HW - bad name[1]\n");
999    mib = vm_data_map_read_word(cpu_data_map(processor),
1000				name,
1001				processor,
1002				cia);
1003    name += sizeof(mib);
1004    switch ((int)mib) {
1005    case 7/*HW_PAGESIZE*/:
1006#if WITH_NetBSD_HOST && (HW_PAGESIZE != 7)
1007#  error "HW_PAGESIZE"
1008#endif
1009      oldlen = vm_data_map_read_word(cpu_data_map(processor),
1010				     oldlenp,
1011				     processor,
1012				     cia);
1013      if (sizeof(natural_word) > oldlen)
1014	error("system_call()sysctl - CTL_HW.HW_PAGESIZE - to small\n");
1015      int_val = 8192;
1016      oldlen = sizeof(int_val);
1017      emul_write_word(oldp, int_val, processor, cia);
1018      emul_write_word(oldlenp, oldlen, processor, cia);
1019      break;
1020    default:
1021      error("sysctl() CTL_HW.%d unknown\n", mib);
1022      break;
1023    }
1024    break;
1025  default:
1026    error("sysctl() name[0]=%d unknown\n", (int)mib);
1027    break;
1028  }
1029  emul_write_status(processor, 0, 0); /* always succeed */
1030}
1031
1032
1033
1034static emul_syscall_descriptor netbsd_descriptors[] = {
1035  /* 0 */ { 0, "syscall" },
1036  /* 1 */ { do_exit, "exit" },
1037  /* 2 */ { 0, "fork" },
1038  /* 3 */ { do_read, "read" },
1039  /* 4 */ { do_write, "write" },
1040  /* 5 */ { do_open, "open" },
1041  /* 6 */ { do_close, "close" },
1042  { 0, }, /* 7 is old wait4 */
1043  { 0, }, /* 8 is old creat */
1044  /* 9 */ { 0, "link" },
1045  /* 10 */ { 0, "unlink" },
1046  { 0, }, /* 11 is obsolete execv */
1047  /* 12 */ { 0, "chdir" },
1048  /* 13 */ { 0, "fchdir" },
1049  { 0, }, /* 14 is old mknod */
1050  /* 15 */ { 0, "chmod" },
1051  /* 16 */ { 0, "chown" },
1052  /* 17 */ { do_break, "break" },
1053  { 0, }, /* 18 is old getfsstat */
1054  { 0, }, /* 19 is old lseek */
1055  /* 20 */ { do_getpid, "getpid" },
1056  { 0, }, /* 21 is old mount */
1057  /* 22 */ { 0, "unmount" },
1058  /* 23 */ { 0, "setuid" },
1059  /* 24 */ { do_getuid, "getuid" },
1060  /* 25 */ { do_geteuid, "geteuid" },
1061  /* 26 */ { 0, "ptrace" },
1062  /* 27 */ { 0, "recvmsg" },
1063  /* 28 */ { 0, "sendmsg" },
1064  /* 29 */ { 0, "recvfrom" },
1065  /* 30 */ { 0, "accept" },
1066  /* 31 */ { 0, "getpeername" },
1067  /* 32 */ { 0, "getsockname" },
1068  /* 33 */ { 0, "access" },
1069  /* 34 */ { 0, "chflags" },
1070  /* 35 */ { 0, "fchflags" },
1071  /* 36 */ { 0, "sync" },
1072  /* 37 */ { do_kill, "kill" },
1073  { 0, }, /* 38 is old stat */
1074  /* 39 */ { 0, "getppid" },
1075  { 0, }, /* 40 is old lstat */
1076  /* 41 */ { do_dup, "dup" },
1077  /* 42 */ { 0, "pipe" },
1078  /* 43 */ { do_getegid, "getegid" },
1079  /* 44 */ { 0, "profil" },
1080  /* 45 */ { 0, "ktrace" },
1081  { 0, }, /* 46 is old sigaction */
1082  /* 47 */ { do_getgid, "getgid" },
1083  { 0, }, /* 48 is old sigprocmask */
1084  /* 49 */ { 0, "getlogin" },
1085  /* 50 */ { 0, "setlogin" },
1086  /* 51 */ { 0, "acct" },
1087  { 0, }, /* 52 is old sigpending */
1088  { 0, }, /* 53 is old sigaltstack */
1089  /* 54 */ { do_ioctl, "ioctl" },
1090  { 0, }, /* 55 is old reboot */
1091  /* 56 */ { 0, "revoke" },
1092  /* 57 */ { 0, "symlink" },
1093  /* 58 */ { 0, "readlink" },
1094  /* 59 */ { 0, "execve" },
1095  /* 60 */ { do_umask, "umask" },
1096  /* 61 */ { 0, "chroot" },
1097  { 0, }, /* 62 is old fstat */
1098  { 0, }, /* 63 is old getkerninfo */
1099  { 0, }, /* 64 is old getpagesize */
1100  { 0, }, /* 65 is old msync */
1101  /* 66 */ { 0, "vfork" },
1102  { 0, }, /* 67 is obsolete vread */
1103  { 0, }, /* 68 is obsolete vwrite */
1104  /* 69 */ { 0, "sbrk" },
1105  /* 70 */ { 0, "sstk" },
1106  { 0, }, /* 71 is old mmap */
1107  /* 72 */ { 0, "vadvise" },
1108  /* 73 */ { 0, "munmap" },
1109  /* 74 */ { 0, "mprotect" },
1110  /* 75 */ { 0, "madvise" },
1111  { 0, }, /* 76 is obsolete vhangup */
1112  { 0, }, /* 77 is obsolete vlimit */
1113  /* 78 */ { 0, "mincore" },
1114  /* 79 */ { 0, "getgroups" },
1115  /* 80 */ { 0, "setgroups" },
1116  /* 81 */ { 0, "getpgrp" },
1117  /* 82 */ { 0, "setpgid" },
1118  { 0, }, /* 83 is old setitimer */
1119  { 0, }, /* 84 is old wait */
1120  { 0, }, /* 85 is old swapon */
1121  { 0, }, /* 86 is old getitimer */
1122  { 0, }, /* 87 is old gethostname */
1123  { 0, }, /* 88 is old sethostname */
1124  { 0, }, /* 89 is old getdtablesize */
1125  { do_dup2, "dup2" },
1126  { 0, }, /* 91 */
1127  /* 92 */ { do_fcntl, "fcntl" },
1128  { 0, }, /* 93 is old select */
1129  { 0, }, /* 94 */
1130  /* 95 */ { 0, "fsync" },
1131  /* 96 */ { 0, "setpriority" },
1132  { 0, }, /* 97 is old socket */
1133  { 0, }, /* 98 is old connect */
1134  { 0, }, /* 99 is old accept */
1135  /* 100 */ { 0, "getpriority" },
1136  { 0, }, /* 101 is old send */
1137  { 0, }, /* 102 is old recv */
1138  { 0, }, /* 103 is old sigreturn */
1139  /* 104 */ { 0, "bind" },
1140  /* 105 */ { 0, "setsockopt" },
1141  /* 106 */ { 0, "listen" },
1142  { 0, }, /* 107 is obsolete vtimes */
1143  { 0, }, /* 108 is old sigvec */
1144  { 0, }, /* 109 is old sigblock */
1145  { 0, }, /* 110 is old sigsetmask */
1146  { 0, }, /* 111 is old sigsuspend */
1147  { 0, }, /* 112 is old sigstack */
1148  { 0, }, /* 113 is old recvmsg */
1149  { 0, }, /* 114 is old sendmsg */
1150  /* - is obsolete vtrace */ { 0, "vtrace	115" },
1151  { 0, }, /* 116 is old gettimeofday */
1152  { 0, }, /* 117 is old getrusage */
1153  /* 118 */ { 0, "getsockopt" },
1154  /* - is obsolete resuba */ { 0, "resuba	119" },
1155  /* 120 */ { 0, "readv" },
1156  /* 121 */ { 0, "writev" },
1157  { 0, }, /* 122 is old settimeofday */
1158  /* 123 */ { 0, "fchown" },
1159  /* 124 */ { 0, "fchmod" },
1160  { 0, }, /* 125 is old recvfrom */
1161  { 0, }, /* 126 is old setreuid */
1162  { 0, }, /* 127 is old setregid */
1163  /* 126 */ { 0, "setreuid" },
1164  /* 127 */ { 0, "setregid" },
1165  /* 128 */ { 0, "rename" },
1166  { 0, }, /* 129 is old truncate */
1167  { 0, }, /* 130 is old ftruncate */
1168  /* 131 */ { 0, "flock" },
1169  /* 132 */ { 0, "mkfifo" },
1170  /* 133 */ { 0, "sendto" },
1171  /* 134 */ { 0, "shutdown" },
1172  /* 135 */ { 0, "socketpair" },
1173  /* 136 */ { 0, "mkdir" },
1174  /* 137 */ { 0, "rmdir" },
1175  { 0, }, /* 138 is old utimes */
1176  { 0, }, /* 139 is obsolete 4.2 sigreturn */
1177  { 0, }, /* 140 is old adjtime */
1178  { 0, }, /* 141 is old getpeername */
1179  { 0, }, /* 142 is old gethostid */
1180  { 0, }, /* 143 is old sethostid */
1181  { 0, }, /* 144 is old getrlimit */
1182  { 0, }, /* 145 is old setrlimit */
1183  { 0, }, /* 146 is old killpg */
1184  /* 147 */ { 0, "setsid" },
1185  /* 148 */ { 0, "quotactl" },
1186  { 0, }, /* 149 is old quota */
1187  { 0, }, /* 150 is old getsockname */
1188  { 0, }, /* 151 */
1189  { 0, }, /* 152 */
1190  { 0, }, /* 153 */
1191  { 0, }, /* 154 */
1192  /* 155 */ { 0, "nfssvc" },
1193  { 0, }, /* 156 is old getdirentries */
1194  { 0, }, /* 157 is old statfs */
1195  { 0, }, /* 158 is old fstatfs */
1196  { 0, }, /* 159 */
1197  { 0, }, /* 160 */
1198  { 0, }, /* 161 is old getfh */
1199  { 0, }, /* 162 is old getdomainname */
1200  { 0, }, /* 163 is old setdomainname */
1201  { 0, }, /* 164 is old uname */
1202  /* 165 */ { 0, "sysarch" },
1203  { 0, }, /* 166 */
1204  { 0, }, /* 167 */
1205  { 0, }, /* 168 */
1206  { 0, }, /* 169 is old semsys */
1207  { 0, }, /* 170 is old msgsys */
1208  { 0, }, /* 171 is old shmsys */
1209  { 0, }, /* 172 */
1210  /* 173 */ { 0, "pread" },
1211  /* 174 */ { 0, "pwrite" },
1212  { 0, }, /* 175 is old ntp_gettime */
1213  /* 176 */ { 0, "ntp_adjtime" },
1214  { 0, }, /* 177 */
1215  { 0, }, /* 178 */
1216  { 0, }, /* 179 */
1217  { 0, }, /* 180 */
1218  /* 181 */ { 0, "setgid" },
1219  /* 182 */ { 0, "setegid" },
1220  /* 183 */ { 0, "seteuid" },
1221  /* 184 */ { 0, "lfs_bmapv" },
1222  /* 185 */ { 0, "lfs_markv" },
1223  /* 186 */ { 0, "lfs_segclean" },
1224  /* 187 */ { 0, "lfs_segwait" },
1225  { 0, }, /* 188 is old stat" */
1226  { 0, }, /* 189 is old fstat */
1227  { 0, }, /* 190 is old lstat */
1228  /* 191 */ { 0, "pathconf" },
1229  /* 192 */ { 0, "fpathconf" },
1230  { 0, }, /* 193 */
1231  /* 194 */ { 0, "getrlimit" },
1232  /* 195 */ { 0, "setrlimit" },
1233  { 0, }, /* 196 is old getdirentries */
1234  /* 197 */ { 0, "mmap" },
1235  /* 198 */ { do___syscall, "__syscall" },
1236  /* 199 */ { do_lseek, "lseek" },
1237  /* 200 */ { 0, "truncate" },
1238  /* 201 */ { 0, "ftruncate" },
1239  /* 202 */ { do___sysctl, "__sysctl" },
1240  /* 203 */ { 0, "mlock" },
1241  /* 204 */ { 0, "munlock" },
1242  /* 205 */ { 0, "undelete" },
1243  { 0, }, /* 206 is old futimes */
1244  /* 207 */ { 0, "getpgid" },
1245  /* 208 */ { 0, "reboot" },
1246  /* 209 */ { 0, "poll" },
1247  { 0, }, /* 210 */
1248  { 0, }, /* 211 */
1249  { 0, }, /* 212 */
1250  { 0, }, /* 213 */
1251  { 0, }, /* 214 */
1252  { 0, }, /* 215 */
1253  { 0, }, /* 216 */
1254  { 0, }, /* 217 */
1255  { 0, }, /* 218 */
1256  { 0, }, /* 219 */
1257  { 0, }, /* 220 is old semctl */
1258  /* 221 */ { 0, "semget" },
1259  /* 222 */ { 0, "semop" },
1260  /* 223 */ { 0, "semconfig" },
1261  { 0, }, /* 224 is old msgctl */
1262  /* 225 */ { 0, "msgget" },
1263  /* 226 */ { 0, "msgsnd" },
1264  /* 227 */ { 0, "msgrcv" },
1265  /* 228 */ { 0, "shmat" },
1266  { 0, }, /* 229 is old shmctl */
1267  /* 230 */ { 0, "shmdt" },
1268  /* 231 */ { 0, "shmget" },
1269  { 0, }, /* 232 is old clock_gettime */
1270  { 0, }, /* 233 is old clock_settime */
1271  { 0, }, /* 234 is old clock_getres */
1272  /* 235 */ { 0, "timer_create" },
1273  /* 236 */ { 0, "timer_delete" },
1274  { 0, }, /* 237 is old timer_settime */
1275  { 0, }, /* 238 is old timer_gettime */
1276  /* 239 */ { 0, "timer_getoverrun" },
1277  { 0, }, /* 240 is old nanosleep */
1278  /* 241 */ { 0, "fdatasync" },
1279  /* 242 */ { 0, "mlockall" },
1280  /* 243 */ { 0, "munlockall" },
1281  { 0, }, /* 244 is old sigtimedwait */
1282  { 0, }, /* 245 */
1283  /* 246 */ { 0, "modctl" },
1284  /* 247 */ { 0, "_ksem_init" },
1285  /* 248 */ { 0, "_ksem_open" },
1286  /* 249 */ { 0, "_ksem_unlink" },
1287  /* 250 */ { 0, "_ksem_close" },
1288  /* 251 */ { 0, "_ksem_post" },
1289  /* 252 */ { 0, "_ksem_wait" },
1290  /* 253 */ { 0, "_ksem_trywait" },
1291  /* 254 */ { 0, "_ksem_getvalue" },
1292  /* 255 */ { 0, "_ksem_destroy" },
1293  { 0, }, /* 256 */
1294  /* 257 */ { 0, "mq_open" },
1295  /* 258 */ { 0, "mq_close" },
1296  /* 259 */ { 0, "mq_unlink" },
1297  /* 260 */ { 0, "mq_getattr" },
1298  /* 261 */ { 0, "mq_setattr" },
1299  /* 262 */ { 0, "mq_notify" },
1300  /* 263 */ { 0, "mq_send" },
1301  /* 264 */ { 0, "mq_receive" },
1302  { 0, }, /* 265 is old mq_timedsend */
1303  { 0, }, /* 266 is old mq_timedrecive */
1304  { 0, }, /* 267 */
1305  { 0, }, /* 268 */
1306  { 0, }, /* 269 */
1307  /* 270 */ { 0, "__posix_rename" },
1308  /* 271 */ { 0, "swapctl" },
1309  { 0, }, /* 272 is old getdents */
1310  /* 273 */ { 0, "minherit" },
1311  /* 274 */ { 0, "lchmod" },
1312  /* 275 */ { 0, "lchown" },
1313  { 0, }, /* 276 is old lutimes */
1314  /* 277 */ { 0, "__msync13" },
1315  { 0, }, /* 278 is old stat */
1316  { 0, }, /* 279 is old fstat */
1317  { 0, }, /* 280 is old lstat */
1318  /* 281 */ { 0, "__sigaltstack13" },
1319  /* 282 */ { 0, "__vfork14" },
1320  /* 283 */ { 0, "__posix_chown" },
1321  /* 284 */ { 0, "__posix_fchown" },
1322  /* 285 */ { 0, "__posix_lchown" },
1323  /* 286 */ { 0, "getsid" },
1324  /* 287 */ { 0, "__clone" },
1325  /* 288 */ { 0, "fktrace" },
1326  /* 289 */ { 0, "preadv" },
1327  /* 290 */ { 0, "pwritev" },
1328  { 0, }, /* 291 is old sigaction */
1329  /* 292 */ { 0, "__sigpending14" },
1330  /* 293 */ { do_sigprocmask, "__sigprocmask14" },
1331  /* 294 */ { 0, "__sigsuspend14" },
1332  /* 295 */ { 0, "__sigreturn14" },
1333  /* 296 */ { 0, "__getcwd" },
1334  /* 297 */ { 0, "fchroot" },
1335  { 0, }, /* 298 is old fhopen */
1336  { 0, }, /* 299 is old fhstat */
1337  { 0, }, /* 300 is old fhstatfs */
1338  { 0, }, /* 301 is old semctl */
1339  { 0, }, /* 302 is old msgctl */
1340  { 0, }, /* 303 is old shmctl */
1341  /* 304 */ { 0, "lchflags" },
1342  /* 305 */ { 0, "issetugid" },
1343  /* 306 */ { 0, "utrace" },
1344  /* 307 */ { 0, "getcontext" },
1345  /* 308 */ { 0, "setcontext" },
1346  /* 309 */ { 0, "_lwp_create" },
1347  /* 310 */ { 0, "_lwp_exit" },
1348  /* 311 */ { 0, "_lwp_self" },
1349  /* 312 */ { 0, "_lwp_wait" },
1350  /* 313 */ { 0, "_lwp_suspend" },
1351  /* 314 */ { 0, "_lwp_continue" },
1352  /* 315 */ { 0, "_lwp_wakeup" },
1353  /* 316 */ { 0, "_lwp_getprivate" },
1354  /* 317 */ { 0, "_lwp_setprivate" },
1355  /* 318 */ { 0, "_lwp_kill" },
1356  /* 319 */ { 0, "_lwp_detach" },
1357  { 0, }, /* 320 is old _lwp_park */
1358  /* 321 */ { 0, "_lwp_unpark" },
1359  /* 322 */ { 0, "_lwp_unpark_all" },
1360  /* 323 */ { 0, "_lwp_setname" },
1361  /* 324 */ { 0, "_lwp_getname" },
1362  /* 325 */ { 0, "_lwp_ctl" },
1363  { 0, }, /* 326 */
1364  { 0, }, /* 327 */
1365  { 0, }, /* 328 */
1366  { 0, }, /* 329 */
1367  /* 330 */ { 0, "sa_register" },
1368  /* 331 */ { 0, "sa_stacks" },
1369  /* 332 */ { 0, "sa_enable" },
1370  /* 333 */ { 0, "sa_setconcurrency" },
1371  /* 334 */ { 0, "sa_yield" },
1372  /* 335 */ { 0, "sa_preempt" },
1373  { 0, }, /* 336 */
1374  { 0, }, /* 337 */
1375  { 0, }, /* 338 */
1376  { 0, }, /* 339 */
1377  /* 340 */ { 0, "__sigaction_sigtramp" },
1378  /* 341 */ { 0, "pmc_get_info" },
1379  /* 342 */ { 0, "pmc_control" },
1380  /* 343 */ { 0, "rasctl" },
1381  /* 344 */ { 0, "kqueue" },
1382  { 0, }, /* 345 is old kevent */
1383  /* 346 */ { 0, "_sched_setparam" },
1384  /* 347 */ { 0, "_sched_getparam" },
1385  /* 348 */ { 0, "_sched_setaffinity" },
1386  /* 349 */ { 0, "_sched_getaffinity" },
1387  /* 350 */ { 0, "sched_yield" },
1388  { 0, }, /* 351 */
1389  { 0, }, /* 352 */
1390  { 0, }, /* 353 */
1391  /* 354 */ { 0, "fsync_range" },
1392  /* 355 */ { 0, "uuidgen" },
1393  /* 356 */ { 0, "getvfsstat" },
1394  /* 357 */ { 0, "statvfs1" },
1395  /* 358 */ { 0, "fstatvfs1" },
1396  { 0, }, /* 359 is old fhstatvfs1 */
1397  /* 360 */ { 0, "extattrctl" },
1398  /* 361 */ { 0, "extattr_set_file" },
1399  /* 362 */ { 0, "extattr_get_file" },
1400  /* 363 */ { 0, "extattr_delete_file" },
1401  /* 364 */ { 0, "extattr_set_fd" },
1402  /* 365 */ { 0, "extattr_get_fd" },
1403  /* 366 */ { 0, "extattr_delete_fd" },
1404  /* 367 */ { 0, "extattr_set_link" },
1405  /* 368 */ { 0, "extattr_get_link" },
1406  /* 369 */ { 0, "extattr_delete_link" },
1407  /* 370 */ { 0, "extattr_list_fd" },
1408  /* 371 */ { 0, "extattr_list_file" },
1409  /* 372 */ { 0, "extattr_list_link" },
1410  { 0, }, /* 373 is old pselect */
1411  { 0, }, /* 374 is old pollts */
1412  /* 375 */ { 0, "setxattr" },
1413  /* 376 */ { 0, "lsetxattr" },
1414  /* 377 */ { 0, "fsetxattr" },
1415  /* 378 */ { 0, "getxattr" },
1416  /* 379 */ { 0, "lgetxattr" },
1417  /* 380 */ { 0, "fgetxattr" },
1418  /* 381 */ { 0, "listxattr" },
1419  /* 382 */ { 0, "llistxattr" },
1420  /* 383 */ { 0, "flistxattr" },
1421  /* 384 */ { 0, "removexattr" },
1422  /* 385 */ { 0, "lremovexattr" },
1423  /* 386 */ { 0, "fremovexattr" },
1424  { 0, }, /* 387 is old stat */
1425  { 0, }, /* 388 is old fstat */
1426  { 0, }, /* 389 is old lstat */
1427  /* 390 */ { do_getdirentries, "__getdents30" },
1428  { 0, }, /* 391 is old posix_fadvise */
1429  { 0, }, /* 392 is old fhstat */
1430  { 0, }, /* 393 is old ntp_gettime */
1431  /* 394 */ { 0, "__socket30" },
1432  /* 395 */ { 0, "__getfh30" },
1433  /* 396 */ { 0, "__fhopen40" },
1434  /* 397 */ { 0, "__fhstatvfs140" },
1435  { 0, }, /* 398 is old fhstat */
1436  /* 399 */ { 0, "aio_cancel" },
1437  /* 400 */ { 0, "aio_error" },
1438  /* 401 */ { 0, "aio_fsync" },
1439  /* 402 */ { 0, "aio_read" },
1440  /* 403 */ { 0, "aio_return" },
1441  { 0, }, /* 404 is old aio_suspend */
1442  /* 405 */ { 0, "aio_write" },
1443  /* 406 */ { 0, "lio_listio" },
1444  { 0, }, /* 407 */
1445  { 0, }, /* 408 */
1446  { 0, }, /* 409 */
1447  /* 410 */ { 0, "__mount50" },
1448  /* 411 */ { 0, "mremap" },
1449  /* 412 */ { 0, "pset_create" },
1450  /* 413 */ { 0, "pset_destroy" },
1451  /* 414 */ { 0, "pset_assign" },
1452  /* 415 */ { 0, "_pset_bind" },
1453  /* 416 */ { 0, "__posix_fadvise50" },
1454  /* 417 */ { 0, "__select50" },
1455  /* 418 */ { do_gettimeofday, "__gettimeofday50" },
1456  /* 419 */ { 0, "__settimeofday50" },
1457  /* 420 */ { 0, "__utimes50" },
1458  /* 421 */ { 0, "__adjtime50" },
1459  /* 422 */ { 0, "__lfs_segwait50" },
1460  /* 423 */ { 0, "__futimes50" },
1461  /* 424 */ { 0, "__lutimes50" },
1462  /* 425 */ { 0, "__setitimer50" },
1463  /* 426 */ { 0, "__getitimer50" },
1464  /* 427 */ { 0, "__clock_gettime50" },
1465  /* 428 */ { 0, "__clock_settime50" },
1466  /* 429 */ { 0, "__clock_getres50" },
1467  /* 430 */ { 0, "__nanosleep50" },
1468  /* 431 */ { 0, "____sigtimedwait50" },
1469  /* 432 */ { 0, "__mq_timedsend50" },
1470  /* 433 */ { 0, "__mq_timedreceive50" },
1471  /* 434 */ { 0, "____lwp_park50" },
1472  /* 435 */ { 0, "__kevent50" },
1473  /* 436 */ { 0, "__pselect50" },
1474  /* 437 */ { 0, "__pollts50" },
1475  /* 438 */ { 0, "__aio_suspend50" },
1476  /* 439 */ { do_stat, "__stat50" },
1477  /* 440 */ { do_fstat, "__fstat50" },
1478  /* 441 */ { do_lstat, "__lstat50" },
1479  /* 442 */ { 0, "____semctl50" },
1480  /* 443 */ { 0, "__shmctl50" },
1481  /* 444 */ { 0, "__msgctl50" },
1482  /* 445 */ { do_getrusage, "__getrusage50" },
1483  /* 446 */ { 0, "__timer_settime50" },
1484  /* 447 */ { 0, "__timer_gettime50" },
1485  /* 448 */ { 0, "__ntp_gettime50" },
1486  /* 449 */ { 0, "__wait450" },
1487  /* 450 */ { 0, "__mknod50" },
1488  /* 451 */ { 0, "__fhstat50" },
1489  { 0, }, /* 452 is obsolete 5.99 __quotactl50 */
1490  /* 453 */ { 0, "pipe2" },
1491  /* 454 */ { 0, "dup3" },
1492  /* 455 */ { 0, "kqueue1" },
1493  /* 456 */ { 0, "paccept" },
1494  /* 457 */ { 0, "linkat" },
1495  /* 458 */ { 0, "renameat" },
1496  /* 459 */ { 0, "mkfifoat" },
1497  /* 460 */ { 0, "mknodat" },
1498  /* 461 */ { 0, "mkdirat" },
1499  /* 462 */ { 0, "faccessat" },
1500  /* 463 */ { 0, "fchmodat" },
1501  /* 464 */ { 0, "fchownat" },
1502  /* 465 */ { 0, "fexecve" },
1503  /* 466 */ { 0, "fstatat" },
1504  /* 467 */ { 0, "utimensat" },
1505  /* 468 */ { 0, "openat" },
1506  /* 469 */ { 0, "readlinkat" },
1507  /* 470 */ { 0, "symlinkat" },
1508  /* 471 */ { 0, "unlinkat" },
1509  /* 472 */ { 0, "futimens" },
1510  /* 473 */ { 0, "__quotactl" },
1511};
1512
1513static char *(netbsd_error_names[]) = {
1514  /* 0 */ "ESUCCESS",
1515  /* 1 */ "EPERM",
1516  /* 2 */ "ENOENT",
1517  /* 3 */ "ESRCH",
1518  /* 4 */ "EINTR",
1519  /* 5 */ "EIO",
1520  /* 6 */ "ENXIO",
1521  /* 7 */ "E2BIG",
1522  /* 8 */ "ENOEXEC",
1523  /* 9 */ "EBADF",
1524  /* 10 */ "ECHILD",
1525  /* 11 */ "EDEADLK",
1526  /* 12 */ "ENOMEM",
1527  /* 13 */ "EACCES",
1528  /* 14 */ "EFAULT",
1529  /* 15 */ "ENOTBLK",
1530  /* 16 */ "EBUSY",
1531  /* 17 */ "EEXIST",
1532  /* 18 */ "EXDEV",
1533  /* 19 */ "ENODEV",
1534  /* 20 */ "ENOTDIR",
1535  /* 21 */ "EISDIR",
1536  /* 22 */ "EINVAL",
1537  /* 23 */ "ENFILE",
1538  /* 24 */ "EMFILE",
1539  /* 25 */ "ENOTTY",
1540  /* 26 */ "ETXTBSY",
1541  /* 27 */ "EFBIG",
1542  /* 28 */ "ENOSPC",
1543  /* 29 */ "ESPIPE",
1544  /* 30 */ "EROFS",
1545  /* 31 */ "EMLINK",
1546  /* 32 */ "EPIPE",
1547  /* 33 */ "EDOM",
1548  /* 34 */ "ERANGE",
1549  /* 35 */ "EAGAIN",
1550  /* 36 */ "EINPROGRESS",
1551  /* 37 */ "EALREADY",
1552  /* 38 */ "ENOTSOCK",
1553  /* 39 */ "EDESTADDRREQ",
1554  /* 40 */ "EMSGSIZE",
1555  /* 41 */ "EPROTOTYPE",
1556  /* 42 */ "ENOPROTOOPT",
1557  /* 43 */ "EPROTONOSUPPORT",
1558  /* 44 */ "ESOCKTNOSUPPORT",
1559  /* 45 */ "EOPNOTSUPP",
1560  /* 46 */ "EPFNOSUPPORT",
1561  /* 47 */ "EAFNOSUPPORT",
1562  /* 48 */ "EADDRINUSE",
1563  /* 49 */ "EADDRNOTAVAIL",
1564  /* 50 */ "ENETDOWN",
1565  /* 51 */ "ENETUNREACH",
1566  /* 52 */ "ENETRESET",
1567  /* 53 */ "ECONNABORTED",
1568  /* 54 */ "ECONNRESET",
1569  /* 55 */ "ENOBUFS",
1570  /* 56 */ "EISCONN",
1571  /* 57 */ "ENOTCONN",
1572  /* 58 */ "ESHUTDOWN",
1573  /* 59 */ "ETOOMANYREFS",
1574  /* 60 */ "ETIMEDOUT",
1575  /* 61 */ "ECONNREFUSED",
1576  /* 62 */ "ELOOP",
1577  /* 63 */ "ENAMETOOLONG",
1578  /* 64 */ "EHOSTDOWN",
1579  /* 65 */ "EHOSTUNREACH",
1580  /* 66 */ "ENOTEMPTY",
1581  /* 67 */ "EPROCLIM",
1582  /* 68 */ "EUSERS",
1583  /* 69 */ "EDQUOT",
1584  /* 70 */ "ESTALE",
1585  /* 71 */ "EREMOTE",
1586  /* 72 */ "EBADRPC",
1587  /* 73 */ "ERPCMISMATCH",
1588  /* 74 */ "EPROGUNAVAIL",
1589  /* 75 */ "EPROGMISMATCH",
1590  /* 76 */ "EPROCUNAVAIL",
1591  /* 77 */ "ENOLCK",
1592  /* 78 */ "ENOSYS",
1593  /* 79 */ "EFTYPE",
1594  /* 80 */ "EAUTH",
1595  /* 81 */ "ENEEDAUTH",
1596  /* 82 */ "EIDRM",
1597  /* 83 */ "ENOMSG",
1598  /* 84 */ "EOVERFLOW",
1599  /* 85 */ "EILSEQ",
1600  /* 86 */ "ENOTSUP",
1601  /* 87 */ "ECANCELED",
1602  /* 88 */ "EBADMSG",
1603  /* 89 */ "ENODATA",
1604  /* 90 */ "ENOSR",
1605  /* 91 */ "ENOSTR",
1606  /* 92 */ "ETIME",
1607  /* 93 */ "ENOATTR",
1608  /* 94 */ "EMULTIHOP",
1609  /* 95 */ "ENOLINK",
1610  /* 96 */ "EPROTO",
1611  /* 96 */ "ELAST",
1612};
1613
1614static char *(netbsd_signal_names[]) = {
1615  /* 0 */ 0,
1616  /* 1 */ "SIGHUP",
1617  /* 2 */ "SIGINT",
1618  /* 3 */ "SIGQUIT",
1619  /* 4 */ "SIGILL",
1620  /* 5 */ "SIGTRAP",
1621  /* 6 */ "SIGABRT",
1622  /* 7 */ "SIGEMT",
1623  /* 8 */ "SIGFPE",
1624  /* 9 */ "SIGKILL",
1625  /* 10 */ "SIGBUS",
1626  /* 11 */ "SIGSEGV",
1627  /* 12 */ "SIGSYS",
1628  /* 13 */ "SIGPIPE",
1629  /* 14 */ "SIGALRM",
1630  /* 15 */ "SIGTERM",
1631  /* 16 */ "SIGURG",
1632  /* 17 */ "SIGSTOP",
1633  /* 18 */ "SIGTSTP",
1634  /* 19 */ "SIGCONT",
1635  /* 20 */ "SIGCHLD",
1636  /* 21 */ "SIGTTIN",
1637  /* 22 */ "SIGTTOU",
1638  /* 23 */ "SIGIO",
1639  /* 24 */ "SIGXCPU",
1640  /* 25 */ "SIGXFSZ",
1641  /* 26 */ "SIGVTALRM",
1642  /* 27 */ "SIGPROF",
1643  /* 28 */ "SIGWINCH",
1644  /* 29 */ "SIGINFO",
1645  /* 30 */ "SIGUSR1",
1646  /* 31 */ "SIGUSR2",
1647  /* 32 */ "SIGPWR",
1648};
1649
1650static emul_syscall emul_netbsd_syscalls = {
1651  netbsd_descriptors,
1652  sizeof(netbsd_descriptors) / sizeof(netbsd_descriptors[0]),
1653  netbsd_error_names,
1654  sizeof(netbsd_error_names) / sizeof(netbsd_error_names[0]),
1655  netbsd_signal_names,
1656  sizeof(netbsd_signal_names) / sizeof(netbsd_signal_names[0]),
1657};
1658
1659
1660/* NetBSD's os_emul interface, most are just passed on to the generic
1661   syscall stuff */
1662
1663static os_emul_data *
1664emul_netbsd_create(device *root,
1665		   bfd *image,
1666		   const char *name)
1667{
1668  unsigned_word top_of_stack;
1669  unsigned stack_size;
1670  int elf_binary;
1671  os_emul_data *bsd_data;
1672  device *vm;
1673  char *filename;
1674
1675  /* check that this emulation is really for us */
1676  if (name != NULL && strcmp(name, "netbsd") != 0)
1677    return NULL;
1678  if (image == NULL)
1679    return NULL;
1680
1681
1682  /* merge any emulation specific entries into the device tree */
1683
1684  /* establish a few defaults */
1685  if (image->xvec->flavour == bfd_target_elf_flavour) {
1686    elf_binary = 1;
1687    top_of_stack = 0xe0000000;
1688    stack_size =   0x00100000;
1689  }
1690  else {
1691    elf_binary = 0;
1692    top_of_stack = 0x20000000;
1693    stack_size =   0x00100000;
1694  }
1695
1696  /* options */
1697  emul_add_tree_options(root, image, "netbsd",
1698			(WITH_ENVIRONMENT == USER_ENVIRONMENT
1699			 ? "user" : "virtual"),
1700			0 /*oea-interrupt-prefix*/);
1701
1702  /* virtual memory - handles growth of stack/heap */
1703  vm = tree_parse(root, "/openprom/vm");
1704  tree_parse(vm, "./stack-base 0x%lx",
1705	     (unsigned long)(top_of_stack - stack_size));
1706  tree_parse(vm, "./nr-bytes 0x%x", stack_size);
1707
1708  filename = tree_quote_property (bfd_get_filename(image));
1709  tree_parse(root, "/openprom/vm/map-binary/file-name %s",
1710	     filename);
1711  free (filename);
1712
1713  /* finish the init */
1714  tree_parse(root, "/openprom/init/register/pc 0x%lx",
1715	     (unsigned long)bfd_get_start_address(image));
1716  tree_parse(root, "/openprom/init/register/sp 0x%lx",
1717	     (unsigned long)top_of_stack);
1718  tree_parse(root, "/openprom/init/register/msr 0x%x",
1719	     ((tree_find_boolean_property(root, "/options/little-endian?")
1720	       ? msr_little_endian_mode
1721	       : 0)
1722	      | (tree_find_boolean_property(root, "/openprom/options/floating-point?")
1723		 ? (msr_floating_point_available
1724		    | msr_floating_point_exception_mode_0
1725		    | msr_floating_point_exception_mode_1)
1726		 : 0)));
1727  tree_parse(root, "/openprom/init/stack/stack-type %s",
1728	     (elf_binary ? "ppc-elf" : "ppc-xcoff"));
1729
1730  /* finally our emulation data */
1731  bsd_data = ZALLOC(os_emul_data);
1732  bsd_data->vm = vm;
1733  bsd_data->syscalls = &emul_netbsd_syscalls;
1734  return bsd_data;
1735}
1736
1737static void
1738emul_netbsd_init(os_emul_data *emul_data,
1739		 int nr_cpus)
1740{
1741  /* nothing yet */
1742}
1743
1744static void
1745emul_netbsd_system_call(cpu *processor,
1746			unsigned_word cia,
1747			os_emul_data *emul_data)
1748{
1749  emul_do_system_call(emul_data,
1750		      emul_data->syscalls,
1751		      cpu_registers(processor)->gpr[0],
1752		      3, /*r3 contains arg0*/
1753		      processor,
1754		      cia);
1755}
1756
1757const os_emul emul_netbsd = {
1758  "netbsd",
1759  emul_netbsd_create,
1760  emul_netbsd_init,
1761  emul_netbsd_system_call,
1762  0, /*instruction_call*/
1763  0 /*data*/
1764};
1765
1766#endif	/* _EMUL_NETBSD_C_ */
1767