Annotation of driverkit/Examples/loadable/User/kl_com.m, revision 1.1.1.1

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(), &notify_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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.