+ ParamInfoBlock pib = Arch::copyin(user_pib);
+ printf("objlist len %u\n", pib.objlist_len);
+
+ if (pib.objlist_len == 0)
+ throw_idl(InvalidArgument, 0, countarray<ORBMM>("no objects"));
+
+ // FIXME: declare constants somewhere
+ if (pib.num_segments > 64)
+ throw_idl(InvalidArgument, 0, countarray<ORBMM>("too many segments"));
+ if (pib.objlist_len > 4096)
+ throw_idl(InvalidArgument, 0, countarray<ORBMM>("too many objects"));
+
+ printf("&pib.objlist[0] %p\n", &pib.objlist[0]);
+
+ IDSpace *ids = &curthread->aspace->idspace;
+ ID objid = Arch::copyin(&pib.objlist[0]);
+ Object *obj = ids->lookup(objid);
+
+ if (!obj) {
+ printf("no obj %d\n", objid);
+ throw_idl(InvalidReference, 0, nullarray);
+ }
+
+ printf("obj %p\n", obj);
+
+ if (obj->aspace == Arch::init_thread->aspace) {
+ KernObject *ko = static_cast<KernObject *>(obj);
+ int datalen = round_up(pib.buffer_size, 8);
+ int buflen = datalen + pib.objlist_len * sizeof(void *);
+ int piboff = datalen;
+ buflen += sizeof(ParamInfoBlock);
+ buflen += pib.num_segments * sizeof(ParamInfoBlock::Segment);
+
+ u8 *args = new(ORBMM()) u8[buflen];
+ u8 *copy = new(ORBMM()) u8[pib.copy_size];
+ ParamInfoBlock *dpib = reinterpret_cast<ParamInfoBlock *>
+ (args + piboff);
+ dpib->objlist = reinterpret_cast<ID *>(args + datalen);
+
+ copy_ids_to_kern(dpib, &pib, ids);
+ copy_data(args, args, pib.buffer_size, dpib, &pib, ~0U, Segment::In);
+ copy_data(copy, copy, pib.copy_size, dpib, &pib, ~0U,
+ Segment::In | Segment::Copy);
+
+ ko->entry(dpib);
+
+ // FIXME: Copy return data
+ return;
+ }
+
+ CallFrame *frame = new_frame(curthread);
+ frame->caller_user_pib = user_pib;
+ frame->ret_stack = stack;
+
+ printf("invoke_method: frame %p pib %p ret_stack %lx obj %p\n",
+ frame, frame->caller_user_pib,
+ frame->ret_stack, obj);
+ }
+
+ uintptr_t return_from_method(uintptr_t &exptr, size_t &exlen)
+ {
+ return 0;
+ }
+
+ void init()
+ {
+ kernobjs = new KIDTable;
+ }