bootstrap_cmds/migcom.tproj/server.c
1/*
2 * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * @OSF_COPYRIGHT@
25 */
26/*
27 * Mach Operating System
28 * Copyright (c) 1991,1990 Carnegie Mellon University
29 * All Rights Reserved.
30 *
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
36 *
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 *
41 * Carnegie Mellon requests users of this software to return to
42 *
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
47 *
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
50 */
51
52#include <assert.h>
53#include <stdlib.h>
54
55#include <mach/message.h>
56#include "write.h"
57#include "utils.h"
58#include "global.h"
59#include "error.h"
60
61#ifndef max
62#define max(a,b) (((a) > (b)) ? (a) : (b))
63#endif /* max */
64
65void WriteLogDefines(FILE *file, string_t who);
66void WriteIdentificationString(FILE *file);
67static void WriteFieldDecl(FILE *file, argument_t *arg);
68
69#define InHeadSeg (UseMachMsg2 ? "InKP" : "In0P")
70#define OutHeadSeg (UseMachMsg2 ? "OutKP" : "OutP")
71
72/* Bear Trap: Certain MIG features are left unimplemented for mach_msg2() KernelServer */
73#define __KernelServer_unreachable() \
74do {\
75 if (UseMachMsg2) \
76 fatal("mach_msg2 KernelServer support for this code block is unimplemented."); \
77} while (0)
78
79static void
80WriteKPD_Iterator(FILE *file, boolean_t in, boolean_t varying, argument_t *arg, boolean_t bracket)
81{
82 ipc_type_t *it = arg->argType;
83 char string[MAX_STR_LEN];
84
85 fprintf(file, "\t{\n");
86 fprintf(file, "\t %s\t*ptr;\n", it->itKPDType);
87 fprintf(file, "\t int\ti");
88 if (varying && !in)
89 fprintf(file, ", j");
90 fprintf(file, ";\n\n");
91
92 if (in)
93 sprintf(string, "%s", arg->argInSegment);
94 else
95 sprintf(string, "%s", arg->argOutSegment);
96
97 fprintf(file, "\t ptr = &%s->%s[0];\n", string, arg->argMsgField);
98
99 if (varying) {
100 argument_t *count = arg->argCount;
101
102 if (in)
103 fprintf(file, "\t for (i = 0; i < %s->%s; ptr++, i++) %s\n", count->argInSegment, count->argMsgField, (bracket) ? "{" : "");
104 else {
105 fprintf(file, "\t j = min(%d, ", it->itKPD_Number);
106 if (akCheck(count->argKind, akbVarNeeded))
107 fprintf(file, "%s);\n", count->argName);
108 else
109 fprintf(file, "%s->%s);\n", string, count->argMsgField);
110 fprintf(file, "\t for (i = 0; i < j; ptr++, i++) %s\n", (bracket) ? "{" : "");
111 }
112}
113 else
114 fprintf(file, "\t for (i = 0; i < %d; ptr++, i++) %s\n", it->itKPD_Number, (bracket) ? "{" : "");
115}
116
117static void
118WriteMyIncludes(FILE *file, statement_t *stats)
119{
120 if (ServerHeaderFileName == strNULL || UseSplitHeaders)
121 WriteIncludes(file, FALSE, FALSE);
122 if (ServerHeaderFileName != strNULL)
123 {
124 char *cp;
125
126 /* Strip any leading path from ServerHeaderFileName. */
127 cp = strrchr(ServerHeaderFileName, '/');
128 if (cp == 0)
129 cp = ServerHeaderFileName;
130 else
131 cp++; /* skip '/' */
132 fprintf(file, "#include \"%s\"\n", cp);
133 }
134 if (ServerHeaderFileName == strNULL || UseSplitHeaders)
135 WriteImplImports(file, stats, FALSE);
136 if (UseEventLogger) {
137 if (IsKernelServer) {
138 fprintf(file, "#if\t__MigKernelSpecificCode\n");
139 fprintf(file, "#include <mig_debug.h>\n");
140 fprintf(file, "#endif\t/* __MigKernelSpecificCode */\n");
141 }
142 fprintf(file, "#if MIG_DEBUG\n");
143 fprintf(file, "#include <mach/mig_log.h>\n");
144 fprintf(file, "#endif /* MIG_DEBUG */\n");
145 }
146
147 fprintf(file, "\n");
148}
149
150static void
151WriteGlobalDecls(FILE *file)
152{
153 if (BeAnsiC) {
154 fprintf(file, "#define novalue void\n");
155 }
156 else {
157 fprintf(file, "#if\t%s\n", NewCDecl);
158 fprintf(file, "#define novalue void\n");
159 fprintf(file, "#else\n");
160 fprintf(file, "#define novalue int\n");
161 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
162 }
163 fprintf(file, "\n");
164
165 if (RCSId != strNULL)
166 WriteRCSDecl(file, strconcat(SubsystemName, "_server"), RCSId);
167
168 /* Used for locations in the request message, *not* reply message.
169 Reply message locations aren't dependent on IsKernelServer. */
170
171 if (IsKernelServer) {
172 fprintf(file, "#if\t__MigKernelSpecificCode\n");
173 fprintf(file, "#define msgh_request_port\tmsgh_remote_port\n");
174 fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
175 fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
176 fprintf(file, "#define msgh_reply_port\t\tmsgh_local_port\n");
177 fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
178 fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
179 fprintf(file, "#else\n");
180 }
181 fprintf(file, "#define msgh_request_port\tmsgh_local_port\n");
182 fprintf(file, "#define MACH_MSGH_BITS_REQUEST(bits)");
183 fprintf(file, "\tMACH_MSGH_BITS_LOCAL(bits)\n");
184 fprintf(file, "#define msgh_reply_port\t\tmsgh_remote_port\n");
185 fprintf(file, "#define MACH_MSGH_BITS_REPLY(bits)");
186 fprintf(file, "\tMACH_MSGH_BITS_REMOTE(bits)\n");
187 if (IsKernelServer) {
188 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
189 }
190 fprintf(file, "\n");
191 if (UseEventLogger)
192 WriteLogDefines(file, "MACH_MSG_LOG_SERVER");
193 fprintf(file, "#define MIG_RETURN_ERROR(X, code)\t{\\\n");
194 fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->RetCode = code;\\\n");
195 fprintf(file, "\t\t\t\t((mig_reply_error_t *)X)->NDR = NDR_record;\\\n");
196 fprintf(file, "\t\t\t\treturn;\\\n");
197 fprintf(file, "\t\t\t\t}\n");
198 fprintf(file, "\n");
199}
200
201
202static void
203WriteForwardDeclarations(FILE *file, statement_t *stats)
204{
205 statement_t *stat;
206
207 fprintf(file, "/* Forward Declarations */\n\n");
208 for (stat = stats; stat != stNULL; stat = stat->stNext)
209 if (stat->stKind == skRoutine) {
210 fprintf(file, "\nmig_internal novalue _X%s\n", stat->stRoutine->rtName);
211 if (!UseMachMsg2) {
212 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);\n");
213 } else {
214 fprintf(file, "\t(mach_msg_header_t *InHeadP, void *InDataP, mach_msg_max_trailer_t *InTrailerP, "
215 "mach_msg_header_t *OutHeadP, void *OutDataP);\n");
216 }
217 }
218 fprintf(file, "\n");
219}
220
221static void
222WriteMIGCheckDefines(FILE *file)
223{
224 fprintf(file, "#define\t__MIG_check__Request__%s_subsystem__ 1\n", SubsystemName);
225 fprintf(file, "\n");
226}
227
228static void
229WriteNDRDefines(FILE *file)
230{
231 fprintf(file, "#define\t__NDR_convert__Request__%s_subsystem__ 1\n", SubsystemName);
232 fprintf(file, "\n");
233}
234
235static void
236WriteProlog(FILE *file, statement_t *stats)
237{
238 WriteIdentificationString(file);
239 fprintf(file, "\n");
240 fprintf(file, "/* Module %s */\n", SubsystemName);
241 fprintf(file, "\n");
242 WriteMIGCheckDefines(file);
243 if (CheckNDR)
244 WriteNDRDefines(file);
245 WriteMyIncludes(file, stats);
246 WriteBogusDefines(file);
247 WriteApplDefaults(file, "Rcv");
248 WriteGlobalDecls(file);
249 if (ServerHeaderFileName == strNULL) {
250 WriteRequestTypes(file, stats);
251 WriteReplyTypes(file, stats);
252 WriteServerReplyUnion(file, stats);
253 }
254}
255
256static void
257WriteSymTabEntries(FILE *file, statement_t *stats)
258{
259 statement_t *stat;
260 u_int current = 0;
261
262 for (stat = stats; stat != stNULL; stat = stat->stNext)
263 if (stat->stKind == skRoutine) {
264 int num = stat->stRoutine->rtNumber;
265 char *name = stat->stRoutine->rtName;
266 while (++current <= num)
267 fprintf(file,"\t\t\t{ \"\", 0, 0 },\n");
268 fprintf(file, "\t{ \"%s\", %d, _X%s },\n", name, SubsystemBase + current - 1, name);
269 }
270 while (++current <= rtNumber)
271 fprintf(file,"\t{ \"\", 0, 0 },\n");
272}
273
274static void
275WriteRoutineEntries(FILE *file, statement_t *stats)
276{
277 u_int current = 0;
278 statement_t *stat;
279 char *sig_array, *rt_name;
280 int arg_count, descr_count;
281 int offset = 0;
282 size_t serverSubsysNameLen = strlen(ServerSubsys);
283 char *kern_ = UseMachMsg2 ? "kern_" : "";
284
285 fprintf(file, "\t{\n");
286 for (stat = stats; stat != stNULL; stat = stat->stNext)
287 if (stat->stKind == skRoutine) {
288 routine_t *rt = stat->stRoutine;
289 size_t rtNameLen = strlen(rt->rtName);
290
291 if (MaxServerReplyDescrs >= 0 && rt->rtReplyKPDs > MaxServerReplyDescrs) {
292 fatal("WriteRoutine(): method %s uses %d reply descriptors (larger than %d)",
293 rt->rtName, rt->rtReplyKPDs, MaxServerReplyDescrs);
294 }
295 if (MaxServerDescrs >= 0 && rt->rtRequestKPDs > MaxServerDescrs) {
296 fatal("WriteRoutine(): method %s uses %d descriptors (larger than %d)",
297 rt->rtName, rt->rtRequestKPDs, MaxServerDescrs);
298 }
299
300 // Include length of rt->rtName in calculation of necessary buffer size, since that string
301 // is actually written into the buffer along with the Server Subsystem name.
302 sig_array = (char *) malloc(serverSubsysNameLen + rtNameLen + 80);
303 rt_name = (char *) malloc(rtNameLen + 5);
304 while (current++ < rt->rtNumber)
305 fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n");
306 // NOTE: if either of the two string constants in the sprintf() function calls below get
307 // much longer, be sure to increase the constant '80' (in the first malloc() call) to ensure
308 // that the allocated buffer is large enough. (Currently, I count 66 characters in the first
309 // string constant, 65 in the second. 80 ought to be enough for now...)
310 if (UseRPCTrap) {
311 sprintf(sig_array, "&%s.arg_descriptor[%d], (mach_msg_size_t)sizeof(__Reply__%s_t)", ServerSubsys, offset, rt->rtName);
312 }
313 else {
314 if (!UseMachMsg2) {
315 sprintf(sig_array, "(routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__%s_t)", rt->rtName);
316 } else {
317 sprintf(sig_array, "%d, (mach_msg_size_t)sizeof(__Reply__%s_t)", rt->rtReplyKPDs, rt->rtName);
318 }
319 }
320 sprintf(rt_name, "_X%s", rt->rtName);
321 descr_count = rtCountArgDescriptors(rt->rtArgs, &arg_count);
322 offset += descr_count;
323
324 fprintf(file, " { (mig_impl_routine_t) 0,\n\
325 (mig_stub_%sroutine_t) %s, ", kern_, rt_name);
326 fprintf(file, "%d, %d, %s}", arg_count, (UseRPCTrap) ? descr_count : 0, sig_array);
327
328 fprintf(file, ",\n");
329 free(sig_array);
330 free(rt_name);
331 }
332 while (current++ < rtNumber)
333 fprintf(file, "\t\t{0, 0, 0, 0, 0, 0},\n");
334
335 fprintf(file, "\t}");
336}
337
338static void
339WriteArgDescriptorEntries(FILE *file, statement_t *stats)
340{
341 statement_t *stat;
342
343 fprintf(file, ",\n\n\t{\n");
344 for (stat = stats; stat != stNULL; stat = stat->stNext)
345 if (stat->stKind == skRoutine) {
346 routine_t *rt = stat->stRoutine;
347
348 /* For each arg of the routine, write an arg descriptor:
349 */
350 WriteRPCRoutineArgDescriptor(file, rt);
351 }
352 fprintf(file, "\t},\n\n");
353}
354
355
356/*
357 * Write out the description of this subsystem, for use in direct RPC
358 */
359static void
360WriteSubsystem(FILE *file, statement_t *stats)
361{
362 statement_t *stat;
363 int descr_count = 0;
364 char *kern_ = "";
365 char *k = "";
366 char *kernel = "";
367
368 if (UseMachMsg2) {
369 kern_ = "kern_";
370 k = "k";
371 kernel = "kernel ";
372 }
373
374 for (stat = stats; stat != stNULL; stat = stat->stNext)
375 if (stat->stKind == skRoutine) {
376 routine_t *rt = stat->stRoutine;
377 descr_count += rtCountArgDescriptors(rt->rtArgs, (int *) 0);
378 }
379 fprintf(file, "\n");
380 if (ServerHeaderFileName == strNULL) {
381 WriteMigExternal(file);
382 fprintf(file, "boolean_t %s(", ServerDemux);
383 if (BeAnsiC) {
384 fprintf(file, "\n\t\tmach_msg_header_t *InHeadP,");
385 if (!UseMachMsg2) {
386 fprintf(file, "\n\t\tmach_msg_header_t *OutHeadP");
387 } else {
388 fprintf(file, "\n\t\tvoid *InDataP,");
389 fprintf(file, "\n\t\tmach_msg_header_t *OutHeadP,");
390 fprintf(file, "\n\t\tvoid *OutDataP");
391 }
392 }
393 fprintf(file, ");\n\n");
394
395 WriteMigExternal(file);
396 fprintf(file, "mig_%sroutine_t %s_routine(", kern_, ServerDemux);
397 if (BeAnsiC) {
398 fprintf(file, "\n\t\tmach_msg_header_t *InHeadP");
399 }
400 fprintf(file, ");\n\n");
401 }
402 fprintf(file, "\n/* Description of this %ssubsystem, for use in direct RPC */\n", kernel);
403 if (ServerHeaderFileName == strNULL) {
404 fprintf(file, "const struct %s {\n", ServerSubsys);
405 if (UseRPCTrap) {
406 __KernelServer_unreachable();
407 fprintf(file, "\tstruct subsystem *\tsubsystem;\t/* Reserved for system use */\n");
408 }
409 else {
410 fprintf(file, "\tmig_%sserver_routine_t \t%sserver;\t/* Server routine */\n", kern_, k);
411 }
412 fprintf(file, "\tmach_msg_id_t\tstart;\t/* Min routine number */\n");
413 fprintf(file, "\tmach_msg_id_t\tend;\t/* Max routine number + 1 */\n");
414 fprintf(file, "\tunsigned int\tmaxsize;\t/* Max msg size */\n");
415 if (UseRPCTrap) {
416 fprintf(file, "\tvm_address_t\tbase_addr;\t/* Base address */\n");
417 fprintf(file, "\tstruct rpc_routine_descriptor\t/* Array of routine descriptors */\n");
418 }
419 else {
420 fprintf(file, "\tvm_address_t\treserved;\t/* Reserved */\n");
421 fprintf(file, "\tstruct %sroutine_descriptor\t/* Array of routine descriptors */\n", kern_);
422 }
423 fprintf(file, "\t\t%sroutine[%d];\n", k, rtNumber);
424 if (UseRPCTrap) {
425 fprintf(file, "\tstruct rpc_routine_arg_descriptor\t/*Array of arg descriptors */\n");
426 fprintf(file, "\t\targ_descriptor[%d];\n", descr_count);
427 }
428 fprintf(file, "} %s = {\n", ServerSubsys);
429 }
430 else {
431 fprintf(file, "const struct %s %s = {\n", ServerSubsys, ServerSubsys);
432 }
433 if (UseRPCTrap) {
434 fprintf(file, "\t0,\n");
435 }
436 else {
437 fprintf(file, "\t%s_routine,\n", ServerDemux);
438 }
439 fprintf(file, "\t%d,\n", SubsystemBase);
440 fprintf(file, "\t%d,\n", SubsystemBase + rtNumber);
441 fprintf(file, "\t(mach_msg_size_t)sizeof(union __ReplyUnion__%s),\n", ServerSubsys);
442 if (UseRPCTrap) {
443 fprintf(file, "\t(vm_address_t)&%s,\n", ServerSubsys);
444 }
445 else {
446 fprintf(file, "\t(vm_address_t)0,\n");
447 }
448 WriteRoutineEntries(file, stats);
449
450 if (UseRPCTrap)
451 WriteArgDescriptorEntries(file, stats);
452 else
453 fprintf(file, "\n");
454
455 fprintf(file, "};\n\n");
456}
457
458#if NOT_CURRENTLY_USED
459
460static void
461WriteArraySizes(FILE *file, statement_t *stats)
462{
463 u_int current = 0;
464 statement_t *stat;
465
466 for (stat = stats; stat != stNULL; stat = stat->stNext)
467 if (stat->stKind == skRoutine) {
468 routine_t *rt = stat->stRoutine;
469
470 while (current++ < rt->rtNumber)
471 fprintf(file, "\t\t0,\n");
472 fprintf(file, "\t\t(mach_msg_size_t)sizeof(__Reply__%s_t),\n", rt->rtName);
473 }
474 while (current++ < rtNumber)
475 fprintf(file, "\t\t\t0,\n");
476}
477
478#endif /* NOT_CURRENTLY_USED */
479
480void
481WriteServerRequestUnion(FILE *file, statement_t *stats)
482{
483 statement_t *stat;
484
485 fprintf(file, "\n");
486 fprintf(file, "/* union of all requests */\n\n");
487 fprintf(file, "#ifndef __RequestUnion__%s__defined\n", ServerSubsys);
488 fprintf(file, "#define __RequestUnion__%s__defined\n", ServerSubsys);
489 fprintf(file, "union __RequestUnion__%s {\n", ServerSubsys);
490 for (stat = stats; stat != stNULL; stat = stat->stNext) {
491 if (stat->stKind == skRoutine) {
492 routine_t *rt;
493
494 rt = stat->stRoutine;
495 fprintf(file, "\t__Request__%s_t Request_%s;\n", rt->rtName, rt->rtName);
496 }
497 }
498 fprintf(file, "};\n");
499 fprintf(file, "#endif /* __RequestUnion__%s__defined */\n", ServerSubsys);
500}
501
502void
503WriteServerReplyUnion(FILE *file, statement_t *stats)
504{
505 statement_t *stat;
506
507 fprintf(file, "\n");
508 fprintf(file, "/* union of all replies */\n\n");
509 fprintf(file, "#ifndef __ReplyUnion__%s__defined\n", ServerSubsys);
510 fprintf(file, "#define __ReplyUnion__%s__defined\n", ServerSubsys);
511 fprintf(file, "union __ReplyUnion__%s {\n", ServerSubsys);
512 for (stat = stats; stat != stNULL; stat = stat->stNext) {
513 if (stat->stKind == skRoutine) {
514 routine_t *rt;
515
516 rt = stat->stRoutine;
517 fprintf(file, "\t__Reply__%s_t Reply_%s;\n", rt->rtName, rt->rtName);
518 }
519 }
520 fprintf(file, "};\n");
521 fprintf(file, "#endif /* __ReplyUnion__%s__defined */\n", ServerSubsys);
522}
523
524static void
525WriteDispatcher(FILE *file, statement_t *stats)
526{
527 char *k = "";
528 char *kern_ = "";
529
530 if (UseMachMsg2) {
531 k = "k";
532 kern_ = "kern_";
533 }
534
535 /*
536 * Write the subsystem stuff.
537 */
538 fprintf(file, "\n");
539 WriteSubsystem(file, stats);
540
541 /*
542 * Then, the server routine
543 */
544 fprintf(file, "mig_external boolean_t %s\n", ServerDemux);
545 if (BeAnsiC) {
546 if (!UseMachMsg2) {
547 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
548 } else {
549 fprintf(file, "\t(mach_msg_header_t *InHeadP, void *InDataP, mach_msg_max_trailer_t *InTrailerP,"
550 " mach_msg_header_t *OutHeadP, void *OutDataP)\n");
551 }
552 }
553 else {
554 __KernelServer_unreachable();
555 fprintf(file, "#if\t%s\n", NewCDecl);
556 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
557 fprintf(file, "#else\n");
558 fprintf(file, "\t(InHeadP, OutHeadP)\n");
559 fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
560 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
561 }
562
563 fprintf(file, "{\n");
564 fprintf(file, "\t/*\n");
565 fprintf(file, "\t * typedef struct {\n");
566 fprintf(file, "\t * \tmach_msg_header_t Head;\n");
567 fprintf(file, "\t * \tNDR_record_t NDR;\n");
568 fprintf(file, "\t * \tkern_return_t RetCode;\n");
569 fprintf(file, "\t * } mig_reply_error_t;\n");
570 fprintf(file, "\t */\n");
571 fprintf(file, "\n");
572
573 fprintf(file, "\tmig_%sroutine_t routine;\n", kern_);
574 fprintf(file, "\n");
575
576 fprintf(file, "\tOutHeadP->msgh_bits = ");
577 fprintf(file, "MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InHeadP->msgh_bits), 0);\n");
578 fprintf(file, "\tOutHeadP->msgh_remote_port = InHeadP->msgh_reply_port;\n");
579 fprintf(file, "\t/* Minimal size: routine() will update it if different */\n");
580 fprintf(file, "\tOutHeadP->msgh_size = (mach_msg_size_t)sizeof(mig_reply_error_t);\n");
581 fprintf(file, "\tOutHeadP->msgh_local_port = MACH_PORT_NULL;\n");
582 fprintf(file, "\tOutHeadP->msgh_id = InHeadP->msgh_id + 100;\n");
583 fprintf(file, "\tOutHeadP->msgh_reserved = 0;\n");
584 fprintf(file, "\n");
585
586 fprintf(file, "\tif ((InHeadP->msgh_id > %d) || (InHeadP->msgh_id < %d) ||\n", SubsystemBase + rtNumber - 1, SubsystemBase);
587 fprintf(file, "\t ((routine = %s.%sroutine[InHeadP->msgh_id - %d].%sstub_routine) == 0)) {\n", ServerSubsys, k, SubsystemBase, k);
588 fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->NDR = NDR_record;\n");
589 fprintf(file, "\t\t((mig_reply_error_t *)OutHeadP)->RetCode = MIG_BAD_ID;\n");
590 if (UseEventLogger) {
591 fprintf(file, "#if MIG_DEBUG\n");
592 fprintf(file, "\t\tLOG_ERRORS(MACH_MSG_LOG_SERVER, MACH_MSG_ERROR_UNKNOWN_ID,\n");
593 fprintf(file, "\t\t\t&InHeadP->msgh_id, __FILE__, __LINE__);\n");
594 fprintf(file, "#endif /* MIG_DEBUG */\n");
595 }
596 fprintf(file, "\t\treturn FALSE;\n");
597 fprintf(file, "\t}\n");
598
599 /* Call appropriate routine */
600 if (!UseMachMsg2)
601 fprintf(file, "\t(*routine) (InHeadP, OutHeadP);\n");
602 else
603 fprintf(file, "\t(*routine) (InHeadP, InDataP, InTrailerP, OutHeadP, OutDataP);\n");
604
605 fprintf(file, "\treturn TRUE;\n");
606 fprintf(file, "}\n");
607 fprintf(file, "\n");
608
609 /*
610 * Then, the <subsystem>_server_routine routine
611 */
612 fprintf(file, "mig_external mig_%sroutine_t %s_routine\n", kern_, ServerDemux);
613 if (BeAnsiC) {
614 fprintf(file, "\t(mach_msg_header_t *InHeadP)\n");
615 }
616 else {
617 fprintf(file, "#if\t%s\n", NewCDecl);
618 fprintf(file, "\t(mach_msg_header_t *InHeadP)\n");
619 fprintf(file, "#else\n");
620 fprintf(file, "\t(InHeadP)\n");
621 fprintf(file, "\tmach_msg_header_t *InHeadP;\n");
622 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
623 }
624
625 fprintf(file, "{\n");
626 fprintf(file, "\tint msgh_id;\n");
627 fprintf(file, "\n");
628 fprintf(file, "\tmsgh_id = InHeadP->msgh_id - %d;\n", SubsystemBase);
629 fprintf(file, "\n");
630 fprintf(file, "\tif ((msgh_id > %d) || (msgh_id < 0))\n", rtNumber - 1);
631 fprintf(file, "\t\treturn 0;\n");
632 fprintf(file, "\n");
633 fprintf(file, "\treturn %s.%sroutine[msgh_id].%sstub_routine;\n", ServerSubsys, k, k);
634 fprintf(file, "}\n");
635
636 /* symtab */
637
638 if (GenSymTab) {
639 fprintf(file,"\nmig_symtab_t _%sSymTab[] = {\n",SubsystemName);
640 WriteSymTabEntries(file,stats);
641 fprintf(file,"};\n");
642 fprintf(file,"int _%sSymTabBase = %d;\n",SubsystemName,SubsystemBase);
643 fprintf(file,"int _%sSymTabEnd = %d;\n",SubsystemName,SubsystemBase+rtNumber);
644 }
645}
646
647#if NOT_CURRENTLY_USED
648/*
649 * Returns the return type of the server-side work function.
650 * Suitable for "extern %s serverfunc()".
651 */
652static char *
653ServerSideType(routine_t *rt)
654{
655 return rt->rtRetCode->argType->itTransType;
656}
657#endif /* NOT_CURRENTLY_USED */
658
659static void
660WriteRetCode(FILE *file, argument_t *ret)
661{
662 ipc_type_t *it = ret->argType;
663
664 if (akCheck(ret->argKind, akbVarNeeded)) {
665 fprintf(file, "\t%s %s;\n", it->itTransType, ret->argVarName);
666 }
667}
668
669static void
670WriteLocalVarDecl(FILE *file, argument_t *arg)
671{
672 ipc_type_t *it = arg->argType;
673 ipc_type_t *btype = it->itElement;
674
675 if (IS_VARIABLE_SIZED_UNTYPED(it))
676 fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, btype->itNumber ? it->itNumber/btype->itNumber : 0);
677 else if (IS_MULTIPLE_KPD(it)) {
678 if (btype->itTransType != strNULL)
679 fprintf(file, "\t%s %s[%d]", btype->itTransType, arg->argVarName, it->itKPD_Number);
680 else
681 /* arrays of ool or oolport */
682 fprintf(file, "\tvoid *%s[%d]", arg->argVarName, it->itKPD_Number);
683 }
684 else
685 fprintf(file, "\t%s %s", it->itTransType, arg->argVarName);
686}
687
688#if NOT_CURRENTLY_USED
689static void
690WriteServerArgDecl(FILE *file, argument_t *arg)
691{
692 fprintf(file, "%s %s%s", arg->argType->itTransType, arg->argByReferenceServer ? "*" : "", arg->argVarName);
693}
694#endif /* NOT_CURRENTLY_USED */
695
696/*
697 * Writes the local variable declarations which are always
698 * present: InP, OutP, the server-side work function.
699 */
700static void
701WriteVarDecls(FILE *file, routine_t *rt)
702{
703 int i;
704
705 if (!UseMachMsg2) {
706 fprintf(file, "\tRequest *In0P = (Request *) InHeadP;\n");
707 for (i = 1; i <= rt->rtMaxRequestPos; i++)
708 fprintf(file, "\tRequest *In%dP;\n", i);
709 fprintf(file, "\tReply *OutP = (Reply *) OutHeadP;\n");
710 } else {
711 fprintf(file, "\tRequestK *InKP = (RequestK *) InHeadP;\n");
712 fprintf(file, "\tRequestU *In0UP = (RequestU *) InDataP;\n");
713 for (i = 1; i <= rt->rtMaxRequestPos; i++)
714 fprintf(file, "\tRequestU *In%dUP;\n", i);
715 fprintf(file, "\tReplyK *OutKP = (ReplyK *) OutHeadP;\n");
716 fprintf(file, "\tReplyU *OutUP = (ReplyU *) OutDataP;\n");
717 fprintf(file, "\t(void)OutUP;\n");
718 }
719
720 /* if reply is variable, we may need msgh_size_delta and msgh_size */
721 if (rt->rtNumReplyVar > 1)
722 fprintf(file, "\tunsigned int msgh_size;\n");
723 if (rt->rtMaxReplyPos > 0)
724 fprintf(file, "\tunsigned int msgh_size_delta;\n");
725 if (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos > 0)
726 fprintf(file, "\n");
727
728 if (rt->rtServerImpl) {
729 fprintf(file, "\tmach_msg_max_trailer_t *TrailerP;\n");
730 fprintf(file, "#if\t__MigTypeCheck\n");
731 fprintf(file, "\tunsigned int trailer_size __attribute__((unused));\n");
732 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
733 }
734 fprintf(file, "#ifdef\t__MIG_check__Request__%s_t__defined\n", rt->rtName);
735 fprintf(file, "\tkern_return_t check_result;\n");
736 fprintf(file, "#endif\t/* __MIG_check__Request__%s_t__defined */\n", rt->rtName);
737 fprintf(file, "\n");
738}
739
740static void
741WriteReplyInit(FILE *file, routine_t *rt)
742{
743 fprintf(file, "\n");
744 if (!UseMachMsg2 && (rt->rtNumReplyVar > 1 || rt->rtMaxReplyPos))
745 /* WritheAdjustMsgSize() has been executed at least once! */
746 fprintf(file, "\tOutP = (Reply *) OutHeadP;\n");
747
748 if (!rt->rtSimpleReply) /* complex reply message */
749 fprintf(file, "\t%s->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;\n", OutHeadSeg);
750
751 if (rt->rtNumReplyVar == 0) {
752 fprintf(file, "\t%s->Head.msgh_size = ", OutHeadSeg);
753 rtMinReplySize(file, rt, "Reply");
754 fprintf(file, ";\n");
755 }
756 else if (rt->rtNumReplyVar > 1)
757 fprintf(file, "\t%s->Head.msgh_size = msgh_size;\n", OutHeadSeg);
758 /* the case rt->rtNumReplyVar = 1 is taken care of in WriteAdjustMsgSize() */
759}
760
761static void
762WriteRetCArgCheckError(FILE *file, routine_t *rt)
763{
764 fprintf(file, "\tif (!(%s->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&\n", InHeadSeg);
765 fprintf(file, "\t (%s->Head.msgh_size == (mach_msg_size_t)sizeof(mig_reply_error_t)))\n", InHeadSeg);
766 fprintf(file, "\t{\n");
767}
768
769static void
770WriteRetCArgFinishError(FILE *file, routine_t *rt)
771{
772 argument_t *retcode = rt->rtRetCArg;
773
774 fprintf(file, "\treturn;\n");
775 fprintf(file, "\t}\n");
776 retcode->argMsgField = "KERN_SUCCESS";
777}
778
779static void
780WriteCheckHead(FILE *file, routine_t *rt)
781{
782 fprintf(file, "#if\t__MigTypeCheck\n");
783 if (rt->rtNumRequestVar > 0)
784 fprintf(file, "\tmsgh_size = %s->Head.msgh_size;\n", InHeadSeg);
785
786 if (rt->rtSimpleRequest) {
787 /* Expecting a simple message. */
788 fprintf(file, "\tif ((%s->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n", InHeadSeg);
789 if (rt->rtNumRequestVar > 0) {
790 fprintf(file, "\t (msgh_size < ");
791 rtMinRequestSize(file, rt, "__Request");
792 fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request)))\n");
793 }
794 else
795 fprintf(file, "\t (%s->Head.msgh_size != (mach_msg_size_t)sizeof(__Request)))\n", InHeadSeg);
796 }
797 else {
798 /* Expecting a complex message. */
799
800 fprintf(file, "\tif (");
801 if (rt->rtRetCArg != argNULL)
802 fprintf(file, "(");
803 fprintf(file, "!(%s->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n", InHeadSeg);
804 fprintf(file, "\t (%s->msgh_body.msgh_descriptor_count != %d) ||\n", InHeadSeg, rt->rtRequestKPDs);
805 if (rt->rtNumRequestVar > 0) {
806 fprintf(file, "\t (msgh_size < ");
807 rtMinRequestSize(file, rt, "__Request");
808 fprintf(file, ") || (msgh_size > (mach_msg_size_t)sizeof(__Request))");
809 }
810 else
811 fprintf(file, "\t (%s->Head.msgh_size != (mach_msg_size_t)sizeof(__Request))", InHeadSeg);
812 if (rt->rtRetCArg == argNULL)
813 fprintf(file, ")\n");
814 else {
815 fprintf(file, ") &&\n");
816 fprintf(file, "\t ((%s->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) ||\n", InHeadSeg);
817 fprintf(file, "\t %s->Head.msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||\n", InHeadSeg);
818 fprintf(file, "\t ((mig_reply_error_t *)%s)->RetCode == KERN_SUCCESS))\n", InHeadSeg);
819 }
820 }
821 fprintf(file, "\t\treturn MIG_BAD_ARGUMENTS;\n");
822 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
823 fprintf(file, "\n");
824}
825
826void
827WriteRequestNDRConvertIntRepArgCond(FILE *file, argument_t *arg)
828{
829 routine_t *rt = arg->argRoutine;
830
831 fprintf(file, "defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
832}
833
834void
835WriteRequestNDRConvertCharRepArgCond(FILE *file, argument_t *arg)
836{
837 routine_t *rt = arg->argRoutine;
838
839 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
840 fprintf(file, "defined(__NDR_convert__char_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
841 else
842 fprintf(file, "0");
843}
844
845void
846WriteRequestNDRConvertFloatRepArgCond(FILE *file, argument_t *arg)
847{
848 routine_t *rt = arg->argRoutine;
849
850 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
851 fprintf(file, "defined(__NDR_convert__float_rep__Request__%s_t__%s__defined)", rt->rtName, arg->argMsgField);
852 else
853 fprintf(file, "0");
854}
855
856void
857WriteRequestNDRConvertIntRepArgDecl(FILE *file, argument_t *arg)
858{
859 WriteNDRConvertArgDecl(file, arg, "int_rep", "Request");
860}
861
862void
863WriteRequestNDRConvertCharRepArgDecl(FILE *file, argument_t *arg)
864{
865 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
866 WriteNDRConvertArgDecl(file, arg, "char_rep", "Request");
867}
868
869void
870WriteRequestNDRConvertFloatRepArgDecl(FILE *file, argument_t *arg)
871{
872 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
873 WriteNDRConvertArgDecl(file, arg, "float_rep", "Request");
874}
875
876void
877WriteRequestNDRConvertArgUse(FILE *file, argument_t *arg, char *convert)
878{
879 routine_t *rt = arg->argRoutine;
880 argument_t *count = arg->argCount;
881 char argname[MAX_STR_LEN];
882
883 if ((akIdent(arg->argKind) == akeCount || akIdent(arg->argKind) == akeCountInOut) &&
884 (arg->argParent && akCheck(arg->argParent->argKind, akbSendNdr)))
885 return;
886
887 if (arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
888 if (count && !arg->argSameCount && !strcmp(convert, "int_rep")) {
889 fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, count->argMsgField);
890 fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&In%dP->%s, In%dP->NDR.int_rep);\n", rt->rtName, count->argMsgField, count->argRequestPos, count->argMsgField, count->argRequestPos);
891 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, count->argMsgField);
892 }
893
894 sprintf(argname, "(%s)(In%dP->%s.address)", FetchServerType(arg->argType), arg->argRequestPos, arg->argMsgField);
895 }
896 else {
897 sprintf(argname, "&In%dP->%s", arg->argRequestPos, arg->argMsgField);
898 }
899
900 fprintf(file, "#if defined(__NDR_convert__%s__Request__%s_t__%s__defined)\n", convert, rt->rtName, arg->argMsgField);
901 fprintf(file, "\t\t__NDR_convert__%s__Request__%s_t__%s(%s, In0P->NDR.%s", convert, rt->rtName, arg->argMsgField, argname, convert);
902 if (count)
903 fprintf(file, ", In%dP->%s", count->argRequestPos, count->argMsgField);
904 fprintf(file, ");\n");
905 fprintf(file, "#endif\t/* __NDR_convert__%s__Request__%s_t__%s__defined */\n", convert, rt->rtName, arg->argMsgField);
906}
907
908void
909WriteRequestNDRConvertIntRepOneArgUse(FILE *file, argument_t *arg)
910{
911 routine_t *rt = arg->argRoutine;
912 char *where = UseMachMsg2 ? "UP" : "P";
913
914 fprintf(file, "#if defined(__NDR_convert__int_rep__Request__%s_t__%s__defined)\n", rt->rtName, arg->argMsgField);
915 fprintf(file, "\tif (In0%s->NDR.int_rep != NDR_record.int_rep)\n", where);
916 fprintf(file, "\t\t__NDR_convert__int_rep__Request__%s_t__%s(&%s->%s, %s->NDR.int_rep);\n", rt->rtName,
917 arg->argMsgField, arg->argInSegment, arg->argMsgField, arg->argInSegment);
918 fprintf(file, "#endif\t/* __NDR_convert__int_rep__Request__%s_t__%s__defined */\n", rt->rtName, arg->argMsgField);
919}
920
921void
922WriteRequestNDRConvertIntRepArgUse(FILE *file, argument_t *arg)
923{
924 WriteRequestNDRConvertArgUse(file, arg, "int_rep");
925}
926
927void
928WriteRequestNDRConvertCharRepArgUse(FILE *file, argument_t *arg)
929{
930 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
931 WriteRequestNDRConvertArgUse(file, arg, "char_rep");
932}
933
934void
935WriteRequestNDRConvertFloatRepArgUse(FILE *file, argument_t *arg)
936{
937 if (akIdent(arg->argKind) != akeCount && akIdent(arg->argKind) != akeCountInOut)
938 WriteRequestNDRConvertArgUse(file, arg, "float_rep");
939}
940
941static void
942WriteCalcArgSize(FILE *file, argument_t *arg)
943{
944 ipc_type_t *ptype = arg->argType;
945
946 if (PackMsg == FALSE) {
947 fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
948 return;
949 }
950
951 if (IS_OPTIONAL_NATIVE(ptype))
952 fprintf(file, "(%s->__Present__%s ? _WALIGNSZ_(%s) : 0)" , arg->argInSegment, arg->argMsgField, ptype->itServerType);
953 else {
954 ipc_type_t *btype = ptype->itElement;
955 argument_t *count = arg->argCount;
956 int multiplier = btype->itTypeSize;
957
958 if (btype->itTypeSize % itWordAlign != 0)
959 fprintf(file, "_WALIGN_");
960 fprintf(file, "(");
961
962 if (multiplier > 1)
963 fprintf(file, "%d * ", multiplier);
964 fprintf(file, "%s->%s", count->argInSegment, count->argMsgField);
965 fprintf(file, ")");
966 }
967}
968
969static void
970WriteCheckArgSize(FILE *file, routine_t *rt, argument_t *arg, const char *comparator)
971{
972 ipc_type_t *ptype = arg->argType;
973
974
975 fprintf(file, "\tif (((msgh_size - ");
976 rtMinRequestSize(file, rt, "__Request");
977 fprintf(file, ") ");
978 if (PackMsg == FALSE) {
979 fprintf(file, "%s %d)", comparator, ptype->itTypeSize + ptype->itPadSize);
980 } else if (IS_OPTIONAL_NATIVE(ptype)) {
981 fprintf(file, "%s (%s->__Present__%s ? _WALIGNSZ_(%s) : 0))" , comparator, arg->argInSegment, arg->argMsgField, ptype->itServerType);
982 } else {
983 ipc_type_t *btype = ptype->itElement;
984 argument_t *count = arg->argCount;
985 int multiplier = btype->itTypeSize;
986
987 if (multiplier > 1)
988 fprintf(file, "/ %d ", multiplier);
989 fprintf(file, "< %s->%s) ||\n", count->argInSegment, count->argMsgField);
990 fprintf(file, "\t (msgh_size %s ", comparator);
991 rtMinRequestSize(file, rt, "__Request");
992 fprintf(file, " + ");
993 WriteCalcArgSize(file, arg);
994 fprintf(file, ")");
995 }
996 fprintf(file, ")\n\t\treturn MIG_BAD_ARGUMENTS;\n");
997}
998
999static void
1000WriteCheckMsgSize(FILE *file, argument_t *arg)
1001{
1002 routine_t *rt = arg->argRoutine;
1003 ipc_type_t *it = arg->argType;
1004 ipc_type_t *btype = it->itElement;
1005
1006 if (arg->argCount && !arg->argSameCount)
1007 WriteRequestNDRConvertIntRepOneArgUse(file, arg->argCount);
1008 if (arg->argRequestPos == rt->rtMaxRequestPos) {
1009 fprintf(file, "#if\t__MigTypeCheck\n");
1010
1011 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
1012 fprintf(file, "\t" "if (%s->%s > %d)\n", arg->argCount->argInSegment,
1013 arg->argCount->argMsgField, it->itNumber/btype->itNumber);
1014 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file);
1015 /* ...end... */
1016
1017 WriteCheckArgSize(file, rt, arg, "!=");
1018
1019 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
1020 }
1021 else {
1022 /* If there aren't any more variable-sized arguments after this,
1023 then we must check for exact msg-size and we don't need to
1024 update msgh_size. */
1025
1026 boolean_t LastVarArg = arg->argRequestPos+1 == rt->rtNumRequestVar;
1027
1028 /* calculate the actual size in bytes of the data field. note
1029 that this quantity must be a multiple of four. hence, if
1030 the base type size isn't a multiple of four, we have to
1031 round up. note also that btype->itNumber must
1032 divide btype->itTypeSize (see itCalculateSizeInfo). */
1033
1034 fprintf(file, "\tmsgh_size_delta = ");
1035 WriteCalcArgSize(file, arg);
1036 fprintf(file, ";\n");
1037 fprintf(file, "#if\t__MigTypeCheck\n");
1038
1039 /* verify that the user-code-provided count does not exceed the maximum count allowed by the type. */
1040 fprintf(file, "\t" "if (%s->%s > %d)\n", arg->argCount->argInSegment,
1041 arg->argCount->argMsgField, it->itNumber/btype->itNumber);
1042 fputs("\t\t" "return MIG_BAD_ARGUMENTS;\n", file);
1043 /* ...end... */
1044
1045 /* Don't decrement msgh_size until we've checked that
1046 it won't underflow. */
1047 WriteCheckArgSize(file, rt, arg, LastVarArg ? "!=" : "<");
1048
1049 if (!LastVarArg)
1050 fprintf(file, "\tmsgh_size -= msgh_size_delta;\n");
1051
1052 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
1053 }
1054 fprintf(file, "\n");
1055}
1056
1057static char *
1058InArgMsgField(argument_t *arg, char *str)
1059{
1060 static char buffer[MAX_STR_LEN];
1061 char who[20] = {0};
1062
1063 /*
1064 * Inside the kernel, the request and reply port fields
1065 * really hold ipc_port_t values, not mach_port_t values.
1066 * Hence we must cast the values.
1067 */
1068
1069 if (!(arg->argFlags & flRetCode)) {
1070 if (akCheck(arg->argKind, akbServerImplicit))
1071 sprintf(who, "TrailerP->");
1072 else
1073 sprintf(who, "%s->", arg->argInSegment);
1074 }
1075
1076#ifdef MIG_KERNEL_PORT_CONVERSION
1077 if (IsKernelServer &&
1078 ((akIdent(arg->argKind) == akeRequestPort) ||
1079 (akIdent(arg->argKind) == akeReplyPort)))
1080 sprintf(buffer, "(ipc_port_t) %s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
1081 else
1082#endif
1083 sprintf(buffer, "%s%s%s", who, str, (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField);
1084
1085 return buffer;
1086}
1087
1088static void
1089WriteExtractArgValue(FILE *file, argument_t *arg)
1090{
1091 ipc_type_t *it = arg->argType;
1092 string_t recast;
1093
1094#ifdef MIG_KERNEL_PORT_CONVERSION
1095 if (IsKernelServer && it->itPortType && streql(it->itServerType, "ipc_port_t")
1096 && akIdent(arg->argKind) != akeRequestPort
1097 && akIdent(arg->argKind) != akeReplyPort)
1098 recast = "(mach_port_t)";
1099 else
1100#endif
1101 recast = "";
1102 if (it->itInTrans != strNULL)
1103 WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s(%s%s)", arg->argVarName, it->itInTrans, recast, InArgMsgField(arg, ""));
1104 else
1105 WriteCopyType(file, it, FALSE, "%s", "/* %s */ %s%s", arg->argVarName, recast, InArgMsgField(arg, ""));
1106
1107 fprintf(file, "\n");
1108}
1109
1110/*
1111 * argKPD_Extract discipline for Port types.
1112 */
1113static void
1114WriteExtractKPD_port(FILE *file, argument_t *arg)
1115{
1116 ipc_type_t *it = arg->argType;
1117 char *recast = "";
1118
1119 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
1120 /* translation function do not apply to complex types */
1121#ifdef MIG_KERNEL_PORT_CONVERSION
1122 if (IsKernelServer)
1123 recast = "(mach_port_t)";
1124#endif
1125 fprintf(file, "\t\t%s[i] = %sptr->name;\n", arg->argVarName, recast);
1126 fprintf(file, "\t}\n");
1127}
1128
1129/*
1130 * argKPD_Extract discipline for out-of-line types.
1131 */
1132static void
1133WriteExtractKPD_ool(FILE *file, argument_t *arg)
1134{
1135 ipc_type_t *it = arg->argType;
1136
1137 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
1138 fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
1139 fprintf(file, "\t}\n");
1140}
1141
1142/*
1143 * argKPD_Extract discipline for out-of-line Port types.
1144 */
1145static void
1146WriteExtractKPD_oolport(FILE *file, argument_t *arg)
1147{
1148 ipc_type_t *it = arg->argType;
1149
1150 WriteKPD_Iterator(file, TRUE, it->itVarArray, arg, FALSE);
1151 fprintf(file, "\t\t%s[i] = ptr->address;\n", arg->argVarName);
1152 fprintf(file, "\t}\n");
1153 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbSendRcv)) {
1154 argument_t *poly = arg->argPoly;
1155 char *pref = poly->argByReferenceServer ? "*" : "";
1156
1157 fprintf(file, "\t%s%s = %s->%s[0].disposition;\n", pref, poly->argVarName, arg->argInSegment, arg->argMsgField);
1158 }
1159}
1160
1161
1162static void
1163WriteInitializeCount(FILE *file, argument_t *arg)
1164{
1165 ipc_type_t *ptype = arg->argParent->argType;
1166 ipc_type_t *btype = ptype->itElement;
1167 char newstr[MAX_STR_LEN];
1168
1169 /*
1170 * Initialize 'count' argument for variable-length inline OUT parameter
1171 * with maximum allowed number of elements.
1172 */
1173
1174 if (akCheck(arg->argKind, akbVarNeeded))
1175 sprintf(newstr, "%s", arg->argMsgField);
1176 else
1177 sprintf(newstr, "%s->%s", arg->argOutSegment, arg->argMsgField);
1178
1179 fprintf(file, "\t%s = ", newstr);
1180 if (IS_MULTIPLE_KPD(ptype))
1181 fprintf(file, "%d;\n", ptype->itKPD_Number);
1182 else
1183 fprintf(file, "%d;\n", btype->itNumber? ptype->itNumber/btype->itNumber : 0);
1184
1185 /*
1186 * If the user passed in a count, then we use the minimum.
1187 * We can't let the user completely override our maximum,
1188 * or the user might convince the server to overwrite the buffer.
1189 */
1190
1191 if (arg->argCInOut != argNULL) {
1192 char *msgfield = InArgMsgField(arg->argCInOut, "");
1193
1194 fprintf(file, "\tif (%s < %s)\n", msgfield, newstr);
1195 fprintf(file, "\t\t%s = %s;\n", newstr, msgfield);
1196 }
1197
1198 fprintf(file, "\n");
1199}
1200
1201static void
1202WriteAdjustRequestMsgPtr(FILE *file, argument_t *arg)
1203{
1204 ipc_type_t *ptype = arg->argType;
1205 char *where = UseMachMsg2 ? "UP" : "P";
1206 char *castType = UseMachMsg2 ? "__RequestU" : "__Request";
1207
1208 if (PackMsg == FALSE) {
1209 fprintf(file, "\t*In%d%sP = In%d%s = (%s *) ((pointer_t) %s);\n\n",
1210 arg->argRequestPos+1, where, arg->argRequestPos+1, where, castType, arg->argInSegment);
1211 return;
1212 }
1213
1214 fprintf(file, "\t*In%d%sP = In%d%s = (%s *) ((pointer_t) %s + msgh_size_delta - ",
1215 arg->argRequestPos+1, where, arg->argRequestPos+1, where, castType, arg->argInSegment);
1216 if (IS_OPTIONAL_NATIVE(ptype))
1217 fprintf(file, "_WALIGNSZ_(%s)", ptype->itUserType);
1218 else
1219 fprintf(file, "%d", ptype->itTypeSize + ptype->itPadSize);
1220 fprintf(file, ");\n\n");
1221}
1222
1223static void
1224WriteCheckRequestTrailerArgs(FILE *file, routine_t *rt)
1225{
1226 argument_t *arg;
1227
1228 if (rt->rtServerImpl)
1229 WriteCheckTrailerHead(file, rt, FALSE);
1230
1231 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
1232 if (akCheck(arg->argKind, akbServerImplicit))
1233 WriteCheckTrailerSize(file, FALSE, arg);
1234 }
1235}
1236
1237static void
1238WriteExtractArg(FILE *file, argument_t *arg)
1239{
1240 if (akCheckAll(arg->argKind, akbSendRcv|akbVarNeeded)) {
1241 if (akCheck(arg->argKind, akbSendKPD))
1242 (*arg->argKPD_Extract)(file, arg);
1243 else
1244 WriteExtractArgValue(file, arg);
1245 }
1246
1247 if ((akIdent(arg->argKind) == akeCount) &&
1248 akCheck(arg->argKind, akbReturnSnd)) {
1249
1250 ipc_type_t *ptype = arg->argParent->argType;
1251 /*
1252 * the count will be initialized to 0 in the case of
1253 * unbounded arrays (MigInLine = TRUE): this is because
1254 * the old interface used to pass to the target procedure
1255 * the maximum in-line size (it was 2048 bytes)
1256 */
1257 if (IS_VARIABLE_SIZED_UNTYPED(ptype) ||
1258 IS_MIG_INLINE_EMUL(ptype) ||
1259 (IS_MULTIPLE_KPD(ptype) && ptype->itVarArray))
1260 WriteInitializeCount(file, arg);
1261 }
1262}
1263
1264static void
1265WriteServerCallArg(FILE *file, argument_t *arg)
1266{
1267 ipc_type_t *it = arg->argType;
1268 boolean_t NeedClose = FALSE;
1269 u_int elemsize = 0;
1270 string_t at = (arg->argByReferenceServer ||
1271 it->itNativePointer) ? "&" : "";
1272 string_t star = (arg->argByReferenceServer) ? " *" : "";
1273 string_t msgfield =
1274 (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField;
1275
1276 if ((it->itInTrans != strNULL) &&
1277 akCheck(arg->argKind, akbSendRcv) &&
1278 !akCheck(arg->argKind, akbVarNeeded)) {
1279 fprintf(file, "%s%s(", at, it->itInTrans);
1280 NeedClose = TRUE;
1281 }
1282
1283 if (akCheckAll(arg->argKind, akbVarNeeded|akbServerArg))
1284 fprintf(file, "%s%s", at, arg->argVarName);
1285 else if (akCheckAll(arg->argKind, akbSendRcv|akbSendKPD)) {
1286 if (!it->itInLine)
1287 /* recast the void *, although it is not necessary */
1288 fprintf(file, "(%s%s)%s(%s)", it->itTransType, star, at, InArgMsgField(arg, ""));
1289 else
1290#ifdef MIG_KERNEL_PORT_CONVERSION
1291 if (IsKernelServer && streql(it->itServerType, "ipc_port_t"))
1292 /* recast the port to the kernel internal form value */
1293 fprintf(file, "(ipc_port_t%s)%s(%s)", star, at, InArgMsgField(arg, ""));
1294 else
1295#endif
1296 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1297 }
1298 else if (akCheck(arg->argKind, akbSendRcv)) {
1299 if (IS_OPTIONAL_NATIVE(it)) {
1300 fprintf(file, "(%s ? ", InArgMsgField(arg, "__Present__"));
1301 fprintf(file, "%s%s.__Real__%s : %s)", at, InArgMsgField(arg, ""), arg->argMsgField, it->itBadValue);
1302 }
1303 else {
1304 if (akIdent(arg->argKind) == akeCount && arg->argParent) {
1305 char *suffix = arg->argParent->argSuffix;
1306 ipc_type_t *elemType = arg->argParent->argType->itElement;
1307 /* temporarily squash any name suffix such as ".address" (we'll be adding our own) */
1308 arg->argParent->argSuffix = NULL;
1309 switch (arg->argParent->argKPD_Type) {
1310 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
1311 /* count of the number of descriptors */
1312 fprintf(file, "%s%s.count", at, InArgMsgField(arg->argParent, ""));
1313 break;
1314 case MACH_MSG_OOL_DESCRIPTOR:
1315 /* descriptor buffer size / element size */
1316 if (!(arg->argByReferenceServer || it->itNativePointer)) {
1317 fprintf(file, "%s%s.size", at, InArgMsgField(arg->argParent, ""));
1318 elemsize = ((elemType->itNumber * elemType->itSize) + 7) / 8;
1319 if (elemsize > 1) {
1320 fprintf(file, " / %d", elemsize);
1321 }
1322 } else {
1323 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1324 }
1325 break;
1326 default:
1327 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1328 break;
1329 }
1330 arg->argParent->argSuffix = suffix;
1331 } else {
1332 fprintf(file, "%s%s", at, InArgMsgField(arg, ""));
1333 }
1334 }
1335 }
1336 else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD)) {
1337 if (!it->itInLine)
1338 /* recast the void *, although it is not necessary */
1339 fprintf(file, "(%s%s)%s(%s->%s)", it->itTransType, star, at, arg->argOutSegment, msgfield);
1340 else
1341#ifdef MIG_KERNEL_PORT_CONVERSION
1342 if (IsKernelServer && streql(it->itServerType, "ipc_port_t"))
1343 /* recast the port to the kernel internal form value */
1344 fprintf(file, "(mach_port_t%s)%s(%s->%s)", star, at, arg->argOutSegment, msgfield);
1345 else
1346#endif
1347 fprintf(file, "%s%s->%s", at, arg->argOutSegment, msgfield);
1348
1349 }
1350 else if (akCheck(arg->argKind, akbReturnSnd))
1351 fprintf(file, "%s%s->%s", at, arg->argOutSegment, msgfield);
1352
1353 if (NeedClose)
1354 fprintf(file, ")");
1355}
1356
1357/*
1358 * Shrunk version of WriteServerCallArg, to implement the RetCode functionality:
1359 * we have received a mig_reply_error_t, therefore we want to call the target
1360 * routine with all 0s except for the error code (and the implicit data).
1361 * We know that we are a SimpleRoutine.
1362 */
1363static void
1364WriteConditionalCallArg(FILE *file, argument_t *arg)
1365{
1366 ipc_type_t *it = arg->argType;
1367 boolean_t NeedClose = FALSE;
1368
1369 if ((it->itInTrans != strNULL) &&
1370 akCheck(arg->argKind, akbSendRcv) &&
1371 !akCheck(arg->argKind, akbVarNeeded)) {
1372 fprintf(file, "%s(", it->itInTrans);
1373 NeedClose = TRUE;
1374 }
1375
1376 if (akCheck(arg->argKind, akbSendRcv)) {
1377 if (akIdent(arg->argKind) == akeRequestPort ||
1378 akCheck(arg->argKind, akbServerImplicit))
1379 fprintf(file, "%s", InArgMsgField(arg, ""));
1380 else if (akIdent(arg->argKind) == akeRetCode) {
1381 assert(arg->argRequestPos == 0);
1382 fprintf(file, "((mig_reply_error_t *)%s)->RetCode", arg->argInSegment);
1383 } else
1384 fprintf(file, "(%s)(0)", it->itTransType);
1385 }
1386
1387 if (NeedClose)
1388 fprintf(file, ")");
1389}
1390
1391static void
1392WriteDestroyArg(FILE *file, argument_t *arg)
1393{
1394 ipc_type_t *it = arg->argType;
1395
1396 /*
1397 * Deallocate IN/INOUT out-of-line args if specified by "auto" flag.
1398 *
1399 * We also have to deallocate in the cases where the target routine
1400 * is given a itInLine semantic whereas the underlying transmission
1401 * was out-of-line
1402 */
1403 if ((argIsIn(arg) && akCheck(arg->argKind, akbSendKPD|akbReturnKPD) &&
1404 arg->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR &&
1405 (arg->argFlags & flAuto))
1406 ||
1407 IS_MIG_INLINE_EMUL(it)
1408 ) {
1409 /*
1410 * Deallocate only if out-of-line.
1411 */
1412 argument_t *count = arg->argCount;
1413 ipc_type_t *btype = it->itElement;
1414 int multiplier = btype->itNumber ? btype->itSize / (8 * btype->itNumber) : 0;
1415
1416 if (IsKernelServer) {
1417 fprintf(file, "#if __MigKernelSpecificCode\n");
1418 fprintf(file, "\tvm_map_copy_discard(%s);\n", InArgMsgField(arg, ""));
1419 fprintf(file, "#else\n");
1420 }
1421 fprintf(file, "\tmig_deallocate((vm_offset_t) %s, ", InArgMsgField(arg, ""));
1422 if (it->itVarArray) {
1423 char *suffix = arg->argSuffix;
1424 /*
1425 * temporarily squash any name suffix such as ".address"
1426 * (we'll be adding our own)
1427 */
1428 arg->argSuffix = NULL;
1429 switch (arg->argKPD_Type) {
1430 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
1431 if (multiplier > 1) {
1432 fprintf(file, "%d * ", multiplier);
1433 }
1434 fprintf(file, "%s.count);\n", InArgMsgField(arg, ""));
1435 break;
1436 case MACH_MSG_OOL_DESCRIPTOR:
1437 fprintf(file, "%s.size);\n", InArgMsgField(arg, ""));
1438 break;
1439 default:
1440 if (multiplier > 1) {
1441 fprintf(file, "%d * ", multiplier);
1442 }
1443 fprintf(file, "%s);\n", InArgMsgField(count, ""));
1444 break;
1445 }
1446 arg->argSuffix = suffix;
1447 }
1448 else
1449 fprintf(file, "%d);\n", (it->itNumber * it->itSize + 7) / 8);
1450 if (IsKernelServer) {
1451 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1452 }
1453 fprintf(file, "\t%s = (void *) 0;\n", InArgMsgField(arg, ""));
1454 fprintf(file, "\t%s->%s.%s = (mach_msg_size_t) 0;\n", arg->argInSegment,
1455 arg->argMsgField, (RPCPortArray(arg) ? "count" : "size"));
1456 }
1457 else {
1458 if (akCheck(arg->argKind, akbVarNeeded))
1459 fprintf(file, "\t%s(%s);\n", it->itDestructor, arg->argVarName);
1460 else
1461 fprintf(file, "\t%s(%s);\n", it->itDestructor, InArgMsgField(arg, ""));
1462 }
1463}
1464
1465static void
1466WriteDestroyPortArg(FILE *file, argument_t *arg)
1467{
1468 ipc_type_t *it = arg->argType;
1469
1470 /*
1471 * If a translated port argument occurs in the body of a request
1472 * message, and the message is successfully processed, then the
1473 * port right should be deallocated. However, the called function
1474 * didn't see the port right; it saw the translation. So we have
1475 * to release the port right for it.
1476 *
1477 * The test over it->itInTrans will exclude any complex type
1478 * made out of ports
1479 */
1480 if ((it->itInTrans != strNULL) &&
1481 (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) {
1482 fprintf(file, "\tipc_port_release_send((ipc_port_t)%s);\n", InArgMsgField(arg, ""));
1483 }
1484}
1485
1486/*
1487 * Check whether WriteDestroyPortArg would generate any code for arg.
1488 */
1489boolean_t
1490CheckDestroyPortArg(argument_t *arg)
1491{
1492 ipc_type_t *it = arg->argType;
1493
1494 if ((it->itInTrans != strNULL) &&
1495 (it->itOutName == MACH_MSG_TYPE_PORT_SEND)) {
1496 return TRUE;
1497 }
1498 return FALSE;
1499}
1500
1501static void
1502WriteServerCall(FILE *file, routine_t *rt, void (*func)(FILE *, argument_t *))
1503{
1504 argument_t *arg = rt->rtRetCode;
1505 ipc_type_t *it = arg->argType;
1506 boolean_t NeedClose = FALSE;
1507
1508 fprintf(file, "\t");
1509 if (akCheck(arg->argKind, akbVarNeeded))
1510 fprintf(file, "%s = ", arg->argMsgField);
1511 else
1512 fprintf(file, "%s->%s = ", arg->argOutSegment, arg->argMsgField);
1513 if (it->itOutTrans != strNULL) {
1514 fprintf(file, "%s(", it->itOutTrans);
1515 NeedClose = TRUE;
1516 }
1517 fprintf(file, "%s(", rt->rtServerName);
1518 WriteList(file, rt->rtArgs, func, akbServerArg, ", ", "");
1519 if (NeedClose)
1520 fprintf(file, ")");
1521 fprintf(file, ");\n");
1522}
1523
1524static void
1525WriteCheckReturnValue(FILE *file, routine_t *rt)
1526{
1527 argument_t *arg = rt->rtRetCode;
1528 char string[MAX_STR_LEN];
1529
1530 if (akCheck(arg->argKind, akbVarNeeded))
1531 sprintf(string, "%s", arg->argMsgField);
1532 else
1533 sprintf(string, "%s->%s", arg->argOutSegment, arg->argMsgField);
1534 fprintf(file, "\tif (%s != KERN_SUCCESS) {\n", string);
1535 fprintf(file, "\t\tMIG_RETURN_ERROR(%s, %s);\n", OutHeadSeg, string);
1536 fprintf(file, "\t}\n");
1537}
1538
1539/*
1540 * WriteInitKPD_port, WriteInitKPD_ool, WriteInitKPD_oolport
1541 * initializes the OutP KPD fields (this job cannot be done once
1542 * the target routine has been called, otherwise informations
1543 * would be lost)
1544 */
1545/*
1546 * argKPD_Init discipline for Port types.
1547 */
1548static void
1549WriteInitKPD_port(FILE *file, argument_t *arg)
1550{
1551 ipc_type_t *it = arg->argType;
1552 char *subindex = "";
1553 boolean_t close = FALSE;
1554 char firststring[MAX_STR_LEN];
1555 char string[MAX_STR_LEN];
1556
1557 if (IS_MULTIPLE_KPD(it)) {
1558 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
1559 (void)sprintf(firststring, "\t*ptr");
1560 (void)sprintf(string, "\tptr->");
1561 subindex = "[i]";
1562 close = TRUE;
1563 }
1564 else {
1565 (void)sprintf(firststring, "%s->%s", arg->argOutSegment, arg->argMsgField);
1566 (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
1567 }
1568
1569 fprintf(file, "#if\tUseStaticTemplates\n");
1570 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1571 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1572 if (IS_MULTIPLE_KPD(it) && it->itVarArray)
1573 fprintf(file, "\t%sname = MACH_PORT_NULL;\n", string);
1574 if (arg->argPoly == argNULL) {
1575 if (IsKernelServer) {
1576 fprintf(file, "#if __MigKernelSpecificCode\n");
1577 fprintf(file, "\t%sdisposition = %s;\n", string, it->itOutNameStr);
1578 fprintf(file, "#else\n");
1579 }
1580 fprintf(file, "\t%sdisposition = %s;\n", string, it->itInNameStr);
1581 if (IsKernelServer)
1582 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1583 }
1584 fprintf(file, "#if !(defined(KERNEL) && defined(__LP64__))\n");
1585 fprintf(file, "\t%spad1 = 0;\n", string);
1586 fprintf(file, "#endif\n");
1587 fprintf(file, "\t%spad2 = 0;\n", string);
1588 fprintf(file, "\t%stype = MACH_MSG_PORT_DESCRIPTOR;\n", string);
1589 fprintf(file, "#if defined(KERNEL)\n");
1590 fprintf(file, "\t%spad_end = 0;\n", string);
1591 fprintf(file, "#endif\n");
1592 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1593 if (close)
1594 fprintf(file, "\t }\n\t}\n");
1595 fprintf(file, "\n");
1596}
1597
1598/*
1599 * argKPD_Init discipline for out-of-line types.
1600 */
1601static void
1602WriteInitKPD_ool(FILE *file, argument_t *arg)
1603{
1604 ipc_type_t *it = arg->argType;
1605 char firststring[MAX_STR_LEN];
1606 char string[MAX_STR_LEN];
1607 boolean_t VarArray;
1608 u_int howmany, howbig;
1609
1610 if (IS_MULTIPLE_KPD(it)) {
1611 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
1612 (void)sprintf(firststring, "\t*ptr");
1613 (void)sprintf(string, "\tptr->");
1614 VarArray = it->itElement->itVarArray;
1615 howmany = it->itElement->itNumber;
1616 howbig = it->itElement->itSize;
1617 }
1618 else {
1619 (void)sprintf(firststring, "%s->%s", arg->argOutSegment, arg->argMsgField);
1620 (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
1621 VarArray = it->itVarArray;
1622 howmany = it->itNumber;
1623 howbig = it->itSize;
1624 }
1625
1626 fprintf(file, "#if\tUseStaticTemplates\n");
1627 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1628 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1629 if (!VarArray)
1630 fprintf(file, "\t%ssize = %d;\n", string, (howmany * howbig + 7)/8);
1631 if (arg->argDeallocate != d_MAYBE)
1632 fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
1633 fprintf(file, "\t%scopy = %s;\n", string, (arg->argFlags & flPhysicalCopy) ? "MACH_MSG_PHYSICAL_COPY" : "MACH_MSG_VIRTUAL_COPY");
1634#ifdef ALIGNMENT
1635 fprintf(file, "\t%salignment = MACH_MSG_ALIGN_%d;\n", string, arg->argMsgField, (howbig < 8) ? 1 : howbig / 8);
1636#endif
1637 fprintf(file, "\t%spad1 = 0;\n", string);
1638 fprintf(file, "\t%stype = MACH_MSG_OOL_DESCRIPTOR;\n", string);
1639 fprintf(file, "#if defined(KERNEL) && !defined(__LP64__)\n");
1640 fprintf(file, "\t%spad_end = 0;\n", string);
1641 fprintf(file, "#endif\n");
1642 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1643
1644 if (IS_MULTIPLE_KPD(it))
1645 fprintf(file, "\t }\n\t}\n");
1646 fprintf(file, "\n");
1647}
1648
1649/*
1650 * argKPD_Init discipline for out-of-line Port types.
1651 */
1652static void
1653WriteInitKPD_oolport(FILE *file, argument_t *arg)
1654{
1655 ipc_type_t *it = arg->argType;
1656 boolean_t VarArray;
1657 ipc_type_t *howit;
1658 u_int howmany;
1659 char firststring[MAX_STR_LEN];
1660 char string[MAX_STR_LEN];
1661
1662 if (IS_MULTIPLE_KPD(it)) {
1663 WriteKPD_Iterator(file, FALSE, FALSE, arg, TRUE);
1664 (void)sprintf(firststring, "\t*ptr");
1665 (void)sprintf(string, "\tptr->");
1666 VarArray = it->itElement->itVarArray;
1667 howmany = it->itElement->itNumber;
1668 howit = it->itElement;
1669 }
1670 else {
1671 (void)sprintf(firststring, "%s->%s", arg->argOutSegment, arg->argMsgField);
1672 (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
1673 VarArray = it->itVarArray;
1674 howmany = it->itNumber;
1675 howit = it;
1676 }
1677
1678 fprintf(file, "#if\tUseStaticTemplates\n");
1679 fprintf(file, "\t%s = %s;\n", firststring, arg->argTTName);
1680 fprintf(file, "#else\t/* UseStaticTemplates */\n");
1681
1682 if (!VarArray)
1683 fprintf(file, "\t%scount = %d;\n", string, howmany);
1684 if (arg->argPoly == argNULL) {
1685 if (IsKernelServer) {
1686 fprintf(file, "#if\t__MigKernelSpecificCode\n");
1687 fprintf(file, "\t%sdisposition = %s;\n", string, howit->itOutNameStr);
1688 fprintf(file, "#else\n");
1689 }
1690 fprintf(file, "\t%sdisposition = %s;\n", string, howit->itInNameStr);
1691 if (IsKernelServer)
1692 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1693 }
1694 if (arg->argDeallocate != d_MAYBE)
1695 fprintf(file, "\t%sdeallocate = %s;\n", string, (arg->argDeallocate == d_YES) ? "TRUE" : "FALSE");
1696 fprintf(file, "\t%stype = MACH_MSG_OOL_PORTS_DESCRIPTOR;\n", string);
1697 fprintf(file, "#endif\t/* UseStaticTemplates */\n");
1698
1699 if (IS_MULTIPLE_KPD(it))
1700 fprintf(file, "\t }\n\t}\n");
1701 fprintf(file, "\n");
1702}
1703
1704static void
1705WriteInitKPDValue(FILE *file, argument_t *arg)
1706{
1707 (*arg->argKPD_Init)(file, arg);
1708}
1709
1710static void
1711WriteAdjustMsgCircular(FILE *file, argument_t *arg)
1712{
1713 fprintf(file, "\n");
1714
1715 fprintf(file,"#if\t__MigKernelSpecificCode\n");
1716 if (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)
1717 fprintf(file, "\tif (%s == MACH_MSG_TYPE_PORT_RECEIVE)\n", arg->argPoly->argVarName);
1718
1719 /*
1720 * The carried port right can be accessed in OutP->XXXX. Normally
1721 * the server function stuffs it directly there. If it is InOut,
1722 * then it has already been copied into the reply message.
1723 * If the server function deposited it into a variable (perhaps
1724 * because the reply message is variable-sized) then it has already
1725 * been copied into the reply message.
1726 *
1727 * The old MiG does not check for circularity in the case of
1728 * array of ports. So do I ...
1729 */
1730
1731 fprintf(file, "\t if (IP_VALID((ipc_port_t) %s->Head.msgh_reply_port) &&\n", InHeadSeg);
1732 fprintf(file, "\t IP_VALID((ipc_port_t) %s->%s.name) &&\n", arg->argOutSegment, arg->argMsgField);
1733 fprintf(file, "\t ipc_port_check_circularity((ipc_port_t) %s->%s.name, (ipc_port_t) %s->Head.msgh_reply_port))\n",
1734 arg->argOutSegment, arg->argMsgField, InHeadSeg);
1735 fprintf(file, "\t\t%s->Head.msgh_bits |= MACH_MSGH_BITS_CIRCULAR;\n", OutHeadSeg);
1736 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
1737}
1738
1739/*
1740 * argKPD_Pack discipline for Port types.
1741 */
1742static void
1743WriteKPD_port(FILE *file, argument_t *arg)
1744{
1745 ipc_type_t *it = arg->argType;
1746 char *subindex = "";
1747 char *recast = "";
1748 boolean_t close = FALSE;
1749 char string[MAX_STR_LEN];
1750 ipc_type_t *real_it;
1751
1752 if (akCheck(arg->argKind, akbVarNeeded)) {
1753 if (IS_MULTIPLE_KPD(it)) {
1754 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
1755 (void)sprintf(string, "\tptr->");
1756 subindex = "[i]";
1757 close = TRUE;
1758 real_it = it->itElement;
1759 }
1760 else {
1761 (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
1762 real_it = it;
1763 }
1764#ifdef MIG_KERNEL_PORT_CONVERSIONS
1765 if (IsKernelServer && streql(real_it->itTransType, "ipc_port_t"))
1766 recast = "(mach_port_t)";
1767#endif
1768
1769 if (it->itOutTrans != strNULL && !close)
1770 fprintf(file, "\t%sname = (mach_port_t)%s(%s);\n", string, it->itOutTrans, arg->argVarName);
1771 else
1772 fprintf(file, "\t%sname = %s%s%s;\n", string, recast, arg->argVarName, subindex);
1773 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd)) {
1774 argument_t *poly = arg->argPoly;
1775
1776 if (akCheck(arg->argPoly->argKind, akbVarNeeded))
1777 fprintf(file, "\t%sdisposition = %s;\n", string, poly->argVarName);
1778 else if (close)
1779 fprintf(file, "\t%sdisposition = %s->%s;\n", string, poly->argOutSegment, poly->argSuffix);
1780 }
1781 if (close)
1782 fprintf(file, "\t }\n\t}\n");
1783 fprintf(file, "\n");
1784 }
1785 else if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd|akbVarNeeded))
1786 fprintf(file, "\t%s->%s.disposition = %s;\n", arg->argOutSegment, arg->argMsgField, arg->argPoly->argVarName);
1787 /*
1788 * If this is a KernelServer, and the reply message contains
1789 * a receive right, we must check for the possibility of a
1790 * port/message circularity. If queueing the reply message
1791 * would cause a circularity, we mark the reply message
1792 * with the circular bit.
1793 */
1794 if (IsKernelServer && !(IS_MULTIPLE_KPD(it)) &&
1795 ((arg->argType->itOutName == MACH_MSG_TYPE_PORT_RECEIVE) ||
1796 (arg->argType->itOutName == MACH_MSG_TYPE_POLYMORPHIC)))
1797 WriteAdjustMsgCircular(file, arg);
1798}
1799
1800/*
1801 * argKPD_Pack discipline for out-of-line types.
1802 */
1803static void
1804WriteKPD_ool(FILE *file, argument_t *arg)
1805{
1806 ipc_type_t *it = arg->argType;
1807 char string[MAX_STR_LEN];
1808 boolean_t VarArray;
1809 argument_t *count;
1810 u_int howbig;
1811 char *subindex;
1812
1813 if (IS_MULTIPLE_KPD(it)) {
1814 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
1815 (void)sprintf(string, "\tptr->");
1816 VarArray = it->itElement->itVarArray;
1817 count = arg->argSubCount;
1818 howbig = it->itElement->itSize;
1819 subindex = "[i]";
1820 }
1821 else {
1822 (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
1823 VarArray = it->itVarArray;
1824 count = arg->argCount;
1825 howbig = it->itSize;
1826 subindex = "";
1827 }
1828
1829 if (akCheck(arg->argKind, akbVarNeeded))
1830 fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex);
1831 if (arg->argDealloc != argNULL)
1832 if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
1833 fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName);
1834 if (VarArray) {
1835 fprintf(file, "\t%ssize = ", string);
1836 if (akCheck(count->argKind, akbVarNeeded))
1837 fprintf(file, "%s%s", count->argName, subindex);
1838 else if (akCheck(arg->argKind, akbReplyCopy))
1839 /* Fixed an ancient bug here, first %s should be the position of count, not arg */
1840 fprintf(file, "%s->%s%s", count->argInSegment, count->argMsgField, subindex);
1841 else
1842 fprintf(file, "%s->%s%s", count->argOutSegment, count->argMsgField, subindex);
1843
1844 if (count->argMultiplier > 1 || howbig > 8)
1845 fprintf(file, " * %d;\n", count->argMultiplier * howbig / 8);
1846 else
1847 fprintf(file, ";\n");
1848 }
1849
1850 if (IS_MULTIPLE_KPD(it)) {
1851 fprintf(file, "\t }\n");
1852 if (it->itVarArray && !it->itElement->itVarArray) {
1853 fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number);
1854 /* since subordinate arrays aren't variable, they are initialized from template:
1855 here we must no-op 'em */
1856 fprintf(file, "\t\tptr->size = 0;\n");
1857 }
1858 fprintf(file, "\t}\n");
1859 }
1860 fprintf(file, "\n");
1861}
1862
1863/*
1864 * argKPD_Pack discipline for out-of-line Port types.
1865 */
1866static void
1867WriteKPD_oolport(FILE *file, argument_t *arg)
1868{
1869 ipc_type_t *it = arg->argType;
1870 boolean_t VarArray;
1871 argument_t *count;
1872 char *subindex, string[MAX_STR_LEN];
1873
1874 if (IS_MULTIPLE_KPD(it)) {
1875 WriteKPD_Iterator(file, FALSE, it->itVarArray, arg, TRUE);
1876 (void)sprintf(string, "\tptr->");
1877 VarArray = it->itElement->itVarArray;
1878 count = arg->argSubCount;
1879 subindex = "[i]";
1880 }
1881 else {
1882 (void)sprintf(string, "%s->%s.", arg->argOutSegment, arg->argMsgField);
1883 VarArray = it->itVarArray;
1884 count = arg->argCount;
1885 subindex = "";
1886 }
1887
1888 if (akCheck(arg->argKind, akbVarNeeded))
1889 fprintf(file, "\t%saddress = (void *)%s%s;\n", string, arg->argMsgField, subindex);
1890 if (arg->argDealloc != argNULL)
1891 if (akCheck(arg->argDealloc->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
1892 fprintf(file, "\t%sdeallocate = %s;\n", string, arg->argDealloc->argVarName);
1893 if (VarArray) {
1894 fprintf(file, "\t%scount = ", string);
1895 if (akCheck(count->argKind, akbVarNeeded))
1896 fprintf(file, "%s%s;\n", count->argName, subindex);
1897 else if (akCheck(arg->argKind, akbReplyCopy))
1898 /* Fixed an ancient bug here, first %s should be the position of count, not arg */
1899 fprintf(file, "%s->%s%s;\n", count->argInSegment, count->argMsgField, subindex);
1900 else
1901 fprintf(file, "%s->%s%s;\n", count->argOutSegment, count->argMsgField, subindex);
1902 }
1903 if (arg->argPoly != argNULL && akCheckAll(arg->argPoly->argKind, akbReturnSnd))
1904 if (akCheck(arg->argPoly->argKind, akbVarNeeded) || IS_MULTIPLE_KPD(it))
1905 fprintf(file, "\t%sdisposition = %s;\n", string, arg->argPoly->argVarName);
1906 if (IS_MULTIPLE_KPD(it)) {
1907 fprintf(file, "\t }\n");
1908 if (it->itVarArray && !it->itElement->itVarArray) {
1909 fprintf(file, "\t for (i = j; i < %d; ptr++, i++)\n", it->itKPD_Number);
1910 /* since subordinate arrays aren't variable, they are initialized from template:
1911 here we must no-op 'em */
1912 fprintf(file, "\t%scount = 0;\n", string);
1913 }
1914 fprintf(file, "\t}\n");
1915 }
1916 fprintf(file, "\n");
1917}
1918
1919/*
1920 * argKPD_TypeCheck discipline for Port types.
1921 */
1922static void
1923WriteTCheckKPD_port(FILE *file, argument_t *arg)
1924{
1925 ipc_type_t *it = arg->argType;
1926 char *tab = "";
1927 char string[MAX_STR_LEN];
1928 boolean_t close = FALSE;
1929
1930 if (IS_MULTIPLE_KPD(it)) {
1931 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
1932 (void)sprintf(string, "ptr->");
1933 tab = "\t";
1934 close = TRUE;
1935 }
1936 else
1937 (void)sprintf(string, "%s->%s.", arg->argInSegment, arg->argMsgField);
1938
1939 fprintf(file, "\t%sif (%stype != MACH_MSG_PORT_DESCRIPTOR", tab, string);
1940 /*
1941 * We can't check disposition on varArray
1942 * (because some of the entries could be empty).
1943 */
1944 if (!it->itVarArray) {
1945 if (arg->argPoly != argNULL) {
1946 switch (it->itOutName) {
1947
1948 case MACH_MSG_TYPE_MOVE_RECEIVE:
1949 fprintf(file, " || \n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_RECEIVE", tab, string);
1950 break;
1951
1952 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
1953 fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND_ONCE", tab, string);
1954 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND_ONCE)", tab, string);
1955 break;
1956
1957 case MACH_MSG_TYPE_MOVE_SEND:
1958 fprintf(file, " || (\n\t%s %sdisposition != MACH_MSG_TYPE_MOVE_SEND", tab, string);
1959 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_MAKE_SEND", tab, string);
1960 fprintf(file, " && \n\t%s %sdisposition != MACH_MSG_TYPE_COPY_SEND)", tab, string);
1961 break;
1962 }
1963 }
1964 else {
1965 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, it->itOutNameStr);
1966 }
1967 }
1968 fprintf(file, ")\n");
1969 fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n");
1970 if (close)
1971 fprintf(file, "\t }\n\t}\n");
1972}
1973
1974/*
1975 * argKPD_TypeCheck discipline for out-of-line types.
1976 */
1977static void
1978WriteTCheckKPD_ool(FILE *file, argument_t *arg)
1979{
1980 ipc_type_t *it = arg->argType;
1981 char *tab, string[MAX_STR_LEN];
1982 boolean_t test;
1983 u_int howmany, howbig;
1984
1985 if (IS_MULTIPLE_KPD(it)) {
1986 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
1987 tab = "\t\t\t";
1988 sprintf(string, "ptr->");
1989 howmany = it->itElement->itNumber;
1990 howbig = it->itElement->itSize;
1991 test = !it->itVarArray && !it->itElement->itVarArray;
1992 }
1993 else {
1994 tab = "";
1995 sprintf(string, "%s->%s.", arg->argInSegment, arg->argMsgField);
1996 howmany = it->itNumber;
1997 howbig = it->itSize;
1998 test = !it->itVarArray;
1999 }
2000
2001 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_DESCRIPTOR", tab, string);
2002 if (test) {
2003 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
2004 fprintf(file, " ||\n\t%s %ssize != %d", tab, string, (howmany * howbig + 7)/8);
2005 }
2006
2007 fprintf(file, ")\n");
2008 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
2009
2010 if (IS_MULTIPLE_KPD(it))
2011 fprintf(file, "\t }\n\t}\n");
2012}
2013
2014/*
2015 * argKPD_TypeCheck discipline for out-of-line Port types.
2016 */
2017static void
2018WriteTCheckKPD_oolport(FILE *file, argument_t *arg)
2019{
2020 ipc_type_t *it = arg->argType;
2021 char *tab, string[MAX_STR_LEN];
2022 boolean_t test;
2023 u_int howmany;
2024 char *howstr;
2025
2026 if (IS_MULTIPLE_KPD(it)) {
2027 WriteKPD_Iterator(file, TRUE, FALSE, arg, TRUE);
2028 tab = "\t";
2029 sprintf(string, "ptr->");
2030 howmany = it->itElement->itNumber;
2031 test = !it->itVarArray && !it->itElement->itVarArray;
2032 howstr = it->itElement->itOutNameStr;
2033 }
2034 else {
2035 tab = "";
2036 sprintf(string, "%s->%s.", arg->argInSegment, arg->argMsgField);
2037 howmany = it->itNumber;
2038 test = !it->itVarArray;
2039 howstr = it->itOutNameStr;
2040 }
2041
2042 fprintf(file, "\t%sif (%stype != MACH_MSG_OOL_PORTS_DESCRIPTOR", tab, string);
2043 if (test)
2044 /* if VarArray we may use no-op; if itElement->itVarArray size might change */
2045 fprintf(file, " ||\n\t%s %scount != %d", tab, string, howmany);
2046 if (arg->argPoly == argNULL)
2047 fprintf(file, " ||\n\t%s %sdisposition != %s", tab, string, howstr);
2048 fprintf(file, ")\n");
2049 fprintf(file, "\t\treturn MIG_TYPE_ERROR;\n");
2050
2051 if (IS_MULTIPLE_KPD(it))
2052 fprintf(file, "\t }\n\t}\n");
2053}
2054
2055/*************************************************************
2056 * Writes code to check that the type of each of the arguments
2057 * in the reply message is what is expected. Called by
2058 * WriteRoutine for each in && typed argument in the request message.
2059 *************************************************************/
2060static void
2061WriteTypeCheck(FILE *file, argument_t *arg)
2062{
2063 fprintf(file, "#if\t__MigTypeCheck\n");
2064 (*arg->argKPD_TypeCheck)(file, arg);
2065 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
2066}
2067
2068static void
2069WritePackArgValueNormal(FILE *file, argument_t *arg)
2070{
2071 ipc_type_t *it = arg->argType;
2072
2073 if (IS_VARIABLE_SIZED_UNTYPED(it) || it->itNoOptArray) {
2074 if (it->itString) {
2075 /*
2076 * Copy variable-size C string with mig_strncpy.
2077 * Save the string length (+ 1 for trailing 0)
2078 * in the argument`s count field.
2079 */
2080 fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
2081 fprintf(file, "\tif (mig_strncpy_zerofill != NULL) {\n");
2082 fprintf(file, "\t\t%s->%s = (%s) mig_strncpy_zerofill(%s->%s, %s, %d);\n",
2083 arg->argCount->argOutSegment, arg->argCount->argMsgField, arg->argCount->argType->itTransType,
2084 arg->argOutSegment, arg->argMsgField, arg->argVarName, it->itNumber);
2085 fprintf(file, "\t} else {\n");
2086 fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
2087
2088 fprintf(file, "\t\t%s->%s = (%s) mig_strncpy(%s->%s, %s, %d);\n",
2089 arg->argCount->argOutSegment, arg->argCount->argMsgField, arg->argCount->argType->itTransType,
2090 arg->argOutSegment, arg->argMsgField, arg->argVarName, it->itNumber);
2091
2092 fprintf(file, "#ifdef USING_MIG_STRNCPY_ZEROFILL\n");
2093 fprintf(file, "\t}\n");
2094 fprintf(file, "#endif /* USING_MIG_STRNCPY_ZEROFILL */\n");
2095
2096 fprintf(file, "\t%s->%sOffset = 0;\n", arg->argOutSegment, arg->argMsgField);
2097 }
2098 else if (it->itNoOptArray)
2099 fprintf(file, "\t(void)memcpy((char *) %s->%s, (const char *) %s, %d);\n",
2100 arg->argOutSegment, arg->argMsgField, arg->argVarName, it->itTypeSize);
2101 else {
2102 argument_t *count = arg->argCount;
2103 ipc_type_t *btype = it->itElement;
2104 identifier_t newstr;
2105 char tmpstr[MAX_STR_LEN];
2106
2107 /* Note btype->itNumber == count->argMultiplier */
2108
2109 fprintf(file, "\t(void)memcpy((char *) %s->%s, (const char *) %s, ",
2110 arg->argOutSegment, arg->argMsgField, arg->argVarName);
2111 if (btype->itTypeSize > 1)
2112 fprintf(file, "%d * ", btype->itTypeSize);
2113 /* count is a akbVarNeeded if arg is akbVarNeeded */
2114 if (akCheck(count->argKind, akbVarNeeded)) {
2115 newstr = count->argVarName;
2116 } else {
2117 sprintf("%s->%s", count->argOutSegment, count->argMsgField);
2118 newstr = tmpstr;
2119 }
2120 fprintf(file, "%s);\n", newstr);
2121 }
2122 }
2123 else if (it->itOutTrans != strNULL)
2124 WriteCopyType(file, it, TRUE, "%s->%s",
2125 "/* %s %s */ %s(%s)", arg->argOutSegment, arg->argMsgField,
2126 it->itOutTrans, arg->argVarName);
2127 else
2128 WriteCopyType(file, it, TRUE, "%s->%s",
2129 "/* %s %s */ %s", arg->argOutSegment, arg->argMsgField,
2130 arg->argVarName);
2131
2132 if (arg->argPadName != NULL && it->itPadSize != 0) {
2133 fprintf(file, "\t for (int i = 0; i < %d; i++)\n", it->itPadSize);
2134 fprintf(file, "\t\t %s->%s[i] = 0;\n", arg->argOutSegment, arg->argPadName);
2135 }
2136}
2137
2138static void
2139WritePackArgValueVariable(FILE *file, argument_t *arg)
2140{
2141 ipc_type_t *it = arg->argType;
2142
2143 /*
2144 * only itString are treated here so far
2145 */
2146 if (it->itString) {
2147 /*
2148 * Emit logic to call strlen to calculate the size of the argument, and ensure that it fits within the 32-bit result field
2149 * in the Reply, when targeting a 64-bit architecture. If a 32-bit architecture is the target, we emit code to just call
2150 * strlen() directly (since it'll return a 32-bit value that is guaranteed to fit).
2151 */
2152 fputs("#ifdef __LP64__\n", file);
2153 fprintf(file, "\t{\n"
2154 "\t\t" "size_t strLength = strlen(%s->%s) + 1;\n", arg->argOutSegment, arg->argMsgField);
2155 fprintf(file, "\t\t" "if (strLength > 0xffffffff)\n"
2156 "\t\t\t" "MIG_RETURN_ERROR(%s, MIG_BAD_ARGUMENTS);\n", OutHeadSeg);
2157 fprintf(file, "\t\t" "%s->%s = (mach_msg_type_number_t) strLength;\n"
2158 "\t}\n", arg->argCount->argOutSegment, arg->argCount->argMsgField);
2159 fputs("#else\n", file);
2160 fprintf(file, "\t%s->%s = (mach_msg_type_number_t) strlen(%s->%s) + 1;\n",
2161 arg->argCount->argOutSegment, arg->argCount->argMsgField, arg->argOutSegment, arg->argMsgField);
2162 fputs("#endif /* __LP64__ */\n", file);
2163 fprintf(file, "\t%s->%sOffset = 0;\n", arg->argCount->argOutSegment, arg->argMsgField);
2164 }
2165}
2166
2167static void
2168WriteCopyArgValue(FILE *file, argument_t *arg)
2169{
2170 fprintf(file, "\n");
2171 char *field = (arg->argSuffix != strNULL) ? arg->argSuffix : arg->argMsgField;
2172 WriteCopyType(file, arg->argType, TRUE, "%s->%s",
2173 "/* %s %s */ %s->%s",arg->argOutSegment, field, arg->argInSegment, field);
2174}
2175
2176static void
2177WriteInitArgValue(FILE *file, argument_t *arg)
2178{
2179 fprintf(file, "\n");
2180 fprintf(file, "\t%s->%s = %s;\n\n", arg->argOutSegment, arg->argMsgField, arg->argVarName);
2181}
2182
2183/*
2184 * Calculate the size of a variable-length message field.
2185 */
2186static void
2187WriteArgSize(FILE *file, argument_t *arg)
2188{
2189 ipc_type_t *ptype = arg->argType;
2190 int bsize = ptype->itElement->itTypeSize;
2191 argument_t *count = arg->argCount;
2192
2193 /* If the base type size of the data field isn`t a multiple of 4,
2194 we have to round up. */
2195 if (bsize % itWordAlign != 0)
2196 fprintf(file, "_WALIGN_");
2197
2198 /* Here, we generate ((value + %d) & ~%d). We have to put two (( at the
2199 * the beginning.
2200 */
2201 fprintf(file, "((");
2202 if (bsize > 1)
2203 fprintf(file, "%d * ", bsize);
2204 if (ptype->itString || !akCheck(count->argKind, akbVarNeeded))
2205 /* get count from descriptor in message */
2206 fprintf(file, "%s->%s", count->argOutSegment, count->argMsgField);
2207 else
2208 /* get count from argument */
2209 fprintf(file, "%s", count->argVarName);
2210
2211 /*
2212 * If the base type size is not a multiple of sizeof(natural_t),
2213 * we have to round up.
2214 */
2215 if (bsize % sizeof(natural_t) != 0)
2216 fprintf(file, " + %d) & ~%d)", (int)sizeof(natural_t)-1, (int)sizeof(natural_t)-1);
2217 else
2218 fprintf(file, "))");
2219}
2220
2221/*
2222 * Adjust message size and advance reply pointer.
2223 * Called after packing a variable-length argument that
2224 * has more arguments following.
2225 */
2226static void
2227WriteAdjustMsgSize(FILE *file, argument_t *arg)
2228{
2229 routine_t *rt = arg->argRoutine;
2230 ipc_type_t *ptype = arg->argType;
2231
2232 /* There are more Out arguments. We need to adjust msgh_size
2233 and advance OutP, so we save the size of the current field
2234 in msgh_size_delta. */
2235
2236 fprintf(file, "\tmsgh_size_delta = ");
2237 WriteArgSize(file, arg);
2238 fprintf(file, ";\n");
2239
2240 if (rt->rtNumReplyVar == 1) {
2241 /* We can still address the message header directly. Fill
2242 in the size field. */
2243
2244 fprintf(file, "\t%s->Head.msgh_size = ", OutHeadSeg);
2245 rtMinReplySize(file, rt, "Reply");
2246 fprintf(file, " + msgh_size_delta;\n");
2247 }
2248 else if (arg->argReplyPos == 0) {
2249 /* First variable-length argument. The previous msgh_size value
2250 is the minimum reply size. */
2251
2252 fprintf(file, "\tmsgh_size = ");
2253 rtMinReplySize(file, rt, "Reply");
2254 fprintf(file, " + msgh_size_delta;\n");
2255 }
2256 else
2257 fprintf(file, "\tmsgh_size += msgh_size_delta;\n");
2258
2259 if (!UseMachMsg2) {
2260 fprintf(file, "\tOutP = (Reply *) ((pointer_t) OutP + msgh_size_delta - %d);\n",
2261 ptype->itTypeSize + ptype->itPadSize);
2262 } else {
2263 fprintf(file, "\tOutUP = (ReplyU *) ((pointer_t) OutUP + msgh_size_delta - %d);\n",
2264 ptype->itTypeSize + ptype->itPadSize);
2265 }
2266}
2267
2268/*
2269 * Calculate the size of the message. Called after the
2270 * last argument has been packed.
2271 */
2272static void
2273WriteFinishMsgSize(FILE *file, argument_t *arg)
2274{
2275 /* No more Out arguments. If this is the only variable Out
2276 argument, we can assign to msgh_size directly. */
2277
2278 if (arg->argReplyPos == 0) {
2279 fprintf(file, "\t%s->Head.msgh_size = ", OutHeadSeg);
2280 rtMinReplySize(file, arg->argRoutine, "Reply");
2281 fprintf(file, " + (");
2282 WriteArgSize(file, arg);
2283 fprintf(file, ");\n");
2284 }
2285 else {
2286 fprintf(file, "\tmsgh_size += ");
2287 WriteArgSize(file, arg);
2288 fprintf(file, ";\n");
2289 }
2290}
2291
2292/*
2293 * Handle reply arguments - fill in message types and copy arguments
2294 * that need to be copied.
2295 */
2296static void
2297WriteReplyArgs(FILE *file, routine_t *rt)
2298{
2299 argument_t *arg;
2300 argument_t *lastVarArg;
2301
2302 /*
2303 * 1. The Kernel Processed Data
2304 */
2305 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext)
2306 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnKPD))
2307 (*arg->argKPD_Pack)(file, arg);
2308 /*
2309 * 2. The Data Stream
2310 */
2311 lastVarArg = argNULL;
2312 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2313 /*
2314 * Adjust message size and advance message pointer if
2315 * the last request argument was variable-length and the
2316 * request position will change.
2317 */
2318 if (lastVarArg != argNULL &&
2319 lastVarArg->argReplyPos < arg->argReplyPos) {
2320 WriteAdjustMsgSize(file, lastVarArg);
2321 lastVarArg = argNULL;
2322 }
2323
2324 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVarNeeded))
2325 WritePackArgValueNormal(file, arg);
2326 else if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable))
2327 WritePackArgValueVariable(file, arg);
2328
2329 if (akCheck(arg->argKind, akbReplyCopy))
2330 WriteCopyArgValue(file, arg);
2331 if (akCheck(arg->argKind, akbReplyInit))
2332 WriteInitArgValue(file, arg);
2333 /*
2334 * Remember whether this was variable-length.
2335 */
2336 if (akCheckAll(arg->argKind, akbReturnSnd|akbReturnBody|akbVariable))
2337 lastVarArg = arg;
2338 }
2339 /*
2340 * Finish the message size.
2341 */
2342 if (lastVarArg != argNULL)
2343 WriteFinishMsgSize(file, lastVarArg);
2344}
2345
2346static void
2347WriteFieldDecl(FILE *file, argument_t *arg)
2348{
2349 if (akCheck(arg->argKind, akbSendKPD) ||
2350 akCheck(arg->argKind, akbReturnKPD))
2351 WriteFieldDeclPrim(file, arg, FetchKPDType);
2352 else
2353 WriteFieldDeclPrim(file, arg, FetchServerType);
2354}
2355
2356static void
2357InitKPD_Disciplines(argument_t *args)
2358{
2359 argument_t *arg;
2360 extern void KPD_noop(FILE *file, argument_t *arg);
2361 extern void KPD_error(FILE *file, argument_t *arg);
2362 extern void WriteTemplateKPD_port(FILE *file, argument_t *arg, boolean_t in);
2363 extern void WriteTemplateKPD_ool(FILE *file, argument_t *arg, boolean_t in);
2364 extern void WriteTemplateKPD_oolport(FILE *file, argument_t *arg, boolean_t in);
2365
2366 /*
2367 * WriteInitKPD_port, WriteKPD_port, WriteExtractKPD_port,
2368 * WriteInitKPD_ool, WriteKPD_ool, WriteExtractKPD_ool,
2369 * WriteInitKPD_oolport, WriteKPD_oolport, WriteExtractKPD_oolport
2370 * are local to this module (which is the reason why this initialization
2371 * takes place here rather than in utils.c).
2372 * Common routines for user and server will be established SOON, and
2373 * all of them (including the initialization) will be transfert to
2374 * utils.c
2375 * All the KPD disciplines are defaulted to be KPD_error().
2376 * Note that akbSendKPD and akbReturnKPd are not exclusive,
2377 * because of inout type of parameters.
2378 */
2379 for (arg = args; arg != argNULL; arg = arg->argNext)
2380 if (akCheck(arg->argKind, akbSendKPD|akbReturnKPD))
2381 switch (arg->argKPD_Type) {
2382
2383 case MACH_MSG_PORT_DESCRIPTOR:
2384 if akCheck(arg->argKind, akbSendKPD) {
2385 arg->argKPD_Extract =
2386 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_port : WriteExtractArgValue;
2387 arg->argKPD_TypeCheck = WriteTCheckKPD_port;
2388 }
2389 if akCheck(arg->argKind, akbReturnKPD) {
2390 arg->argKPD_Template = WriteTemplateKPD_port;
2391 arg->argKPD_Init = WriteInitKPD_port;
2392 arg->argKPD_Pack = WriteKPD_port;
2393 }
2394 break;
2395
2396 case MACH_MSG_OOL_DESCRIPTOR:
2397 if akCheck(arg->argKind, akbSendKPD) {
2398 arg->argKPD_Extract =
2399 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_ool : WriteExtractArgValue;
2400 arg->argKPD_TypeCheck = WriteTCheckKPD_ool;
2401 }
2402 if akCheck(arg->argKind, akbReturnKPD) {
2403 arg->argKPD_Template = WriteTemplateKPD_ool;
2404 arg->argKPD_Init = WriteInitKPD_ool;
2405 arg->argKPD_Pack = WriteKPD_ool;
2406 }
2407 break;
2408
2409 case MACH_MSG_OOL_PORTS_DESCRIPTOR:
2410 if akCheck(arg->argKind, akbSendKPD) {
2411 arg->argKPD_Extract =
2412 (IS_MULTIPLE_KPD(arg->argType)) ? WriteExtractKPD_oolport : WriteExtractArgValue;
2413 arg->argKPD_TypeCheck = WriteTCheckKPD_oolport;
2414 }
2415 if akCheck(arg->argKind, akbReturnKPD) {
2416 arg->argKPD_Template = WriteTemplateKPD_oolport;
2417 arg->argKPD_Init = WriteInitKPD_oolport;
2418 arg->argKPD_Pack = WriteKPD_oolport;
2419 }
2420 break;
2421
2422 default:
2423 printf("MiG internal error: type of kernel processed data unknown\n");
2424 exit(1);
2425 } /* end of switch */
2426}
2427
2428static void WriteStringTerminatorCheck(FILE *file, routine_t *rt)
2429{
2430 // generate code to verify that the length of a C string is not greater than the size of the
2431 // buffer in which it is stored.
2432 argument_t *argPtr;
2433 int msg_limit_calculated = FALSE;
2434 int found_string_argument = FALSE;
2435 int variable_length_args_present = (rt->rtMaxRequestPos > 0);
2436
2437 // scan through arguments to see if there are any strings
2438 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
2439 if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) {
2440 found_string_argument = TRUE;
2441 break;
2442 }
2443 }
2444
2445 if (found_string_argument) {
2446 // create a new scope, for local variables
2447 fputs("#if __MigTypeCheck\n" "\t" "{" "\n", file);
2448
2449 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
2450 if ((argPtr->argKind & akbRequest) && argPtr->argType->itString) {
2451 //fprintf(stderr, "### found itString: variable name = %s, max length = %d\n", argPtr->argName, argPtr->argType->itNumber);
2452
2453 if (!msg_limit_calculated) {
2454 msg_limit_calculated = TRUE; // only need to do this once
2455 if (!UseMachMsg2) {
2456 fprintf(file, "\t\t" "char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;\n");
2457 } else {
2458 fprintf(file, "\t\t" "char * msg_limit = (char *) InTrailerP;\n");
2459 }
2460 if (IsKernelServer) {
2461 fputs("#if __MigKernelSpecificCode\n", file);
2462 fputs("\t\t" "size_t strnlen_limit;" "\n", file);
2463 fputs("#else\n", file);
2464 }
2465 fputs("\t\t" "size_t memchr_limit;" "\n", file);
2466 if (IsKernelServer) {
2467 fputs("#endif /* __MigKernelSpecificCode */" "\n", file);
2468 }
2469 fputc('\n', file);
2470 }
2471
2472 // I would really prefer to use strnlen() here, to ensure that the byte scanning logic does not extend beyond
2473 // the end of the buffer, but it's not necessarily guaranteed to be available. Instead, I'll use memchr(),
2474 // and let it look for the terminating null byte.
2475 // (later...)
2476 // It turns out that the kernel does not have memchr() available, but strnlen() IS available, so we'll just
2477 // have to emit some conditional code to use the appropriate runtime environment scanning function.
2478 //
2479 if (!variable_length_args_present) {
2480 assert(argPtr->argRequestPos == 0);
2481 }
2482 if (IsKernelServer) {
2483 fputs("#if __MigKernelSpecificCode\n", file);
2484 fputs("\t\t" "strnlen_limit = min((msg_limit - ", file);
2485 // If there are variable-length arguments within the message, the proper (adjusted)
2486 // pointers must be used to access those strings
2487 fprintf(file, "%s->%s), %d);" "\n", argPtr->argInSegment, argPtr->argName, argPtr->argType->itNumber);
2488 fputs("\t\t" "if (", file);
2489 fprintf(file, "( strnlen(%s->%s, strnlen_limit) >= %d + 1 )", argPtr->argInSegment, argPtr->argName, argPtr->argType->itNumber);
2490 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file);
2491 fputs("#else\n", file);
2492 }
2493 // If there are variable-length arguments within the message, the proper (adjusted)
2494 // pointers must be used to access those strings
2495 fprintf(file, "\t\t" "memchr_limit = min((msg_limit - %s->%s), %d);" "\n",
2496 argPtr->argInSegment, argPtr->argName, argPtr->argType->itNumber);
2497 fputs("\t\t" "if (", file);
2498 fprintf(file, "( memchr(%s->%s, '\\0', memchr_limit) == NULL )", argPtr->argInSegment, argPtr->argName);
2499 fputs(")" "\n" "\t\t\t" "return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!" "\n", file);
2500 if (IsKernelServer) {
2501 fputs("#endif /* __MigKernelSpecificCode */" "\n", file);
2502 }
2503 }
2504 }
2505 fputs("\t" "}" "\n" "#endif" "\t" "/* __MigTypeCheck */" "\n\n", file); // terminate new scope
2506 }
2507
2508 return;
2509}
2510
2511static void
2512WriteOOLSizeCheck(FILE *file, routine_t *rt)
2513{
2514 /* Emit code to validate the actual size of ool data vs. the reported size */
2515
2516 argument_t *argPtr;
2517 boolean_t openedTypeCheckConditional = FALSE;
2518
2519 // scan through arguments to see if there are any ool data blocks
2520 for (argPtr = rt->rtArgs; argPtr != NULL; argPtr = argPtr->argNext) {
2521 if (akCheck(argPtr->argKind, akbSendKPD)) {
2522 ipc_type_t *it = argPtr->argType;
2523 boolean_t multiple_kpd = IS_MULTIPLE_KPD(it);
2524 char string[MAX_STR_LEN];
2525 boolean_t test;
2526 argument_t *argCountPtr;
2527 char *tab;
2528
2529 if (argPtr->argKPD_Type == MACH_MSG_OOL_DESCRIPTOR) {
2530
2531 if (multiple_kpd) {
2532 if ( !openedTypeCheckConditional ) {
2533 openedTypeCheckConditional = TRUE;
2534 fputs("#if __MigTypeCheck\n", file);
2535 }
2536 WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE);
2537 tab = "\t";
2538 sprintf(string, "ptr->");
2539 test = !it->itVarArray && !it->itElement->itVarArray;
2540 it = it->itElement; // point to element descriptor, so size calculation is correct
2541 argCountPtr = argPtr->argSubCount;
2542 } else {
2543 tab = "";
2544 sprintf(string, "%s->%s.", argPtr->argInSegment, argPtr->argMsgField);
2545 test = !it->itVarArray;
2546 argCountPtr = argPtr->argCount;
2547 }
2548
2549 if (!test) {
2550 int multiplier = (argCountPtr->argMultiplier > 1 || it->itSize > 8) ? argCountPtr->argMultiplier * it->itSize / 8 : 1;
2551 if ( !openedTypeCheckConditional ) {
2552 openedTypeCheckConditional = TRUE;
2553 fputs("#if __MigTypeCheck\n", file);
2554 }
2555
2556 fprintf(file, "\t%s" "if (%ssize ", tab, string);
2557 if (multiplier > 1)
2558 fprintf(file, "/ %d ", multiplier);
2559 fprintf(file,"!= %s->%s%s", argCountPtr->argInSegment, argCountPtr->argVarName, multiple_kpd ? "[i]" : "");
2560 if (it->itOOL_Number) {
2561 fprintf(file," || %s->%s%s > %d", argCountPtr->argInSegment,
2562 argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number);
2563 }
2564
2565 fprintf(file,")\n");
2566 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
2567 }
2568
2569 if (multiple_kpd)
2570 fprintf(file, "\t }\n\t}\n");
2571 } else if (argPtr->argKPD_Type == MACH_MSG_OOL_PORTS_DESCRIPTOR) {
2572 if (multiple_kpd) {
2573 if ( !openedTypeCheckConditional ) {
2574 openedTypeCheckConditional = TRUE;
2575 fputs("#if __MigTypeCheck\n", file);
2576 }
2577 WriteKPD_Iterator(file, TRUE, FALSE, argPtr, TRUE);
2578 tab = "\t";
2579 sprintf(string, "ptr->");
2580 test = !it->itVarArray && !it->itElement->itVarArray;
2581 it = it->itElement; // point to element descriptor, so size calculation is correct
2582 argCountPtr = argPtr->argSubCount;
2583 } else {
2584 tab = "";
2585 sprintf(string, "%s->%s.", argPtr->argInSegment, argPtr->argMsgField);
2586 test = !it->itVarArray;
2587 argCountPtr = argPtr->argCount;
2588 }
2589
2590 if (!test) {
2591 if ( !openedTypeCheckConditional ) {
2592 openedTypeCheckConditional = TRUE;
2593 fputs("#if __MigTypeCheck\n", file);
2594 }
2595
2596 fprintf(file, "\t%s" "if (%scount ", tab, string);
2597 fprintf(file,"!= %s->%s%s", argCountPtr->argInSegment, argCountPtr->argVarName, multiple_kpd ? "[i]" : "");
2598 if (it->itOOL_Number) {
2599 fprintf(file," || %s->%s%s > %d", argCountPtr->argInSegment,
2600 argCountPtr->argVarName, multiple_kpd ? "[i]" : "", it->itOOL_Number);
2601 }
2602 fprintf(file,")\n");
2603 fprintf(file, "\t\t%s" "return MIG_TYPE_ERROR;\n", tab);
2604 }
2605
2606 if (multiple_kpd)
2607 fprintf(file, "\t }\n\t}\n");
2608 }
2609 }
2610 }
2611
2612 if ( openedTypeCheckConditional )
2613 fputs("#endif" "\t" "/* __MigTypeCheck */" "\n\n", file);
2614}
2615
2616
2617void
2618WriteCheckRequest(FILE *file, routine_t *rt)
2619{
2620 int i;
2621
2622 /* initialize the disciplines for the handling of KPDs */
2623 InitKPD_Disciplines(rt->rtArgs);
2624
2625 fprintf(file, "\n");
2626 fprintf(file, "#if ( __MigTypeCheck ");
2627 if (CheckNDR)
2628 fprintf(file, "|| __NDR_convert__ ");
2629 fprintf(file, ")\n");
2630 fprintf(file, "#if __MIG_check__Request__%s_subsystem__\n", SubsystemName);
2631 fprintf(file, "#if !defined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
2632 fprintf(file, "#define __MIG_check__Request__%s_t__defined\n", rt->rtName);
2633 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) {
2634 __KernelServer_unreachable();
2635 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgDecl, akbSendNdr, "", "");
2636 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgDecl, akbSendNdr, "", "");
2637 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgDecl, akbSendNdr, "", "");
2638 }
2639 fprintf(file, "\n");
2640 if (!UseMachMsg2) {
2641 fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(__attribute__((__unused__)) __Request__%s_t *In0P",
2642 rt->rtName, rt->rtName);
2643 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2644 fprintf(file, ", __attribute__((__unused__)) __Request__%s_t **In%dPP", rt->rtName, i);
2645 } else {
2646 fprintf(file, "mig_internal kern_return_t __MIG_check__Request__%s_t(\n"
2647 "\t__attribute__((__unused__)) __RequestKData__%s_t *InKP,\n"
2648 "\t__attribute__((__unused__)) __RequestUData__%s_t *In0UP,\n"
2649 "\t__attribute__((__unused__)) mach_msg_max_trailer_t *InTrailerP",
2650 rt->rtName, rt->rtName, rt->rtName);
2651 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2652 fprintf(file, ",\n\t__attribute__((__unused__)) __RequestUData__%s_t **In%dUPP", rt->rtName, i);
2653 }
2654 fprintf(file, ")\n{\n");
2655
2656 fprintf(file, "\n\ttypedef __Request__%s_t __Request;\n", rt->rtName);
2657 if (!UseMachMsg2) {
2658 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2659 fprintf(file, "\t__Request *In%dP;\n", i);
2660 } else {
2661 fprintf(file, "\ttypedef __RequestUData__%s_t __RequestU __attribute__((unused));\n", rt->rtName);
2662 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2663 fprintf(file, "\t__RequestU *In%dUP;\n", i);
2664 }
2665
2666 if (rt->rtNumRequestVar > 0) {
2667 fprintf(file, "#if\t__MigTypeCheck\n");
2668 fprintf(file, "\tunsigned int msgh_size;\n");
2669 fprintf(file, "#endif\t/* __MigTypeCheck */\n");
2670 }
2671 if (rt->rtMaxRequestPos > 0)
2672 fprintf(file, "\tunsigned int msgh_size_delta;\n");
2673 if (rt->rtNumRequestVar > 0 || rt->rtMaxRequestPos > 0)
2674 fprintf(file, "\n");
2675
2676 WriteCheckHead(file, rt);
2677
2678 WriteList(file, rt->rtArgs, WriteTypeCheck, akbSendKPD, "\n", "\n");
2679
2680 {
2681 argument_t *arg, *lastVarArg;
2682
2683 lastVarArg = argNULL;
2684 for (arg = rt->rtArgs; arg != argNULL; arg = arg->argNext) {
2685 if (lastVarArg != argNULL &&
2686 lastVarArg->argRequestPos < arg->argRequestPos) {
2687 WriteAdjustRequestMsgPtr(file, lastVarArg);
2688 lastVarArg = argNULL;
2689 }
2690 if (akCheckAll(arg->argKind, akbSendRcv|akbSendBody)) {
2691 if (akCheck(arg->argKind, akbVariable)) {
2692 WriteCheckMsgSize(file, arg);
2693 lastVarArg = arg;
2694 }
2695 }
2696 }
2697 }
2698
2699 if (CheckNDR && akCheck(rt->rtNdrCode->argKind, akbRequest)) {
2700 __KernelServer_unreachable();
2701 fprintf(file, "#if\t");
2702 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgCond, akbSendNdr, " || \\\n\t", "\n");
2703 fprintf(file, "\tif (In0P->NDR.int_rep != NDR_record.int_rep) {\n");
2704 WriteList(file, rt->rtArgs, WriteRequestNDRConvertIntRepArgUse, akbSendNdr, "", "");
2705 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__int_rep...) */\n\n");
2706
2707 WriteOOLSizeCheck(file, rt);
2708
2709 fprintf(file, "#if\t");
2710 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgCond, akbSendNdr, " || \\\n\t", "\n");
2711 fprintf(file, "\tif (In0P->NDR.char_rep != NDR_record.char_rep) {\n");
2712 WriteList(file, rt->rtArgs, WriteRequestNDRConvertCharRepArgUse, akbSendNdr, "", "");
2713 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__char_rep...) */\n\n");
2714
2715 fprintf(file, "#if\t");
2716 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgCond, akbSendNdr, " || \\\n\t", "\n");
2717 fprintf(file, "\tif (In0P->NDR.float_rep != NDR_record.float_rep) {\n");
2718 WriteList(file, rt->rtArgs, WriteRequestNDRConvertFloatRepArgUse, akbSendNdr, "", "");
2719 fprintf(file, "\t}\n#endif\t/* defined(__NDR_convert__float_rep...) */\n\n");
2720 } else {
2721 WriteOOLSizeCheck(file, rt);
2722 }
2723
2724 WriteStringTerminatorCheck(file, rt);
2725
2726 fprintf(file, "\treturn MACH_MSG_SUCCESS;\n");
2727 fprintf(file, "}\n");
2728 fprintf(file, "#endif /* !defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName);
2729 fprintf(file, "#endif /* __MIG_check__Request__%s_subsystem__ */\n", SubsystemName);
2730 fprintf(file, "#endif /* ( __MigTypeCheck ");
2731 if (CheckNDR)
2732 fprintf(file, "|| __NDR_convert__ ");
2733 fprintf(file, ") */\n");
2734 fprintf(file, "\n");
2735}
2736
2737void
2738WriteCheckRequestCall(FILE *file, routine_t *rt)
2739{
2740 int i;
2741
2742 fprintf(file, "\n");
2743 fprintf(file, "#if\tdefined(__MIG_check__Request__%s_t__defined)\n", rt->rtName);
2744 if (!UseMachMsg2) {
2745 fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((__Request *)In0P", rt->rtName);
2746 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2747 fprintf(file, ", (__Request **)&In%dP", i);
2748 } else {
2749 fprintf(file, "\tcheck_result = __MIG_check__Request__%s_t((RequestK *)InKP, (__RequestU *)In0UP, InTrailerP", rt->rtName);
2750 for (i = 1; i <= rt->rtMaxRequestPos; i++)
2751 fprintf(file, ", (__RequestU **)&In%dUP", i);
2752 }
2753 fprintf(file, ");\n");
2754 fprintf(file, "\tif (check_result != MACH_MSG_SUCCESS)\n");
2755 fprintf(file, "\t\t{ MIG_RETURN_ERROR(%s, check_result); }\n", OutHeadSeg);
2756 fprintf(file, "#endif\t/* defined(__MIG_check__Request__%s_t__defined) */\n", rt->rtName);
2757 fprintf(file, "\n");
2758}
2759
2760void
2761WriteCheckRequests(FILE *file, statement_t *stats)
2762{
2763 statement_t *stat;
2764
2765 for (stat = stats; stat != stNULL; stat = stat->stNext)
2766 if (stat->stKind == skRoutine)
2767 WriteCheckRequest(file, stat->stRoutine);
2768}
2769
2770static void
2771WriteRoutine(FILE *file, routine_t *rt)
2772{
2773 /* Declare the server work function: */
2774 if (ServerHeaderFileName == strNULL)
2775 WriteServerRoutine(file, rt);
2776
2777 fprintf(file, "\n");
2778
2779 fprintf(file, "/* %s %s */\n", rtRoutineKindToStr(rt->rtKind), rt->rtName);
2780 fprintf(file, "mig_internal novalue _X%s\n", rt->rtName);
2781 if (BeAnsiC) {
2782 if (!UseMachMsg2) {
2783 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2784 } else {
2785 fprintf(file, "\t(mach_msg_header_t *InHeadP, __attribute__((__unused__)) void *InDataP,\n"
2786 "\t__attribute__((__unused__)) mach_msg_max_trailer_t *InTrailerP,\n"
2787 "\tmach_msg_header_t *OutHeadP, __attribute__((__unused__)) void *OutDataP)\n");
2788 }
2789 }
2790 else {
2791 __KernelServer_unreachable();
2792 fprintf(file, "#if\t%s\n", NewCDecl);
2793 fprintf(file, "\t(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)\n");
2794 fprintf(file, "#else\n");
2795 fprintf(file, "\t(InHeadP, OutHeadP)\n");
2796 fprintf(file, "\tmach_msg_header_t *InHeadP, *OutHeadP;\n");
2797 fprintf(file, "#endif\t/* %s */\n", NewCDecl);
2798 }
2799
2800 fprintf(file, "{\n");
2801 if (!UseMachMsg2) {
2802 WriteStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "Request",
2803 rt->rtSimpleRequest, TRUE, rt->rtServerImpl, FALSE);
2804 } else {
2805 WriteUDataStructDecl(file, rt->rtArgs, WriteFieldDecl, akbRequest, "RequestU",
2806 rt->rtSimpleRequest, TRUE, rt->rtServerImpl, FALSE);
2807 fprintf(file, "\ttypedef __RequestKData__%s_t RequestK;\n", rt->rtName);
2808 fprintf(file, "\ttypedef __RequestUData__%s_t __RequestU;\n", rt->rtName);
2809 fprintf(file, "\ttypedef __ReplyKData__%s_t ReplyK __attribute__((unused));\n", rt->rtName);
2810 fprintf(file, "\ttypedef __ReplyUData__%s_t ReplyU __attribute__((unused));\n", rt->rtName);
2811 }
2812 fprintf(file, "\ttypedef __Reply__%s_t Reply __attribute__((unused));\n", rt->rtName);
2813 fprintf(file, "\ttypedef __Request__%s_t __Request __attribute__((unused));\n\n", rt->rtName);
2814
2815 /*
2816 * Define a Minimal Reply structure to be used in case of errors
2817 */
2818 fprintf(file, "\t/*\n");
2819 fprintf(file, "\t * typedef struct {\n");
2820 fprintf(file, "\t * \tmach_msg_header_t Head;\n");
2821 fprintf(file, "\t * \tNDR_record_t NDR;\n");
2822 fprintf(file, "\t * \tkern_return_t RetCode;\n");
2823 fprintf(file, "\t * } mig_reply_error_t;\n");
2824 fprintf(file, "\t */\n");
2825 fprintf(file, "\n");
2826
2827 WriteVarDecls(file, rt);
2828
2829 if (IsKernelServer) {
2830 fprintf(file, "#if\t__MigKernelSpecificCode\n");
2831 WriteList(file, rt->rtArgs, WriteTemplateDeclOut, akbReturnKPD, "\n", "\n");
2832 fprintf(file, "#else\n");
2833 }
2834 WriteList(file, rt->rtArgs, WriteTemplateDeclIn, akbReturnKPD, "\n", "\n");
2835 if (IsKernelServer) {
2836 fprintf(file, "#endif /* __MigKernelSpecificCode */\n");
2837 }
2838 WriteRetCode(file, rt->rtRetCode);
2839 WriteList(file, rt->rtArgs, WriteLocalVarDecl, akbVarNeeded | akbServerArg, ";\n", ";\n\n");
2840 WriteApplMacro(file, "Rcv", "Declare", rt);
2841 WriteApplMacro(file, "Rcv", "Before", rt);
2842 if (rt->rtRetCArg != argNULL && !rt->rtSimpleRequest) {
2843 WriteRetCArgCheckError(file, rt);
2844 if (rt->rtServerImpl)
2845 WriteCheckTrailerHead(file, rt, FALSE);
2846 WriteServerCall(file, rt, WriteConditionalCallArg);
2847 WriteRetCArgFinishError(file, rt);
2848 }
2849
2850 WriteCheckRequestCall(file, rt);
2851 WriteCheckRequestTrailerArgs(file, rt);
2852
2853 /*
2854 * Initialize the KPD records in the Reply structure with the
2855 * templates. We do this beforehand because the call to the procedure
2856 * will overwrite some of the values (after the call it would be impossible
2857 * to initialize the KPD records from the static Templates, because we
2858 * would lose data).
2859 */
2860 WriteList(file, rt->rtArgs, WriteInitKPDValue, akbReturnKPD, "\n", "\n");
2861
2862 WriteList(file, rt->rtArgs, WriteExtractArg, akbNone, "", "");
2863
2864 if (UseEventLogger)
2865 WriteLogMsg(file, rt, LOG_SERVER, LOG_REQUEST);
2866
2867 WriteServerCall(file, rt, WriteServerCallArg);
2868
2869 WriteReverseList(file, rt->rtArgs, WriteDestroyArg, akbDestroy, "", "");
2870
2871 /*
2872 * For one-way routines, it doesn`t make sense to check the return
2873 * code, because we return immediately afterwards. However,
2874 * kernel servers may want to deallocate port arguments - and the
2875 * deallocation must not be done if the return code is not KERN_SUCCESS.
2876 */
2877 if (rt->rtOneWay || rt->rtNoReplyArgs) {
2878 if (IsKernelServer) {
2879 fprintf(file,"#if\t__MigKernelSpecificCode\n");
2880 if (rtCheckMaskFunction(rt->rtArgs, akbSendKPD, CheckDestroyPortArg)) {
2881 WriteCheckReturnValue(file, rt);
2882 }
2883 WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", "");
2884 fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
2885 }
2886 /* although we have an empty reply, we still have to make sure that
2887 some fields such as NDR get properly initialized */
2888 if (!rt->rtOneWay)
2889 WriteList(file, rt->rtArgs, WriteInitArgValue, akbReplyInit, "\n", "\n");
2890 }
2891 else {
2892 WriteCheckReturnValue(file, rt);
2893
2894 if (IsKernelServer) {
2895 fprintf(file,"#if\t__MigKernelSpecificCode\n");
2896 WriteReverseList(file, rt->rtArgs, WriteDestroyPortArg, akbSendKPD, "", "");
2897 fprintf(file,"#endif /* __MigKernelSpecificCode */\n");
2898 }
2899 WriteReplyArgs(file, rt);
2900 WriteReplyInit(file, rt);
2901 if (!rt->rtSimpleReply)
2902 fprintf(file, "\t%s->msgh_body.msgh_descriptor_count = %d;\n", OutHeadSeg, rt->rtReplyKPDs);
2903 }
2904 if (UseEventLogger)
2905 WriteLogMsg(file, rt, LOG_SERVER, LOG_REPLY);
2906
2907 WriteApplMacro(file, "Rcv", "After", rt);
2908 fprintf(file, "}\n");
2909}
2910
2911void
2912WriteServer(FILE *file, statement_t *stats)
2913{
2914 statement_t *stat;
2915
2916 WriteProlog(file, stats);
2917 if (BeAnsiC)
2918 WriteForwardDeclarations(file, stats);
2919 for (stat = stats; stat != stNULL; stat = stat->stNext)
2920 switch (stat->stKind) {
2921
2922 case skRoutine:
2923 WriteCheckRequest(file, stat->stRoutine);
2924 WriteRoutine(file, stat->stRoutine);
2925 break;
2926
2927 case skIImport:
2928 case skImport:
2929 case skSImport:
2930 case skDImport:
2931 case skUImport:
2932 break;
2933
2934 default:
2935 fatal("WriteServer(): bad statement_kind_t (%d)",
2936 (int) stat->stKind);
2937 }
2938 WriteDispatcher(file, stats);
2939}