|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* @(#)kl_com.m 2.0 27/07/90 (c) 1990 NeXT */ ! 25: ! 26: /* ! 27: * kl_com.m -- common kern_loader communication module. ! 28: * ! 29: * HISTORY ! 30: * 27-Jul-90 Doug Mitchell at NeXT ! 31: * Cloned from DOS source. ! 32: */ ! 33: ! 34: #import <mach/mach_traps.h> ! 35: #import <mach/mach.h> ! 36: #import <ansi/stdlib.h> ! 37: #import <bsd/libc.h> ! 38: #import <ansi/stdio.h> ! 39: #import <bsd/strings.h> ! 40: #import <mach/mach_error.h> ! 41: #import <mach/mig_errors.h> ! 42: #import <mach/cthreads.h> ! 43: #import <servers/bootstrap.h> ! 44: #import <kernserv/kern_loader_error.h> ! 45: #import <kernserv/kern_loader_types.h> ! 46: #import <kernserv/kern_loader.h> ! 47: #import <kernserv/kern_loader_reply_handler.h> ! 48: #import <bsd/sys/param.h> ! 49: #import <mach/notify.h> ! 50: #import <mach/message.h> ! 51: #import "kl_com.h" ! 52: #import <machkit/NXLock.h> ! 53: #import <driverkit/generalFuncs.h> ! 54: ! 55: static int kl_init(); ! 56: static int kl_com_log(port_name_t port); ! 57: static kern_return_t print_string ( ! 58: void *arg, ! 59: printf_data_t string, ! 60: u_int stringCnt, ! 61: int level); ! 62: static kern_return_t ping ( ! 63: void *arg, ! 64: int id); ! 65: static void kl_com_error(char *err_str, kern_return_t rtn); ! 66: ! 67: port_name_t kl_port; ! 68: port_name_t kernel_task, reply_port; ! 69: boolean_t kl_init_flag = FALSE; ! 70: static id ping_lock; ! 71: ! 72: /* ! 73: * Set up ports, etc. for kern_loader communication. ! 74: */ ! 75: static int ! 76: kl_init() { ! 77: kern_return_t r; ! 78: boolean_t isactive; ! 79: ! 80: if(kl_init_flag) ! 81: return(0); ! 82: r = kern_loader_look_up(&kl_port); ! 83: if (r != KERN_SUCCESS) { ! 84: kl_com_error("can't find kernel loader", r); ! 85: return(1); ! 86: } ! 87: ! 88: r = task_by_unix_pid(task_self(), 0, &kernel_task); ! 89: if (r != KERN_SUCCESS) { ! 90: kl_com_error("cannot get kernel task port\n", r); ! 91: return(1); ! 92: } ! 93: ! 94: r = port_allocate(task_self(), &reply_port); ! 95: if (r != KERN_SUCCESS) { ! 96: kl_com_error("can't allocate reply port", r); ! 97: return(1); ! 98: } ! 99: ! 100: r = bootstrap_status(bootstrap_port, KERN_LOADER_NAME, &isactive); ! 101: if (r != KERN_SUCCESS) { ! 102: kl_com_error("can't find kernel loader status", r); ! 103: return(1); ! 104: } ! 105: /* ! 106: * Create a thread to listen on reply_port ! 107: * and print out anything that comes back. ! 108: */ ! 109: cthread_init(); ! 110: cthread_set_name(cthread_self(), "command thread"); ! 111: cthread_detach(cthread_fork((cthread_fn_t)kl_com_log, ! 112: (any_t)reply_port)); ! 113: ! 114: if (!isactive) ! 115: printf("kernel loader inactive, pausing\n"); ! 116: ! 117: r = kern_loader_status_port(kl_port, reply_port); ! 118: if(r) { ! 119: kl_com_error("can't get status back\n", r); ! 120: return(1); ! 121: } ! 122: ping_lock = [[NXConditionLock alloc] initWith:FALSE]; ! 123: kl_init_flag = TRUE; ! 124: return(0); ! 125: } ! 126: ! 127: ! 128: kern_loader_reply_t kern_loader_reply = { ! 129: 0, ! 130: 0, ! 131: print_string, ! 132: ping ! 133: }; ! 134: ! 135: /* ! 136: * wait for reply messages. ! 137: */ ! 138: static int ! 139: kl_com_log(port_name_t port) ! 140: { ! 141: char msg_buf[kern_loader_replyMaxRequestSize]; ! 142: msg_header_t *msg = (msg_header_t *)msg_buf; ! 143: port_name_t notify_port; ! 144: port_set_name_t port_set; ! 145: kern_return_t r; ! 146: ! 147: r = port_allocate(task_self(), ¬ify_port); ! 148: if (r != KERN_SUCCESS) { ! 149: kl_com_error("allocating notify port", r); ! 150: return(1); ! 151: } ! 152: ! 153: r = task_set_notify_port(task_self(), notify_port); ! 154: if (r != KERN_SUCCESS) { ! 155: kl_com_error("cannot set notify port", r); ! 156: return(1); ! 157: } ! 158: ! 159: r = port_set_allocate(task_self(), &port_set); ! 160: if (r != KERN_SUCCESS) { ! 161: kl_com_error("allocating port set", r); ! 162: return(1); ! 163: } ! 164: ! 165: r = port_set_add(task_self(), port_set, notify_port); ! 166: if (r != KERN_SUCCESS) { ! 167: kl_com_error("adding notify port to port set", r); ! 168: return(1); ! 169: } ! 170: ! 171: r = port_set_add(task_self(), port_set, port); ! 172: if (r != KERN_SUCCESS) { ! 173: kl_com_error("adding listener port to port set", r); ! 174: return(1); ! 175: } ! 176: while(1) { ! 177: msg->msg_size = kern_loader_replyMaxRequestSize; ! 178: msg->msg_local_port = port_set; ! 179: r = msg_receive(msg, MSG_OPTION_NONE, 0); ! 180: if (r != KERN_SUCCESS) { ! 181: kl_com_error("log_thread receive", r); ! 182: return(1); ! 183: } ! 184: if (msg->msg_local_port == notify_port) { ! 185: notification_t *n = (notification_t *)msg; ! 186: ! 187: if(msg->msg_id == NOTIFY_PORT_DELETED) { ! 188: if(n->notify_port == kl_port) { ! 189: printf("kdb: kern_loader port " ! 190: "deleted\n"); ! 191: continue; ! 192: } ! 193: else { ! 194: printf("kdb: port death detected" ! 195: "(port %d)\n", n->notify_port); ! 196: continue; ! 197: } ! 198: } ! 199: else { ! 200: printf("kdb: weird notification " ! 201: "(msg_id %d)\n", msg->msg_id); ! 202: continue; ! 203: } ! 204: } ! 205: else ! 206: kern_loader_reply_handler(msg, &kern_loader_reply); ! 207: } ! 208: return(0); ! 209: } ! 210: ! 211: static kern_return_t ! 212: print_string ( ! 213: void *arg, ! 214: printf_data_t string, ! 215: u_int stringCnt, ! 216: int level) ! 217: { ! 218: #if DEBUG ! 219: if (stringCnt == 0 || !string) ! 220: return KERN_SUCCESS; ! 221: fputs(string, stdout); ! 222: fflush(stdout); ! 223: #endif DEBUG ! 224: return KERN_SUCCESS; ! 225: } ! 226: ! 227: static kern_return_t ! 228: ping ( ! 229: void *arg, ! 230: int id) ! 231: { ! 232: [ping_lock lockWhen:FALSE]; ! 233: [ping_lock unlockWith:TRUE]; ! 234: return KERN_SUCCESS; ! 235: } ! 236: ! 237: /* ! 238: * Exported functions. ! 239: */ ! 240: ! 241: /* ! 242: * Add specified server ("kl_util -a"). If server already exists, this ! 243: * is a nop. ! 244: * ! 245: * path_name is the location of the relocatable. ! 246: * server_name is kern_loader's notion of the server's identity. ! 247: */ ! 248: int ! 249: kl_com_add(char *path_name, char *server_name) { ! 250: int rtn; ! 251: kern_return_t r; ! 252: ! 253: if(rtn = kl_init()) ! 254: return(rtn); ! 255: switch(kl_com_get_state(server_name)) { ! 256: case KSS_LOADED: ! 257: case KSS_ALLOCATED: ! 258: return(0); /* this function is a nop */ ! 259: default: ! 260: break; ! 261: } ! 262: r = kern_loader_add_server(kl_port, kernel_task, path_name); ! 263: if((r != KERN_SUCCESS) && ! 264: (r != KERN_LOADER_SERVER_EXISTS) && ! 265: /* bogus - covers kern_loader bug #7190 */ ! 266: (r != KERN_LOADER_SERVER_WONT_LOAD)) { ! 267: kl_com_error("kern_loader_add_server", r); ! 268: rtn = 1; ! 269: } ! 270: return(rtn); ! 271: } ! 272: ! 273: /* ! 274: * Delete specified server. ! 275: */ ! 276: int ! 277: kl_com_delete(char *server_name) { ! 278: int rtn; ! 279: kern_return_t r; ! 280: ! 281: if(rtn = kl_init()) ! 282: return(rtn); ! 283: r = kern_loader_delete_server(kl_port, kernel_task, server_name); ! 284: if(r) { ! 285: kl_com_error("kern_loader_delete_server", r); ! 286: rtn = 1; ! 287: } ! 288: return(rtn); ! 289: } ! 290: ! 291: /* ! 292: * Load the specified server into kernel memory if it isn't already loaded. ! 293: */ ! 294: int ! 295: kl_com_load(char *server_name) { ! 296: int rtn; ! 297: kern_return_t r; ! 298: ! 299: if(rtn = kl_init()) ! 300: return(rtn); ! 301: switch(kl_com_get_state(server_name)) { ! 302: case KSS_LOADED: ! 303: return(0); /* this function is a nop */ ! 304: default: ! 305: break; ! 306: } ! 307: r = kern_loader_load_server(kl_port, server_name); ! 308: if(r) { ! 309: kl_com_error("kern_loader_load_server", r); ! 310: rtn = 1; ! 311: } ! 312: return(rtn); ! 313: } ! 314: ! 315: /* ! 316: * Unload specified server from kernel memory. The server is not deleted ! 317: * from kern_loader's list of servers. ! 318: */ ! 319: int ! 320: kl_com_unload(char *server_name) { ! 321: int rtn = 0; ! 322: kern_return_t r; ! 323: ! 324: if(rtn = kl_init()) ! 325: return(rtn); ! 326: r = kern_loader_unload_server(kl_port, kernel_task, server_name); ! 327: if(r) { ! 328: kl_com_error("kern_loader_unload_server", r); ! 329: rtn = 1; ! 330: } ! 331: return(rtn); ! 332: } ! 333: ! 334: klc_server_state ! 335: kl_com_get_state(char *server_name) ! 336: { ! 337: server_state_t state; ! 338: /* ! 339: * remainder are unused... ! 340: */ ! 341: vm_address_t load_address; ! 342: vm_size_t load_size; ! 343: server_reloc_t reloc, loadable; ! 344: port_name_t *ports; ! 345: port_name_string_array_t port_names; ! 346: u_int cnt; ! 347: boolean_t *advertised; ! 348: kern_return_t rtn; ! 349: ! 350: if(rtn = kl_init()) ! 351: return(rtn); ! 352: rtn = kern_loader_server_info(kl_port, PORT_NULL, server_name, ! 353: &state, &load_address, &load_size, reloc, loadable, ! 354: &ports, &cnt, &port_names, &cnt, &advertised, &cnt); ! 355: if(rtn != KERN_SUCCESS) { ! 356: return(KSS_UNKNOWN); ! 357: } ! 358: switch(state) { ! 359: case Allocating: ! 360: case Allocated: ! 361: return(KSS_ALLOCATED); ! 362: case Loading: ! 363: case Loaded: ! 364: return(KSS_LOADED); ! 365: case Zombie: ! 366: case Unloading: ! 367: case Deallocated: ! 368: default: ! 369: return(KSS_UNKNOWN); ! 370: } ! 371: ! 372: } ! 373: ! 374: void ! 375: kl_com_error(char *err_str, kern_return_t rtn) ! 376: { ! 377: IOLog("%s: error %d\n", err_str, rtn); ! 378: } ! 379: ! 380: void ! 381: kl_com_wait() ! 382: { ! 383: kern_loader_ping(kl_port, reply_port, 0); ! 384: ! 385: ! 386: /* ! 387: * ping() is called when this is done... ! 388: */ ! 389: [ping_lock lockWhen:TRUE]; ! 390: [ping_lock unlockWith:FALSE]; ! 391: } ! 392:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.