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