Annotation of qemu/darwin-user/syscall.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *  Darwin syscalls
        !             3:  *
        !             4:  *  Copyright (c) 2003 Fabrice Bellard
        !             5:  *  Copyright (c) 2006 Pierre d'Herbemont
        !             6:  *
        !             7:  *  This program is free software; you can redistribute it and/or modify
        !             8:  *  it under the terms of the GNU General Public License as published by
        !             9:  *  the Free Software Foundation; either version 2 of the License, or
        !            10:  *  (at your option) any later version.
        !            11:  *
        !            12:  *  This program is distributed in the hope that it will be useful,
        !            13:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            14:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            15:  *  GNU General Public License for more details.
        !            16:  *
        !            17:  *  You should have received a copy of the GNU General Public License
        !            18:  *  along with this program; if not, write to the Free Software
        !            19:  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            20:  */
        !            21: #include <fcntl.h>
        !            22: #include <stdio.h>
        !            23: #include <stdlib.h>
        !            24: #include <errno.h>
        !            25: 
        !            26: #include <mach/host_info.h>
        !            27: #include <mach/mach.h>
        !            28: #include <mach/mach_time.h>
        !            29: #include <mach/message.h>
        !            30: 
        !            31: #include <pthread.h>
        !            32: #include <dirent.h>
        !            33: 
        !            34: #include <sys/stat.h>
        !            35: #include <sys/syscall.h>
        !            36: #include <sys/sysctl.h>
        !            37: #include <sys/types.h>
        !            38: #include <unistd.h>
        !            39: #include <sys/ioctl.h>
        !            40: #include <sys/mman.h>
        !            41: #include <sys/types.h>
        !            42: #include <sys/dirent.h>
        !            43: #include <sys/uio.h>
        !            44: #include <sys/termios.h>
        !            45: #include <sys/ptrace.h>
        !            46: #include <net/if.h>
        !            47: 
        !            48: #include <sys/param.h>
        !            49: #include <sys/mount.h>
        !            50: 
        !            51: #include <sys/attr.h>
        !            52: 
        !            53: #include <mach/ndr.h>
        !            54: #include <mach/mig_errors.h>
        !            55: 
        !            56: #include "qemu.h"
        !            57: 
        !            58: //#define DEBUG_SYSCALL
        !            59: 
        !            60: #ifdef DEBUG_SYSCALL
        !            61: # define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
        !            62: # define DEBUG_BEGIN_ENABLE  __DEBUG_qemu_user_force_enable = 1;
        !            63: # define DEBUG_END_ENABLE  __DEBUG_qemu_user_force_enable = 0;
        !            64: 
        !            65: # define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
        !            66: # define DEBUG_ENABLE_ALL()  static int __DEBUG_qemu_user_force_enable = 1
        !            67:     DEBUG_ENABLE_ALL();
        !            68: 
        !            69: # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); \
        !            70:                            if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
        !            71:                          } while(0)
        !            72: #else
        !            73: # define DEBUG_FORCE_ENABLE_LOCAL()
        !            74: # define DEBUG_BEGIN_ENABLE
        !            75: # define DEBUG_END_ENABLE
        !            76: 
        !            77: # define DPRINTF(...) do { if(loglevel) fprintf(logfile, __VA_ARGS__); } while(0)
        !            78: #endif
        !            79: 
        !            80: enum {
        !            81:     bswap_out = 0,
        !            82:     bswap_in = 1
        !            83: };
        !            84: 
        !            85: extern const char *interp_prefix;
        !            86: 
        !            87: static inline long get_errno(long ret)
        !            88: {
        !            89:     if (ret == -1)
        !            90:         return -errno;
        !            91:     else
        !            92:         return ret;
        !            93: }
        !            94: 
        !            95: static inline int is_error(long ret)
        !            96: {
        !            97:     return (unsigned long)ret >= (unsigned long)(-4096);
        !            98: }
        !            99: 
        !           100: /* ------------------------------------------------------------
        !           101:    Mach syscall handling
        !           102: */
        !           103: 
        !           104: void static inline print_description_msg_header(mach_msg_header_t *hdr)
        !           105: {
        !           106:     char *name = NULL;
        !           107:     int i;
        !           108:     struct { int number; char *name; } msg_name[] =
        !           109:     {
        !           110:         /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */
        !           111:         { 200,      "host_info" },
        !           112:         { 202,      "host_page_size" },
        !           113:         { 206,      "host_get_clock_service" },
        !           114:         { 206,      "host_get_clock_service" },
        !           115:         { 206,      "host_get_clock_service" },
        !           116:         { 306,      "host_get_clock_service" },
        !           117:         { 3204,     "mach_port_allocate" },
        !           118:         { 3206,     "mach_port_deallocate" },
        !           119:         { 3404,     "mach_ports_lookup" },
        !           120:         { 3409,     "mach_task_get_special_port" },
        !           121:         { 3414,     "mach_task_get_exception_ports" },
        !           122:         { 3418,     "mach_semaphore_create" },
        !           123:         { 3504,     "mach_semaphore_create" },
        !           124:         { 3509,     "mach_semaphore_create" },
        !           125:         { 3518,     "semaphore_create" },
        !           126:         { 3616,     "thread_policy" },
        !           127:         { 3801,     "vm_allocate" },
        !           128:         { 3802,     "vm_deallocate" },
        !           129:         { 3802,     "vm_deallocate" },
        !           130:         { 3803,     "vm_protect" },
        !           131:         { 3812,     "vm_map" },
        !           132:         { 4241776,  "lu_message_send_id" },  /* lookupd */
        !           133:         { 4241876,  "lu_message_reply_id" }, /* lookupd */
        !           134:     };
        !           135: 
        !           136:     for(i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
        !           137:         if(msg_name[i].number == hdr->msgh_id)
        !           138:         {
        !           139:             name = msg_name[i].name;
        !           140:             break;
        !           141:         }
        !           142:     }
        !           143:     if(!name)
        !           144:         DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
        !           145:     else
        !           146:         DPRINTF("%s\n", name);
        !           147: #if 0
        !           148:     DPRINTF("Bits: %8x\n", hdr->msgh_bits);
        !           149:     DPRINTF("Size: %8x\n", hdr->msgh_size);
        !           150:     DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
        !           151:     DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
        !           152:     DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
        !           153: 
        !           154:     DPRINTF("Id  : %8x\n", hdr->msgh_id);
        !           155: 
        !           156:     NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
        !           157:     DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
        !           158:     DPRINTF("%d %d %d %d %d %d %d %d\n",
        !           159:            ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
        !           160:            ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
        !           161: #endif
        !           162: }
        !           163: 
        !           164: static inline void print_mach_msg_return(mach_msg_return_t ret)
        !           165: {
        !           166:     int i, found = 0;
        !           167: #define MACH_MSG_RET(msg) { msg, #msg }
        !           168:     struct { int code; char *name; } msg_name[] =
        !           169:     {
        !           170:         /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
        !           171:         /* send message */
        !           172:         MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
        !           173:         MACH_MSG_RET(MACH_SEND_NO_BUFFER),
        !           174:         MACH_MSG_RET(MACH_SEND_INVALID_DATA),
        !           175:         MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
        !           176:         MACH_MSG_RET(MACH_SEND_INVALID_DEST),
        !           177:         MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
        !           178:         MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
        !           179:         MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
        !           180:         MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
        !           181:         MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
        !           182:         MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
        !           183:         MACH_MSG_RET(MACH_SEND_INTERRUPTED),
        !           184:         MACH_MSG_RET(MACH_SEND_TIMED_OUT),
        !           185: 
        !           186:         MACH_MSG_RET(MACH_RCV_BODY_ERROR),
        !           187:         MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
        !           188: 
        !           189:         MACH_MSG_RET(MACH_RCV_IN_SET),
        !           190:         MACH_MSG_RET(MACH_RCV_INTERRUPTED),
        !           191: 
        !           192:         MACH_MSG_RET(MACH_RCV_INVALID_DATA),
        !           193:         MACH_MSG_RET(MACH_RCV_INVALID_NAME),
        !           194:         MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
        !           195:         MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
        !           196:         MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
        !           197: 
        !           198:         MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
        !           199:         MACH_MSG_RET(MACH_RCV_PORT_DIED),
        !           200: 
        !           201:         MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
        !           202:         MACH_MSG_RET(MACH_RCV_TIMED_OUT),
        !           203:         MACH_MSG_RET(MACH_RCV_TOO_LARGE)
        !           204:     };
        !           205: #undef MACH_MSG_RET
        !           206: 
        !           207:     if( ret == MACH_MSG_SUCCESS)
        !           208:         DPRINTF("MACH_MSG_SUCCESS\n");
        !           209:     else
        !           210:     {
        !           211:         for( i = 0; i < sizeof(msg_name)/sizeof(msg_name[0]); i++) {
        !           212:             if(msg_name[i].code == ret) {
        !           213:                 DPRINTF("%s\n", msg_name[i].name);
        !           214:                 found = 1;
        !           215:                 break;
        !           216:             }
        !           217:         }
        !           218:         if(!found)
        !           219:             qerror("unknow mach message ret code %d\n", ret);
        !           220:     }
        !           221: }
        !           222: 
        !           223: static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
        !           224: {
        !           225:     hdr->msgh_bits = tswap32(hdr->msgh_bits);
        !           226:     hdr->msgh_size = tswap32(hdr->msgh_size);
        !           227:     hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
        !           228:     hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
        !           229:     hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
        !           230:     hdr->msgh_id = tswap32(hdr->msgh_id);
        !           231: }
        !           232: 
        !           233: struct complex_msg {
        !           234:             mach_msg_header_t hdr;
        !           235:             mach_msg_body_t body;
        !           236: };
        !           237: 
        !           238: static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
        !           239: {
        !           240:     mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
        !           241:     int i,j;
        !           242: 
        !           243:     if(bswap == bswap_in)
        !           244:         tswap32s(&complex_msg->body.msgh_descriptor_count);
        !           245: 
        !           246:     DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
        !           247: 
        !           248:     for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
        !           249:         switch(descr->type)
        !           250:         {
        !           251:             case MACH_MSG_PORT_DESCRIPTOR:
        !           252:                 tswap32s(&descr->name);
        !           253:                 descr++;
        !           254:                 break;
        !           255:             case MACH_MSG_OOL_DESCRIPTOR:
        !           256:             {
        !           257:                 mach_msg_ool_descriptor_t *ool = (void *)descr;
        !           258:                 tswap32s((uint32_t *)&ool->address);
        !           259:                 tswap32s(&ool->size);
        !           260: 
        !           261:                 descr = (mach_msg_port_descriptor_t *)(ool+1);
        !           262:                 break;
        !           263:             }
        !           264:             case MACH_MSG_OOL_PORTS_DESCRIPTOR:
        !           265:             {
        !           266:                 mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
        !           267:                 mach_port_name_t * port_names;
        !           268: 
        !           269:                 if(bswap == bswap_in)
        !           270:                 {
        !           271:                     tswap32s((uint32_t *)&ool_ports->address);
        !           272:                     tswap32s(&ool_ports->count);
        !           273:                 }
        !           274: 
        !           275:                 port_names = ool_ports->address;
        !           276: 
        !           277:                 for(j = 0; j < ool_ports->count; j++)
        !           278:                     tswap32s(&port_names[j]);
        !           279: 
        !           280:                 if(bswap == bswap_out)
        !           281:                 {
        !           282:                     tswap32s((uint32_t *)&ool_ports->address);
        !           283:                     tswap32s(&ool_ports->count);
        !           284:                 }
        !           285: 
        !           286:                 descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
        !           287:                 break;
        !           288:             }
        !           289:             default: qerror("unknow mach msg descriptor type %x\n", descr->type);
        !           290:         }
        !           291:     }
        !           292:     if(bswap == bswap_out)
        !           293:         tswap32s(&complex_msg->body.msgh_descriptor_count);
        !           294: }
        !           295: 
        !           296: static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap)
        !           297: {
        !           298:     if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
        !           299:         swap_mach_msg_body((struct complex_msg *)hdr, bswap);
        !           300: 
        !           301:     swap_mach_msg_header(hdr);
        !           302: 
        !           303:     if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
        !           304:         swap_mach_msg_body((struct complex_msg *)hdr, bswap);
        !           305: }
        !           306: 
        !           307: static inline uint32_t target_mach_msg_trap(
        !           308:         mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
        !           309:         uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify)
        !           310: {
        !           311:     extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t,
        !           312:           mach_msg_size_t, mach_msg_size_t, mach_port_t,
        !           313:           mach_msg_timeout_t, mach_port_t);
        !           314:     mach_msg_audit_trailer_t *trailer;
        !           315:     mach_msg_id_t msg_id;
        !           316:     uint32_t ret = 0;
        !           317:     int i;
        !           318: 
        !           319:     swap_mach_msg(hdr, bswap_in);
        !           320: 
        !           321:     msg_id = hdr->msgh_id;
        !           322: 
        !           323:     print_description_msg_header(hdr);
        !           324: 
        !           325:     ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
        !           326: 
        !           327:     print_mach_msg_return(ret);
        !           328: 
        !           329:     if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
        !           330:     {
        !           331:         /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should
        !           332:                 probably always bswap it  */
        !           333:         /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in
        !           334:                     natural_t units but according to xnu/osfmk/mach/message.h: "The size of
        !           335:                     the message must be specified in bytes" */
        !           336:         trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
        !           337:         /* XXX: Should probably do that based on the option asked by the sender, but dealing
        !           338:         with kernel answer seems more sound */
        !           339:         switch(trailer->msgh_trailer_size)
        !           340:         {
        !           341:             case sizeof(mach_msg_audit_trailer_t):
        !           342:                 for(i = 0; i < 8; i++)
        !           343:                     tswap32s(&trailer->msgh_audit.val[i]);
        !           344:                 /* Fall in mach_msg_security_trailer_t case */
        !           345:             case sizeof(mach_msg_security_trailer_t):
        !           346:                 tswap32s(&trailer->msgh_sender.val[0]);
        !           347:                 tswap32s(&trailer->msgh_sender.val[1]);
        !           348:                 /* Fall in mach_msg_seqno_trailer_t case */
        !           349:             case sizeof(mach_msg_seqno_trailer_t):
        !           350:                 tswap32s(&trailer->msgh_seqno);
        !           351:                 /* Fall in mach_msg_trailer_t case */
        !           352:             case sizeof(mach_msg_trailer_t):
        !           353:                 tswap32s(&trailer->msgh_trailer_type);
        !           354:                 tswap32s(&trailer->msgh_trailer_size);
        !           355:                 break;
        !           356:             case 0:
        !           357:                 /* Safer not to byteswap, but probably wrong */
        !           358:                 break;
        !           359:             default:
        !           360:                 qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
        !           361:                 break;
        !           362:         }
        !           363:     }
        !           364: 
        !           365:     /* Special message handling */
        !           366:     switch (msg_id) {
        !           367:         case 200: /* host_info */
        !           368:         {
        !           369:             mig_reply_error_t *err = (mig_reply_error_t *)hdr;
        !           370:             struct host_basic_info *data = (void *)(err+1);
        !           371: 
        !           372:             DPRINTF("maxcpu = 0x%x\n",   data->max_cpus);
        !           373:             DPRINTF("numcpu = 0x%x\n",   data->avail_cpus);
        !           374:             DPRINTF("memsize = 0x%x\n",  data->memory_size);
        !           375: 
        !           376: #if defined(TARGET_I386)
        !           377:             data->cpu_type = CPU_TYPE_I386;
        !           378:             DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
        !           379:             data->cpu_subtype = CPU_SUBTYPE_PENT;
        !           380:             DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
        !           381: #elif defined(TARGET_PPC)
        !           382:             data->cpu_type = CPU_TYPE_POWERPC;
        !           383:             DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
        !           384:             data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
        !           385:             DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
        !           386: #else
        !           387: # error target not supported
        !           388: #endif
        !           389:             break;
        !           390:         }
        !           391:         case 202: /* host_page_size */
        !           392:         {
        !           393:             mig_reply_error_t *err = (mig_reply_error_t *)hdr;
        !           394:             uint32_t *pagesize = (uint32_t *)(err+1);
        !           395: 
        !           396:             DPRINTF("pagesize = %d\n", *pagesize);
        !           397:             break;
        !           398:         }
        !           399:         default: break;
        !           400:     }
        !           401: 
        !           402:     swap_mach_msg(hdr, bswap_out);
        !           403: 
        !           404:     return ret;
        !           405: }
        !           406: 
        !           407: long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
        !           408:                 uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
        !           409:                 uint32_t arg8)
        !           410: {
        !           411:     extern uint32_t mach_reply_port();
        !           412: 
        !           413:     long ret = 0;
        !           414: 
        !           415:     arg1 = tswap32(arg1);
        !           416:     arg2 = tswap32(arg2);
        !           417:     arg3 = tswap32(arg3);
        !           418:     arg4 = tswap32(arg4);
        !           419:     arg5 = tswap32(arg5);
        !           420:     arg6 = tswap32(arg6);
        !           421:     arg7 = tswap32(arg7);
        !           422:     arg8 = tswap32(arg8);
        !           423: 
        !           424:     DPRINTF("mach syscall %d : " , num);
        !           425: 
        !           426:     switch(num) {
        !           427:     /* see xnu/osfmk/mach/syscall_sw.h */
        !           428:     case -26:
        !           429:         DPRINTF("mach_reply_port()\n");
        !           430:         ret = mach_reply_port();
        !           431:         break;
        !           432:     case -27:
        !           433:         DPRINTF("mach_thread_self()\n");
        !           434:         ret = mach_thread_self();
        !           435:         break;
        !           436:     case -28:
        !           437:         DPRINTF("mach_task_self()\n");
        !           438:         ret = mach_task_self();
        !           439:         break;
        !           440:     case -29:
        !           441:         DPRINTF("mach_host_self()\n");
        !           442:         ret = mach_host_self();
        !           443:         break;
        !           444:     case -31:
        !           445:         DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
        !           446:                 arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        !           447: 
        !           448:         ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        !           449: 
        !           450:         break;
        !           451:     case -36:
        !           452:         DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
        !           453:         extern int semaphore_wait_trap(int); // XXX: is there any header for that?
        !           454:         ret = semaphore_wait_trap(arg1);
        !           455:         break;
        !           456:     case -43:
        !           457:         DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
        !           458:                 arg1, arg2, arg3, arg4, arg5);
        !           459:         ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
        !           460:         tswap32s((uint32_t*)arg3);
        !           461:         break;
        !           462:     case -89:
        !           463:         DPRINTF("mach_timebase_info(0x%x)\n", arg1);
        !           464:         struct mach_timebase_info info;
        !           465:         ret = mach_timebase_info(&info);
        !           466:         if(!is_error(ret))
        !           467:         {
        !           468:             struct mach_timebase_info *outInfo = (void*)arg1;
        !           469:             outInfo->numer = tswap32(info.numer);
        !           470:             outInfo->denom = tswap32(info.denom);
        !           471:         }
        !           472:         break;
        !           473:     case -90:
        !           474:         DPRINTF("mach_wait_until()\n");
        !           475:         extern int mach_wait_until(uint64_t); // XXX: is there any header for that?
        !           476:         ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
        !           477:         break;
        !           478:     case -91:
        !           479:         DPRINTF("mk_timer_create()\n");
        !           480:         extern int mk_timer_create(); // XXX: is there any header for that?
        !           481:         ret = mk_timer_create();
        !           482:         break;
        !           483:     case -92:
        !           484:         DPRINTF("mk_timer_destroy()\n");
        !           485:         extern int mk_timer_destroy(int); // XXX: is there any header for that?
        !           486:         ret = mk_timer_destroy(arg1);
        !           487:         break;
        !           488:     case -93:
        !           489:         DPRINTF("mk_timer_create()\n");
        !           490:         extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that?
        !           491:         ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2);
        !           492:         break;
        !           493:     case -94:
        !           494:         DPRINTF("mk_timer_cancel()\n");
        !           495:         extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that?
        !           496:         ret = mk_timer_cancel(arg1, (uint64_t *)arg2);
        !           497:         if((!is_error(ret)) && arg2)
        !           498:             tswap64s((uint64_t *)arg2);
        !           499:         break;
        !           500:     default:
        !           501:         gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num);
        !           502:         gdb_handlesig (cpu_env, SIGTRAP);
        !           503:         exit(0);
        !           504:         break;
        !           505:     }
        !           506:     return ret;
        !           507: }
        !           508: 
        !           509: /* ------------------------------------------------------------
        !           510:    thread type syscall handling
        !           511: */
        !           512: long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
        !           513:                 uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
        !           514:                 uint32_t arg8)
        !           515: {
        !           516:     extern uint32_t cthread_set_self(uint32_t);
        !           517:     extern uint32_t processor_facilities_used();
        !           518:     long ret = 0;
        !           519: 
        !           520:     arg1 = tswap32(arg1);
        !           521:     arg2 = tswap32(arg2);
        !           522:     arg3 = tswap32(arg3);
        !           523:     arg4 = tswap32(arg4);
        !           524:     arg5 = tswap32(arg5);
        !           525:     arg6 = tswap32(arg6);
        !           526:     arg7 = tswap32(arg7);
        !           527:     arg8 = tswap32(arg8);
        !           528: 
        !           529:     DPRINTF("thread syscall %d : " , num);
        !           530: 
        !           531:     switch(num) {
        !           532: #ifdef TARGET_I386
        !           533:     case 0x3:
        !           534: #endif
        !           535:     case 0x7FF1: /* cthread_set_self */
        !           536:         DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1);
        !           537:         ret = cthread_set_self(arg1);
        !           538: #ifdef TARGET_I386
        !           539:         /* we need to update the LDT with the address of the thread */
        !           540:         write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1,
        !           541:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
        !           542:                  (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
        !           543:         /* New i386 convention, %gs should be set to our this LDT entry */
        !           544:         cpu_x86_load_seg(cpu_env, R_GS, 0x27);
        !           545:         /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/
        !           546:         ret = 0x27;
        !           547: #endif
        !           548:         break;
        !           549:     case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */
        !           550:         DPRINTF("pthread_self()\n");
        !           551:         ret = (uint32_t)pthread_self();
        !           552:         break;
        !           553:     case 0x7FF3:
        !           554:         DPRINTF("processor_facilities_used()\n");
        !           555: #ifdef __i386__
        !           556:         qerror("processor_facilities_used: not implemented!\n");
        !           557: #else
        !           558:         ret = (uint32_t)processor_facilities_used();
        !           559: #endif
        !           560:         break;
        !           561:     default:
        !           562:         gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num);
        !           563:         gdb_handlesig (cpu_env, SIGTRAP);
        !           564:         exit(0);
        !           565:         break;
        !           566:     }
        !           567:     return ret;
        !           568: }
        !           569: 
        !           570: /* ------------------------------------------------------------
        !           571:    ioctl handling
        !           572: */
        !           573: static inline void byteswap_termios(struct termios *t)
        !           574: {
        !           575:     tswap32s((uint32_t*)&t->c_iflag);
        !           576:     tswap32s((uint32_t*)&t->c_oflag);
        !           577:     tswap32s((uint32_t*)&t->c_cflag);
        !           578:     tswap32s((uint32_t*)&t->c_lflag);
        !           579:     /* 20 (char) bytes then */
        !           580:     tswap32s((uint32_t*)&t->c_ispeed);
        !           581:     tswap32s((uint32_t*)&t->c_ospeed);
        !           582: }
        !           583: 
        !           584: static inline void byteswap_winsize(struct winsize *w)
        !           585: {
        !           586:     tswap16s(&w->ws_row);
        !           587:     tswap16s(&w->ws_col);
        !           588:     tswap16s(&w->ws_xpixel);
        !           589:     tswap16s(&w->ws_ypixel);
        !           590: }
        !           591: 
        !           592: #define STRUCT(name, list...) STRUCT_ ## name,
        !           593: #define STRUCT_SPECIAL(name) STRUCT_ ## name,
        !           594: enum {
        !           595: #include "ioctls_types.h"
        !           596: };
        !           597: #undef STRUCT
        !           598: #undef STRUCT_SPECIAL
        !           599: 
        !           600: #define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
        !           601: #define STRUCT_SPECIAL(name)
        !           602: #include "ioctls_types.h"
        !           603: #undef STRUCT
        !           604: #undef STRUCT_SPECIAL
        !           605: 
        !           606: typedef struct IOCTLEntry {
        !           607:     unsigned int target_cmd;
        !           608:     unsigned int host_cmd;
        !           609:     const char *name;
        !           610:     int access;
        !           611:     const argtype arg_type[5];
        !           612: } IOCTLEntry;
        !           613: 
        !           614: #define IOC_R 0x0001
        !           615: #define IOC_W 0x0002
        !           616: #define IOC_RW (IOC_R | IOC_W)
        !           617: 
        !           618: #define MAX_STRUCT_SIZE 4096
        !           619: 
        !           620: IOCTLEntry ioctl_entries[] = {
        !           621: #define IOCTL(cmd, access, types...) \
        !           622:     { cmd, cmd, #cmd, access, { types } },
        !           623: #include "ioctls.h"
        !           624:     { 0, 0, },
        !           625: };
        !           626: 
        !           627: /* ??? Implement proper locking for ioctls.  */
        !           628: static long do_ioctl(long fd, long cmd, long arg)
        !           629: {
        !           630:     const IOCTLEntry *ie;
        !           631:     const argtype *arg_type;
        !           632:     int ret;
        !           633:     uint8_t buf_temp[MAX_STRUCT_SIZE];
        !           634:     int target_size;
        !           635:     void *argptr;
        !           636: 
        !           637:     ie = ioctl_entries;
        !           638:     for(;;) {
        !           639:         if (ie->target_cmd == 0) {
        !           640:             gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
        !           641:             return -ENOSYS;
        !           642:         }
        !           643:         if (ie->target_cmd == cmd)
        !           644:             break;
        !           645:         ie++;
        !           646:     }
        !           647:     arg_type = ie->arg_type;
        !           648: #if defined(DEBUG)
        !           649:     gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
        !           650: #endif
        !           651:     switch(arg_type[0]) {
        !           652:     case TYPE_NULL:
        !           653:         /* no argument */
        !           654:         ret = get_errno(ioctl(fd, ie->host_cmd));
        !           655:         break;
        !           656:     case TYPE_PTRVOID:
        !           657:     case TYPE_INT:
        !           658:         /* int argment */
        !           659:         ret = get_errno(ioctl(fd, ie->host_cmd, arg));
        !           660:         break;
        !           661:     case TYPE_PTR:
        !           662:         arg_type++;
        !           663:         target_size = thunk_type_size(arg_type, 0);
        !           664:         switch(ie->access) {
        !           665:         case IOC_R:
        !           666:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
        !           667:             if (!is_error(ret)) {
        !           668:                 argptr = lock_user(arg, target_size, 0);
        !           669:                 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
        !           670:                 unlock_user(argptr, arg, target_size);
        !           671:             }
        !           672:             break;
        !           673:         case IOC_W:
        !           674:             argptr = lock_user(arg, target_size, 1);
        !           675:             thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
        !           676:             unlock_user(argptr, arg, 0);
        !           677:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
        !           678:             break;
        !           679:         default:
        !           680:         case IOC_RW:
        !           681:             argptr = lock_user(arg, target_size, 1);
        !           682:             thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
        !           683:             unlock_user(argptr, arg, 0);
        !           684:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
        !           685:             if (!is_error(ret)) {
        !           686:                 argptr = lock_user(arg, target_size, 0);
        !           687:                 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
        !           688:                 unlock_user(argptr, arg, target_size);
        !           689:             }
        !           690:             break;
        !           691:         }
        !           692:         break;
        !           693:     default:
        !           694:         gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
        !           695:         ret = -ENOSYS;
        !           696:         break;
        !           697:     }
        !           698:     return ret;
        !           699: }
        !           700: 
        !           701: /* ------------------------------------------------------------
        !           702:    Unix syscall handling
        !           703: */
        !           704: 
        !           705: static inline void byteswap_attrlist(struct attrlist *a)
        !           706: {
        !           707:     tswap16s(&a->bitmapcount);
        !           708:     tswap16s(&a->reserved);
        !           709:     tswap32s(&a->commonattr);
        !           710:     tswap32s(&a->volattr);
        !           711:     tswap32s(&a->dirattr);
        !           712:     tswap32s(&a->fileattr);
        !           713:     tswap32s(&a->forkattr);
        !           714: }
        !           715: 
        !           716: struct attrbuf_header {
        !           717:     unsigned long length;
        !           718: };
        !           719: 
        !           720: static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
        !           721: {
        !           722:     DPRINTF("attrBuf.lenght %lx\n", attrbuf->length);
        !           723: }
        !           724: 
        !           725: static inline void byteswap_statfs(struct statfs *s)
        !           726: {
        !           727:     tswap16s((uint16_t*)&s->f_otype);
        !           728:     tswap16s((uint16_t*)&s->f_oflags);
        !           729:     tswap32s((uint32_t*)&s->f_bsize);
        !           730:     tswap32s((uint32_t*)&s->f_iosize);
        !           731:     tswap32s((uint32_t*)&s->f_blocks);
        !           732:     tswap32s((uint32_t*)&s->f_bfree);
        !           733:     tswap32s((uint32_t*)&s->f_bavail);
        !           734:     tswap32s((uint32_t*)&s->f_files);
        !           735:     tswap32s((uint32_t*)&s->f_ffree);
        !           736:     tswap32s((uint32_t*)&s->f_fsid.val[0]);
        !           737:     tswap32s((uint32_t*)&s->f_fsid.val[1]);
        !           738:     tswap16s((uint16_t*)&s->f_reserved1);
        !           739:     tswap16s((uint16_t*)&s->f_type);
        !           740:     tswap32s((uint32_t*)&s->f_flags);
        !           741: }
        !           742: 
        !           743: static inline void byteswap_stat(struct stat *s)
        !           744: {
        !           745:     tswap32s((uint32_t*)&s->st_dev);
        !           746:     tswap32s(&s->st_ino);
        !           747:     tswap16s(&s->st_mode);
        !           748:     tswap16s(&s->st_nlink);
        !           749:     tswap32s(&s->st_uid);
        !           750:     tswap32s(&s->st_gid);
        !           751:     tswap32s((uint32_t*)&s->st_rdev);
        !           752:     tswap32s((uint32_t*)&s->st_atimespec.tv_sec);
        !           753:     tswap32s((uint32_t*)&s->st_atimespec.tv_nsec);
        !           754:     tswap32s((uint32_t*)&s->st_mtimespec.tv_sec);
        !           755:     tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec);
        !           756:     tswap32s((uint32_t*)&s->st_ctimespec.tv_sec);
        !           757:     tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec);
        !           758:     tswap64s((uint64_t*)&s->st_size);
        !           759:     tswap64s((uint64_t*)&s->st_blocks);
        !           760:     tswap32s((uint32_t*)&s->st_blksize);
        !           761:     tswap32s(&s->st_flags);
        !           762:     tswap32s(&s->st_gen);
        !           763: }
        !           764: 
        !           765: static inline void byteswap_dirents(struct dirent *d, int bytes)
        !           766: {
        !           767:     char *b;
        !           768:     for( b = (char*)d; (int)b < (int)d+bytes; )
        !           769:     {
        !           770:         unsigned short s = ((struct dirent *)b)->d_reclen;
        !           771:         tswap32s(&((struct dirent *)b)->d_ino);
        !           772:         tswap16s(&((struct dirent *)b)->d_reclen);
        !           773:         if(s<=0)
        !           774:             break;
        !           775:         b += s;
        !           776:     }
        !           777: }
        !           778: 
        !           779: static inline void byteswap_iovec(struct iovec *v, int n)
        !           780: {
        !           781:     int i;
        !           782:     for(i = 0; i < n; i++)
        !           783:     {
        !           784:         tswap32s((uint32_t*)&v[i].iov_base);
        !           785:         tswap32s((uint32_t*)&v[i].iov_len);
        !           786:     }
        !           787: }
        !           788: 
        !           789: static inline void byteswap_timeval(struct timeval *t)
        !           790: {
        !           791:     tswap32s((uint32_t*)&t->tv_sec);
        !           792:     tswap32s((uint32_t*)&t->tv_usec);
        !           793: }
        !           794: 
        !           795: long do_unix_syscall_indirect(void *cpu_env, int num);
        !           796: long do_sync();
        !           797: long do_exit(uint32_t arg1);
        !           798: long do_getlogin(char *out, uint32_t size);
        !           799: long do_open(char * arg1, uint32_t arg2, uint32_t arg3);
        !           800: long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3);
        !           801: long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3);
        !           802: long do_execve(char* arg1, char ** arg2, char ** arg3);
        !           803: long do_getgroups(uint32_t arg1, gid_t * arg2);
        !           804: long do_gettimeofday(struct timeval * arg1, void * arg2);
        !           805: long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
        !           806: long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
        !           807: long do_utimes(char * arg1, struct timeval * arg2);
        !           808: long do_futimes(uint32_t arg1, struct timeval * arg2);
        !           809: long do_statfs(char * arg1, struct statfs * arg2);
        !           810: long do_fstatfs(uint32_t arg1, struct statfs * arg2);
        !           811: long do_stat(char * arg1, struct stat * arg2);
        !           812: long do_fstat(uint32_t arg1, struct stat * arg2);
        !           813: long do_lstat(char * arg1, struct stat * arg2);
        !           814: long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4);
        !           815: long do_lseek(void *cpu_env, int num);
        !           816: long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */);
        !           817: long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5);
        !           818: long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8);
        !           819: long do_fcntl(int fd, int cmd, int arg);
        !           820: 
        !           821: long no_syscall(void *cpu_env, int num);
        !           822: 
        !           823: long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
        !           824: {
        !           825:     DPRINTF("0x%x, %p, 0x%lx, 0x%llx\n", arg1, arg2, arg3, arg4);
        !           826:     long ret = pread(arg1, arg2, arg3, arg4);
        !           827:     return ret;
        !           828: }
        !           829: 
        !           830: long do_read(int d, void *buf, size_t nbytes)
        !           831: {
        !           832:     DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes);
        !           833:     long ret = get_errno(read(d, buf, nbytes));
        !           834:     if(!is_error(ret))
        !           835:         DPRINTF("%x\n", *(uint32_t*)buf);
        !           836:     return ret;
        !           837: }
        !           838: 
        !           839: long unimpl_unix_syscall(void *cpu_env, int num);
        !           840: 
        !           841: typedef long (*syscall_function_t)(void *cpu_env, int num);
        !           842: 
        !           843: 
        !           844: /* define a table that will handle the syscall number->function association */
        !           845: #define VOID    void
        !           846: #define INT     (uint32_t)get_int_arg(&i, cpu_env)
        !           847: #define INT64   (uint64_t)get_int64_arg(&i, cpu_env)
        !           848: #define UINT    (unsigned int)INT
        !           849: #define PTR     (void*)INT
        !           850: 
        !           851: #define SIZE    INT
        !           852: #define OFFSET  INT64
        !           853: 
        !           854: #define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) {  return (long)function(); }
        !           855: #define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1;  return (long)function(arg1); }
        !           856: #define WRAPPER_CALL_DIRECT_2(function, _arg1, _arg2) long __qemu_##function(void *cpu_env) { int i = 0;  typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; return (long)function(arg1, arg2); }
        !           857: #define WRAPPER_CALL_DIRECT_3(function, _arg1, _arg2, _arg3) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; return (long)function(arg1, arg2, arg3); }
        !           858: #define WRAPPER_CALL_DIRECT_4(function, _arg1, _arg2, _arg3, _arg4) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; return (long)function(arg1, arg2, arg3, arg4); }
        !           859: #define WRAPPER_CALL_DIRECT_5(function, _arg1, _arg2, _arg3, _arg4, _arg5) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5;  return (long)function(arg1, arg2, arg3, arg4, arg5); }
        !           860: #define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); }
        !           861: #define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
        !           862: #define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
        !           863: #define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
        !           864: #define WRAPPER_CALL_NOERRNO(function, nargs, args...)  WRAPPER_CALL_DIRECT(function, nargs, args)
        !           865: #define WRAPPER_CALL_INDIRECT(function, nargs, args...)
        !           866: #define ENTRY(name, number, function, nargs, call_type, args...)  WRAPPER_##call_type(function, nargs, args)
        !           867: 
        !           868: #include "syscalls.h"
        !           869: 
        !           870: #undef ENTRY
        !           871: #undef WRAPPER_CALL_DIRECT
        !           872: #undef WRAPPER_CALL_NOERRNO
        !           873: #undef WRAPPER_CALL_INDIRECT
        !           874: #undef OFFSET
        !           875: #undef SIZE
        !           876: #undef INT
        !           877: #undef PTR
        !           878: #undef INT64
        !           879: 
        !           880: #define _ENTRY(name, number, function, nargs, call_type) [number] = {\
        !           881:         name, \
        !           882:         number, \
        !           883:         (syscall_function_t)function, \
        !           884:         nargs, \
        !           885:         call_type  \
        !           886:         },
        !           887: 
        !           888: #define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)  _ENTRY(name, number, __qemu_##function, nargs, call_type)
        !           889: #define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
        !           890: #define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
        !           891: #define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type)
        !           892: 
        !           893: #define CALL_DIRECT 1
        !           894: #define CALL_INDIRECT 2
        !           895: #define CALL_NOERRNO  (CALL_DIRECT | 4 /* = 5 */)
        !           896: 
        !           897: struct unix_syscall {
        !           898:     char * name;
        !           899:     int number;
        !           900:     syscall_function_t function;
        !           901:     int nargs;
        !           902:     int call_type;
        !           903: } unix_syscall_table[SYS_MAXSYSCALL] = {
        !           904: #include "syscalls.h"
        !           905: };
        !           906: 
        !           907: #undef ENTRY
        !           908: #undef _ENTRY
        !           909: #undef ENTRY_CALL_DIRECT
        !           910: #undef ENTRY_CALL_INDIRECT
        !           911: #undef ENTRY_CALL_NOERRNO
        !           912: 
        !           913: /* Actual syscalls implementation */
        !           914: 
        !           915: long do_unix_syscall_indirect(void *cpu_env, int num)
        !           916: {
        !           917:     long ret;
        !           918:     int new_num;
        !           919:     int i = 0;
        !           920: 
        !           921:     new_num = get_int_arg(&i, cpu_env);
        !           922: #ifdef TARGET_I386
        !           923:     ((CPUX86State*)cpu_env)->regs[R_ESP] += 4;
        !           924:     /* XXX: not necessary */
        !           925:     ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num;
        !           926: #elif TARGET_PPC
        !           927:     {
        !           928:         int i;
        !           929:         uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
        !           930:         for(i = 3; i < 11; i++)
        !           931:             *regs[i] = *regs[i+1];
        !           932:         /* XXX: not necessary */
        !           933:         *regs[0] = new_num;
        !           934:     }
        !           935: #endif
        !           936:     ret = do_unix_syscall(cpu_env, new_num);
        !           937: #ifdef TARGET_I386
        !           938:     ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4;
        !           939:     /* XXX: not necessary */
        !           940:     ((CPUX86State*)cpu_env)->regs[R_EAX] = num;
        !           941: #elif TARGET_PPC
        !           942:     {
        !           943:         int i;
        !           944:         /* XXX: not really needed those regs are volatile accross calls */
        !           945:         uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
        !           946:         for(i = 11; i > 3; i--)
        !           947:             *regs[i] = *regs[i-1];
        !           948:         regs[3] = new_num;
        !           949:         *regs[0] = num;
        !           950:     }
        !           951: #endif
        !           952:     return ret;
        !           953: }
        !           954: 
        !           955: long do_exit(uint32_t arg1)
        !           956: {
        !           957:     exit(arg1);
        !           958:     /* not reached */
        !           959:     return -1;
        !           960: }
        !           961: 
        !           962: long do_sync()
        !           963: {
        !           964:     sync();
        !           965:     return 0;
        !           966: }
        !           967: 
        !           968: long do_getlogin(char *out, uint32_t size)
        !           969: {
        !           970:     char *login = getlogin();
        !           971:     if(!login)
        !           972:         return -1;
        !           973:     memcpy(out, login, size);
        !           974:     return 0;
        !           975: }
        !           976: long do_open(char * arg1, uint32_t arg2, uint32_t arg3)
        !           977: {
        !           978:     /* XXX: don't let the %s stay in there */
        !           979:     DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3);
        !           980:     return get_errno(open(arg1, arg2, arg3));
        !           981: }
        !           982: 
        !           983: long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3)
        !           984: {
        !           985:     long ret;
        !           986:     DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3);
        !           987:     ret = get_errno(getfsstat(arg1, arg2, arg3));
        !           988:     if((!is_error(ret)) && arg1)
        !           989:         byteswap_statfs(arg1);
        !           990:     return ret;
        !           991: }
        !           992: 
        !           993: long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3)
        !           994: {
        !           995:     long ret;
        !           996:     DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3);
        !           997:     gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3);
        !           998:     if(arg2)
        !           999:         tswap32s(arg2);
        !          1000:     ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3));
        !          1001:     if((!is_error(ret)) && arg3)
        !          1002:         tswap32s(arg3);
        !          1003:     if(arg2)
        !          1004:         tswap32s(arg2);
        !          1005:     return ret;
        !          1006: }
        !          1007: 
        !          1008: long do_execve(char* arg1, char ** arg2, char ** arg3)
        !          1009: {
        !          1010:     long ret;
        !          1011:     char **argv = arg2;
        !          1012:     char **envp = arg3;
        !          1013:     int argc;
        !          1014:     int envc;
        !          1015: 
        !          1016:     /* XXX: don't let the %s stay in here */
        !          1017:     DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3);
        !          1018: 
        !          1019:     for(argc = 0; argv[argc]; argc++);
        !          1020:     for(envc = 0; envp[envc]; envc++);
        !          1021: 
        !          1022:     argv = (char**)malloc(sizeof(char*)*argc);
        !          1023:     envp = (char**)malloc(sizeof(char*)*envc);
        !          1024: 
        !          1025:     for(; argc >= 0; argc--)
        !          1026:         argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]);
        !          1027: 
        !          1028:     for(; envc >= 0; envc--)
        !          1029:         envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]);
        !          1030: 
        !          1031:     ret = get_errno(execve(arg1, argv, envp));
        !          1032:     free(argv);
        !          1033:     free(envp);
        !          1034:     return ret;
        !          1035: }
        !          1036: 
        !          1037: long do_getgroups(uint32_t arg1, gid_t * arg2)
        !          1038: {
        !          1039:     long ret;
        !          1040:     int i;
        !          1041:     DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2);
        !          1042:     ret = get_errno(getgroups(arg1, arg2));
        !          1043:     if(ret > 0)
        !          1044:         for(i = 0; i < arg1; i++)
        !          1045:             tswap32s(&arg2[i]);
        !          1046:     return ret;
        !          1047: }
        !          1048: 
        !          1049: long do_gettimeofday(struct timeval * arg1, void * arg2)
        !          1050: {
        !          1051:     long ret;
        !          1052:     DPRINTF("gettimeofday(%p, %p)\n",
        !          1053:             arg1, arg2);
        !          1054:     ret = get_errno(gettimeofday(arg1, arg2));
        !          1055:     if(!is_error(ret))
        !          1056:     {
        !          1057:         /* timezone no longer used according to the manpage, so don't bother with it */
        !          1058:         byteswap_timeval(arg1);
        !          1059:     }
        !          1060:     return ret;
        !          1061: }
        !          1062: 
        !          1063: long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
        !          1064: {
        !          1065:     long ret;
        !          1066:     DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
        !          1067:     if(arg2)
        !          1068:         byteswap_iovec(arg2, arg3);
        !          1069:     ret = get_errno(readv(arg1, arg2, arg3));
        !          1070:     if((!is_error(ret)) && arg2)
        !          1071:         byteswap_iovec(arg2, arg3);
        !          1072:     return ret;
        !          1073: }
        !          1074: 
        !          1075: long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
        !          1076: {
        !          1077:     long ret;
        !          1078:     DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
        !          1079:     if(arg2)
        !          1080:         byteswap_iovec(arg2, arg3);
        !          1081:     ret = get_errno(writev(arg1, arg2, arg3));
        !          1082:     if((!is_error(ret)) && arg2)
        !          1083:         byteswap_iovec(arg2, arg3);
        !          1084:     return ret;
        !          1085: }
        !          1086: 
        !          1087: long do_utimes(char * arg1, struct timeval * arg2)
        !          1088: {
        !          1089:     DPRINTF("utimes(%p, %p)\n", arg1, arg2);
        !          1090:     if(arg2)
        !          1091:     {
        !          1092:         byteswap_timeval(arg2);
        !          1093:         byteswap_timeval(arg2+1);
        !          1094:     }
        !          1095:     return get_errno(utimes(arg1, arg2));
        !          1096: }
        !          1097: 
        !          1098: long do_futimes(uint32_t arg1, struct timeval * arg2)
        !          1099: {
        !          1100:     DPRINTF("futimes(0x%x, %p)\n", arg1, arg2);
        !          1101:     if(arg2)
        !          1102:     {
        !          1103:         byteswap_timeval(arg2);
        !          1104:         byteswap_timeval(arg2+1);
        !          1105:     }
        !          1106:     return get_errno(futimes(arg1, arg2));
        !          1107: }
        !          1108: 
        !          1109: long do_statfs(char * arg1, struct statfs * arg2)
        !          1110: {
        !          1111:     long ret;
        !          1112:     DPRINTF("statfs(%p, %p)\n", arg1, arg2);
        !          1113:     ret = get_errno(statfs(arg1, arg2));
        !          1114:     if(!is_error(ret))
        !          1115:         byteswap_statfs(arg2);
        !          1116:     return ret;
        !          1117: }
        !          1118: 
        !          1119: long do_fstatfs(uint32_t arg1, struct statfs* arg2)
        !          1120: {
        !          1121:     long ret;
        !          1122:     DPRINTF("fstatfs(0x%x, %p)\n",
        !          1123:             arg1, arg2);
        !          1124:     ret = get_errno(fstatfs(arg1, arg2));
        !          1125:     if(!is_error(ret))
        !          1126:         byteswap_statfs(arg2);
        !          1127: 
        !          1128:     return ret;
        !          1129: }
        !          1130: 
        !          1131: long do_stat(char * arg1, struct stat * arg2)
        !          1132: {
        !          1133:     long ret;
        !          1134:     /* XXX: don't let the %s stay in there */
        !          1135:     DPRINTF("stat(%s, %p)\n", arg1, arg2);
        !          1136:     ret = get_errno(stat(arg1, arg2));
        !          1137:     if(!is_error(ret))
        !          1138:         byteswap_stat(arg2);
        !          1139:     return ret;
        !          1140: }
        !          1141: 
        !          1142: long do_fstat(uint32_t arg1, struct stat * arg2)
        !          1143: {
        !          1144:     long ret;
        !          1145:     DPRINTF("fstat(0x%x, %p)\n", arg1, arg2);
        !          1146:     ret = get_errno(fstat(arg1, arg2));
        !          1147:     if(!is_error(ret))
        !          1148:         byteswap_stat(arg2);
        !          1149:     return ret;
        !          1150: }
        !          1151: 
        !          1152: long do_lstat(char * arg1, struct stat * arg2)
        !          1153: {
        !          1154:     long ret;
        !          1155:     /* XXX: don't let the %s stay in there */
        !          1156:     DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2);
        !          1157:     ret = get_errno(lstat(arg1, arg2));
        !          1158:     if(!is_error(ret))
        !          1159:         byteswap_stat(arg2);
        !          1160:     return ret;
        !          1161: }
        !          1162: 
        !          1163: long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4)
        !          1164: {
        !          1165:     long ret;
        !          1166:     DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4);
        !          1167:     if(arg4)
        !          1168:         tswap32s((uint32_t *)arg4);
        !          1169:     ret = get_errno(getdirentries(arg1, arg2, arg3, arg4));
        !          1170:     if(arg4)
        !          1171:         tswap32s((uint32_t *)arg4);
        !          1172:     if(!is_error(ret))
        !          1173:         byteswap_dirents(arg2, ret);
        !          1174:     return ret;
        !          1175: }
        !          1176: 
        !          1177: long do_lseek(void *cpu_env, int num)
        !          1178: {
        !          1179:     long ret;
        !          1180:     int i = 0;
        !          1181:     uint32_t arg1 = get_int_arg(&i, cpu_env);
        !          1182:     uint64_t offset = get_int64_arg(&i, cpu_env);
        !          1183:     uint32_t arg3 = get_int_arg(&i, cpu_env);
        !          1184:     uint64_t r = lseek(arg1, offset, arg3);
        !          1185: #ifdef TARGET_I386
        !          1186:     /* lowest word in eax, highest in edx */
        !          1187:     ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */
        !          1188:     ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ;
        !          1189: #elif defined TARGET_PPC
        !          1190:     ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */
        !          1191:     ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ;
        !          1192: #else
        !          1193:     qerror("64 bit ret value on your arch?");
        !          1194: #endif
        !          1195:     return get_errno(ret);
        !          1196: }
        !          1197: 
        !          1198: void no_swap(void * oldp, int size)
        !          1199: {
        !          1200: }
        !          1201: 
        !          1202: void sysctl_tswap32s(void * oldp, int size)
        !          1203: {
        !          1204:     tswap32s(oldp);
        !          1205: }
        !          1206: 
        !          1207: void bswap_oid(uint32_t * oldp, int size)
        !          1208: {
        !          1209:     int count = size / sizeof(int);
        !          1210:     int i = 0;
        !          1211:     do { tswap32s(oldp + i); } while (++i < count);
        !          1212: }
        !          1213: 
        !          1214: void sysctl_usrstack(uint32_t * oldp, int size)
        !          1215: {
        !          1216:     DPRINTF("sysctl_usrstack: 0x%x\n", *oldp);
        !          1217:     tswap32s(oldp);
        !          1218: }
        !          1219: 
        !          1220: void sysctl_ncpu(uint32_t * ncpu, int size)
        !          1221: {
        !          1222:     *ncpu = 0x1;
        !          1223:     DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu);
        !          1224:     tswap32s(ncpu);
        !          1225: }
        !          1226: 
        !          1227: void sysctl_exec(char * exec, int size)
        !          1228: {
        !          1229:     DPRINTF("sysctl_exec: %s\n", exec);
        !          1230: }
        !          1231: 
        !          1232: void sysctl_translate(char * exec, int size)
        !          1233: {
        !          1234:     DPRINTF("sysctl_translate: %s\n", exec);
        !          1235: }
        !          1236: 
        !          1237: struct sysctl_dir {
        !          1238:     int num;
        !          1239:     const char * name;
        !          1240:     void (*swap_func)(void *, int);
        !          1241:     struct sysctl_dir *childs;
        !          1242: };
        !          1243: 
        !          1244: #define ENTRYD(num, name, childs) { num, name, NULL, childs }
        !          1245: #define ENTRYE(num, name, func)   { num, name, (void (*)(void *, int))func, NULL  }
        !          1246: struct sysctl_dir sysctls_unspec[] = {
        !          1247:     ENTRYE(3,  "oip", bswap_oid),
        !          1248:     { 0, NULL, NULL, NULL }
        !          1249: };
        !          1250: 
        !          1251: struct sysctl_dir sysctls_kern[] = {
        !          1252:     ENTRYE(KERN_TRANSLATE,          "translate",    sysctl_translate), /* 44 */
        !          1253:     ENTRYE(KERN_EXEC,               "exec",         sysctl_exec), /* 45 */
        !          1254:     ENTRYE(KERN_USRSTACK32,          "KERN_USRSTACK32", sysctl_usrstack), /* 35 */
        !          1255:     ENTRYE(KERN_SHREG_PRIVATIZABLE,  "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */
        !          1256:     { 0, NULL, NULL, NULL }
        !          1257: };
        !          1258: 
        !          1259: struct sysctl_dir sysctls_hw[] = {
        !          1260:     ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s),
        !          1261:     ENTRYE(104, "104", no_swap),
        !          1262:     ENTRYE(105, "105", no_swap),
        !          1263:     { 0, NULL, NULL, NULL }
        !          1264: };
        !          1265: 
        !          1266: struct sysctl_dir sysctls[] = {
        !          1267:     ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec),
        !          1268:     ENTRYD(CTL_KERN, "kern", sysctls_kern),
        !          1269:     ENTRYD(CTL_HW,   "hw",   sysctls_hw ),
        !          1270:     { 0, NULL, NULL, NULL }
        !          1271: };
        !          1272: 
        !          1273: #undef ENTRYE
        !          1274: #undef ENTRYD
        !          1275: 
        !          1276: static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt)
        !          1277: {
        !          1278:     if(!sysctl_elmt)
        !          1279:         return NULL;
        !          1280:     for(; sysctl_elmt->name != NULL ; sysctl_elmt++) {
        !          1281:         if(sysctl_elmt->num == mib)
        !          1282:             return sysctl_elmt;
        !          1283:     }
        !          1284:     return NULL;
        !          1285: }
        !          1286: 
        !          1287: static inline long bswap_syctl(int * mib, int count, void *buf, int size)
        !          1288: {
        !          1289:     int i;
        !          1290:     struct sysctl_dir * sysctl = sysctls;
        !          1291:     struct sysctl_dir * ret = NULL;
        !          1292: 
        !          1293:     for(i = 0; i < count; i++) {
        !          1294: 
        !          1295:         if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) {
        !          1296:             gemu_log("bswap_syctl: can't find mib %d\n", mib[i]);
        !          1297:             return -ENOTDIR;
        !          1298:         }
        !          1299:         if(!(sysctl = sysctl->childs))
        !          1300:             break;
        !          1301:     }
        !          1302:     
        !          1303:     if(ret->childs)
        !          1304:         qerror("we shouldn't have a directory element\n");
        !          1305: 
        !          1306:     ret->swap_func(buf, size);
        !          1307:     return 0;
        !          1308: }
        !          1309: 
        !          1310: static inline void print_syctl(int * mib, int count)
        !          1311: {
        !          1312:     int i;
        !          1313:     struct sysctl_dir * sysctl = sysctls;
        !          1314:     struct sysctl_dir * ret = NULL;
        !          1315: 
        !          1316:     for(i = 0; i < count; i++) {
        !          1317:         if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){
        !          1318:             gemu_log("print_syctl: can't find mib %d\n", mib[i]);
        !          1319:             return;
        !          1320:         }
        !          1321:         DPRINTF("%s.", sysctl->name);
        !          1322:         if(!(sysctl = sysctl->childs))
        !          1323:             break;
        !          1324:     }
        !          1325:     DPRINTF("\n");
        !          1326: }
        !          1327: 
        !          1328: long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */)
        !          1329: {
        !          1330:     long ret = 0;
        !          1331:     int i;
        !          1332:     DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
        !          1333:             name, namelen, oldp, oldlenp, newp, newlen);
        !          1334:     if(name) {
        !          1335:         i = 0;
        !          1336:         do { tswap32s( name + i); } while (++i < namelen);
        !          1337:         print_syctl(name, namelen);
        !          1338:         //bswap_syctl(name, namelen, newp, newlen);
        !          1339:         tswap32s((uint32_t*)oldlenp);
        !          1340:     }
        !          1341:         
        !          1342:     if(name) /* Sometimes sysctl is called with no arg1, ignore */
        !          1343:         ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
        !          1344: 
        !          1345:     if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) {
        !          1346:         return -ENOTDIR;
        !          1347:     }
        !          1348:     if(name) {
        !          1349:         //bswap_syctl(name, namelen, newp, newlen);
        !          1350:         tswap32s((uint32_t*)oldlenp);
        !          1351: 
        !          1352:         i = 0;
        !          1353:         do { tswap32s( name + i); } while (++i < namelen);
        !          1354:     }
        !          1355:     return ret;
        !          1356: }
        !          1357: 
        !          1358: long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
        !          1359: {
        !          1360:     struct attrlist * attrlist = (void *)arg2;
        !          1361:     long ret;
        !          1362: 
        !          1363: #if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
        !          1364:     gemu_log("SYS_getdirentriesattr unimplemented\n");
        !          1365:     return -ENOTSUP;
        !          1366: #endif
        !          1367:     /* XXX: don't let the %s stay in there */
        !          1368:     DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
        !          1369:             (char *)arg1, arg2, arg3, arg4, arg5);
        !          1370: 
        !          1371:     if(arg2) /* XXX: We should handle that in a copy especially
        !          1372:         if the structure is not writable */
        !          1373:         byteswap_attrlist(attrlist);
        !          1374: 
        !          1375:     ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));
        !          1376: 
        !          1377:     if(!is_error(ret))
        !          1378:     {
        !          1379:         byteswap_attrbuf((void *)arg3, attrlist);
        !          1380:         byteswap_attrlist(attrlist);
        !          1381:     }
        !          1382:     return ret;
        !          1383: }
        !          1384: 
        !          1385: long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8)
        !          1386: {
        !          1387:     DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n",
        !          1388:             arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
        !          1389: #if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
        !          1390:     qerror("SYS_getdirentriesattr unimplemented\n");
        !          1391: #endif
        !          1392: 
        !          1393:     return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4,
        !          1394:                                        (unsigned long *)arg5, (unsigned long *)arg6,
        !          1395:                                        (unsigned long *)arg7, arg8));
        !          1396: }
        !          1397: 
        !          1398: static inline void bswap_flock(struct flock *f)
        !          1399: {
        !          1400:     tswap64s(&f->l_start);
        !          1401:     tswap64s(&f->l_len);
        !          1402:     tswap32s(&f->l_pid);
        !          1403:     tswap16s(&f->l_type);
        !          1404:     tswap16s(&f->l_whence);
        !          1405: }
        !          1406: 
        !          1407: static inline void bswap_fstore(struct fstore *f)
        !          1408: {
        !          1409:     tswap32s(&f->fst_flags);
        !          1410:     tswap32s(&f->fst_posmode);
        !          1411:     tswap64s(&f->fst_offset);
        !          1412:     tswap64s(&f->fst_length);
        !          1413:     tswap64s(&f->fst_bytesalloc);
        !          1414: }
        !          1415: 
        !          1416: static inline void bswap_radvisory(struct radvisory *f)
        !          1417: {
        !          1418:     tswap64s(&f->ra_offset);
        !          1419:     tswap32s(&f->ra_count);
        !          1420: }
        !          1421: 
        !          1422: static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f)
        !          1423: {
        !          1424:     tswap64s(&f->fbt_offset);
        !          1425:     tswap32s((uint32_t*)&f->fbt_length);
        !          1426:     tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */
        !          1427: }
        !          1428: 
        !          1429: static inline void bswap_log2phys(struct log2phys *f)
        !          1430: {
        !          1431:     tswap32s(&f->l2p_flags);
        !          1432:     tswap64s(&f->l2p_contigbytes);
        !          1433:     tswap64s(&f->l2p_devoffset);
        !          1434: }
        !          1435: 
        !          1436: static inline void bswap_fcntl_arg(int cmd, void * arg)
        !          1437: {
        !          1438:     switch(cmd)
        !          1439:     {
        !          1440:         case F_DUPFD:
        !          1441:         case F_GETFD:
        !          1442:         case F_SETFD:
        !          1443:         case F_GETFL:
        !          1444:         case F_SETFL:
        !          1445:         case F_GETOWN:
        !          1446:         case F_SETOWN:
        !          1447:         case F_SETSIZE:
        !          1448:         case F_RDAHEAD:
        !          1449:         case F_FULLFSYNC:
        !          1450:             break;
        !          1451:         case F_GETLK:
        !          1452:         case F_SETLK:
        !          1453:         case F_SETLKW:
        !          1454:             bswap_flock(arg);
        !          1455:             break;
        !          1456:         case F_PREALLOCATE:
        !          1457:             bswap_fstore(arg);
        !          1458:             break;
        !          1459:         case F_RDADVISE:
        !          1460:             bswap_radvisory(arg);
        !          1461:             break;
        !          1462:         case F_READBOOTSTRAP:
        !          1463:         case F_WRITEBOOTSTRAP:
        !          1464:             bswap_fbootstraptransfer(arg);
        !          1465:             break;
        !          1466:         case F_LOG2PHYS:
        !          1467:             bswap_log2phys(arg);
        !          1468:             break;
        !          1469:         default:
        !          1470:             gemu_log("unknow cmd in fcntl\n");
        !          1471:     }
        !          1472: }
        !          1473: 
        !          1474: long do_fcntl(int fd, int cmd, int arg)
        !          1475: {
        !          1476:     long ret;
        !          1477:     bswap_fcntl_arg(cmd, (void *)arg);
        !          1478:     ret = get_errno(fcntl(fd, cmd, arg));
        !          1479:     if(!is_error(ret))
        !          1480:         bswap_fcntl_arg(cmd, (void *)arg);
        !          1481:     return ret;
        !          1482: }
        !          1483: 
        !          1484: long no_syscall(void *cpu_env, int num)
        !          1485: {
        !          1486:     /* XXX: We should probably fordward it to the host kernel */
        !          1487:     qerror("no unix syscall %d\n", num);
        !          1488:     /* not reached */
        !          1489:     return -1;
        !          1490: }
        !          1491: 
        !          1492: long unimpl_unix_syscall(void *cpu_env, int num)
        !          1493: {
        !          1494:     if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
        !          1495:         qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
        !          1496: 
        !          1497:     gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num);
        !          1498:     gdb_handlesig (cpu_env, SIGTRAP);
        !          1499:     exit(-1);
        !          1500: }
        !          1501: 
        !          1502: long do_unix_syscall(void *cpu_env, int num)
        !          1503: {
        !          1504:     long ret = 0;
        !          1505: 
        !          1506:     DPRINTF("unix syscall %d: " , num);
        !          1507: 
        !          1508:     if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
        !          1509:         qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
        !          1510: 
        !          1511:     DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" );
        !          1512:     ret = unix_syscall_table[num].function(cpu_env, num);
        !          1513: 
        !          1514:     if(!(unix_syscall_table[num].call_type & CALL_NOERRNO))
        !          1515:         ret = get_errno(ret);
        !          1516: 
        !          1517:     DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret);
        !          1518:     return ret;
        !          1519: }
        !          1520: 
        !          1521: /* ------------------------------------------------------------
        !          1522:    syscall_init
        !          1523: */
        !          1524: void syscall_init(void)
        !          1525: {
        !          1526:     /* Nothing yet */
        !          1527: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.