bootstrap_cmds/migcom.tproj/server.c

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