|
|
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.