/* mig_put_reply_port(_buf_start->Head.msgh_local_port); */ #if 0 if (_buf_start->RetCode != KERN_SUCCESS) fprintf(stderr,"Return error code: %x\n", _buf_start->RetCode); #endif return mr; } #if 0 /* the send is handled by a direct call to mach_msg now */ mach_msg_return_t flick_mach3mig_send(void *buf_current, mach_msg_option_t msg_options, mach_msg_timeout_t timeout) { register mig_reply_header_t *_buf_start = _global_buf_start; register void *_buf_current = buf_current; mach_msg_return_t mr; _buf_start->Head.msgh_local_port = MACH_PORT_NULL; #if 0 printf("Send:\n"); print_message(_buf_start, _buf_start->Head.msgh_size); #endif mr = mach_msg(&_buf_start->Head, MACH_SEND_MSG|msg_options, _buf_start->Head.msgh_size, 0, MACH_PORT_NULL, timeout, MACH_PORT_NULL); if (mr != MACH_MSG_SUCCESS) { while (mr == MACH_SEND_INTERRUPTED) { /* Retry both the send and the receive. */ mr = mach_msg_trap(&_buf_start->Head, MACH_SEND_MSG, _buf_start->Head.msgh_size, 0, MACH_PORT_NULL, 0, 0); } if (mr != MACH_MSG_SUCCESS) { #if 0 if ((mr == MACH_SEND_INVALID_REPLY) || (mr == MACH_SEND_INVALID_MEMORY) || (mr == MACH_SEND_INVALID_RIGHT) || (mr == MACH_SEND_INVALID_TYPE) || (mr == MACH_SEND_MSG_TOO_SMALL) || (mr == MACH_RCV_INVALID_NAME)) mig_dealloc_reply_port(_buf_start->Head.msgh_local_port); else mig_put_reply_port(_buf_start->Head.msgh_local_port); #endif return mr; } } #if 0 if (_buf_start->RetCode != KERN_SUCCESS) fprintf(stderr,"Return error code: %x\n", _buf_start->RetCode); #endif return mr; }
static int32 mach_msg(MachHeader *h, int32 op, uint32 send_size, uint32 rcv_size, uint32 rcv_name, uint32 timeout, uint32 notify) { // TODO: Loop on interrupt. return runtime·mach_msg_trap(h, op, send_size, rcv_size, rcv_name, timeout, notify); }
mach_msg_return_t flick_mach3mig_rpc(mach_msg_option_t msg_options, mach_msg_timeout_t timeout) { register mig_reply_header_t *_buf_start = _global_buf_start; mach_msg_return_t mr; int buf_size = ((int)_buf_end - (int)_buf_start); /* * Consider the following cases: * 1) Errors in pseudo-receive (eg, MACH_SEND_INTERRUPTED * plus special bits). * 2) Use of MACH_SEND_INTERRUPT/MACH_RCV_INTERRUPT options. * 3) RPC calls with interruptions in one/both halves. * 4) Exception reply messages that are bigger * than the expected non-exception reply message. * * We refrain from passing the option bits that we implement * to the kernel. This prevents their presence from inhibiting * the kernel's fast paths (when it checks the option value). */ #if 0 printf("RPC-SND:\n"); print_message(_buf_start, _buf_start->Head.msgh_size); #endif mr = mach_msg(&_buf_start->Head, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE | msg_options, _buf_start->Head.msgh_size, buf_size, _buf_start->Head.msgh_local_port, timeout, MACH_PORT_NULL); if (mr != MACH_MSG_SUCCESS) { while (mr == MACH_SEND_INTERRUPTED) { /* Retry both the send and the receive. */ mr = mach_msg_trap(&_buf_start->Head, (MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_LARGE | msg_options), _buf_start->Head.msgh_size, buf_size, _buf_start->Head.msgh_local_port, timeout, MACH_PORT_NULL); } while ((mr == MACH_RCV_INTERRUPTED) || (mr == MACH_RCV_TOO_LARGE)) { if (mr == MACH_RCV_TOO_LARGE) { /* Oops, message too large - grow the buffer. */ buf_size = _buf_start->Head.msgh_size; if (!(_buf_start = (mig_reply_header_t *) nonposix_realloc(_buf_start, buf_size))) { mig_dealloc_reply_port(/*_buf_start->Head.msgh_local_port*/); return FLICK_NO_MEMORY; } #if 0 __buffer = _buf_start; __buflen = buf_size; #endif } /* Retry the receive only (the request message has already been sent successfully). */ mr = mach_msg_trap(&_buf_start->Head, MACH_RCV_MSG|MACH_RCV_LARGE|msg_options, 0, buf_size, _buf_start->Head.msgh_local_port, timeout, MACH_PORT_NULL); } if (mr != MACH_MSG_SUCCESS) { #if 0 if ((mr == MACH_SEND_INVALID_REPLY) || (mr == MACH_SEND_INVALID_MEMORY) || (mr == MACH_SEND_INVALID_RIGHT) || (mr == MACH_SEND_INVALID_TYPE) || (mr == MACH_SEND_MSG_TOO_SMALL) || (mr == MACH_RCV_INVALID_NAME)) mig_dealloc_reply_port(_buf_start->Head.msgh_local_port); else mig_put_reply_port(_buf_start->Head.msgh_local_port); #endif return mr; } } #if 0 printf("RPC-RCV: (%d, 0x%08x)\n", mr, mr); print_message(_buf_start, _buf_start->Head.msgh_size); scanf("%d",&mr); #endif /* Stash the reply port again for future use. */ /* mig_put_reply_port(_buf_start->Head.msgh_local_port); */ #if 0 if (_buf_start->RetCode != KERN_SUCCESS) fprintf(stderr,"Return error code: %x\n", _buf_start->RetCode); #endif return mr; }
static inline uint32_t target_mach_msg_trap( mach_msg_header_t *hdr, uint32_t options, uint32_t send_size, uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify) { extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t, mach_msg_size_t, mach_msg_size_t, mach_port_t, mach_msg_timeout_t, mach_port_t); mach_msg_audit_trailer_t *trailer; mach_msg_id_t msg_id; uint32_t ret = 0; int i; swap_mach_msg(hdr, bswap_in); msg_id = hdr->msgh_id; print_description_msg_header(hdr); ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify); print_mach_msg_return(ret); if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) ) { /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should probably always bswap it */ /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in natural_t units but according to xnu/osfmk/mach/message.h: "The size of the message must be specified in bytes" */ trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size); /* XXX: Should probably do that based on the option asked by the sender, but dealing with kernel answer seems more sound */ switch(trailer->msgh_trailer_size) { case sizeof(mach_msg_audit_trailer_t): for(i = 0; i < 8; i++) tswap32s(&trailer->msgh_audit.val[i]); /* Fall in mach_msg_security_trailer_t case */ case sizeof(mach_msg_security_trailer_t): tswap32s(&trailer->msgh_sender.val[0]); tswap32s(&trailer->msgh_sender.val[1]); /* Fall in mach_msg_seqno_trailer_t case */ case sizeof(mach_msg_seqno_trailer_t): tswap32s(&trailer->msgh_seqno); /* Fall in mach_msg_trailer_t case */ case sizeof(mach_msg_trailer_t): tswap32s(&trailer->msgh_trailer_type); tswap32s(&trailer->msgh_trailer_size); break; case 0: /* Safer not to byteswap, but probably wrong */ break; default: qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size); break; } } /* Special message handling */ switch (msg_id) { case 200: /* host_info */ { mig_reply_error_t *err = (mig_reply_error_t *)hdr; struct { uint32_t unknow1; uint32_t max_cpus; uint32_t avail_cpus; uint32_t memory_size; uint32_t cpu_type; uint32_t cpu_subtype; } *data = (void *)(err+1); DPRINTF("maxcpu = 0x%x\n", data->max_cpus); DPRINTF("numcpu = 0x%x\n", data->avail_cpus); DPRINTF("memsize = 0x%x\n", data->memory_size); #if defined(TARGET_I386) data->cpu_type = CPU_TYPE_I386; DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type); data->cpu_subtype = CPU_SUBTYPE_PENT; DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype); #elif defined(TARGET_PPC) data->cpu_type = CPU_TYPE_POWERPC; DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type); data->cpu_subtype = CPU_SUBTYPE_POWERPC_750; DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype); #else # error target not supported #endif break; } case 202: /* host_page_size */ { mig_reply_error_t *err = (mig_reply_error_t *)hdr; uint32_t *pagesize = (uint32_t *)(err+1); DPRINTF("pagesize = %d\n", *pagesize); break; } default: break; } swap_mach_msg(hdr, bswap_out); return ret; }