Source to machdep/ppc/swapgeneric.m


Enter a symbol's name here to quickly find it.

/*
 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
 * Reserved.  This file contains Original Code and/or Modifications of
 * Original Code as defined in and that are subject to the Apple Public
 * Source License Version 1.0 (the 'License').  You may not use this file
 * except in compliance with the License.  Please obtain a copy of the
 * License at http://www.apple.com/publicsource and read it before using
 * this file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License."
 * 
 * @APPLE_LICENSE_HEADER_END@
 */

/* 
 * Copyright (c) 1987, 1988 NeXT, Inc.
 *
 * HISTORY
 *
 * Tue Dec  7 17:37:14 PST 1993 Matt Watson (mwatson) at NeXT
 *	Added netboot capability.
 *
 * 07-Apr-90	Doug Mitchell at NeXT
 *	Added fd driver support.
 *
 * 16-Feb-88  John Seamons (jks) at NeXT
 *	Updated to Mach release 2.
 *
 * 29-Oct-87  Robert V. Baron (rvb) at Carnegie-Mellon University
 *	Allow root to be an arbitrary slice on the drive.
 *
 * 14-Nov-86  John Seamons (jks) at NeXT
 *	Ported to NeXT.
 */ 

#import <sys/param.h>
#import <sys/conf.h>
#import <sys/buf.h>
#import <sys/time.h>
#import <sys/systm.h>
#import <sys/mount.h>
#import <sys/reboot.h>
#import <sys/vnode.h>
#import <sys/socket.h>
#import <sys/errno.h>
#import <sys/ioctl.h>
#import <net/if.h>
#import <netinet/in_systm.h>
#import <netinet/in.h>
#import <netinet/in_var.h>
#import <netinet/ip.h>
#import <netinet/udp.h>
#import <netinet/if_ether.h>
//#import <machdep/ppc/kernBootStruct.h>
#import <machdep/ppc/powermac.h>
#import <driverkit/kernelDriver.h>
#import <driverkit/IODiskPartition.h>
#import <bsd/dev/scsireg.h>
/*
 * Hack to avoid collision with vnode.h!
 */
#undef IO_UNIT
#import <driverkit/IODeviceParams.h>
#import <driverkit/SCSIDisk.h>

extern int ffs_mountroot();

#ifdef	NFSCLIENT
extern char	*nfsbootdevname;	/* nfs_boot.c */
extern int nfs_mountroot(); 	/* nfs_vfsops.c */
#else	/* NFSCLIENT */
static char	*nfsbootdevname;
static int nfs_mountroot() { return ENOSYS; }
#endif	/* NFSCLIENT */

extern int (*mountroot)();

extern char hostname[], boot_info[], boot_dev[];
extern char domainname[];
extern struct xdr_ops xdrmbuf_ops;
extern int hostnamelen;
char rootdevice[ 128 ];

// wait until 30 seconds after probe for non-ready root disk
#define MAX_DISK_PROBE_TIME	30

int	boottype = 0, boothowto = RB_DEBUG;

/*
 * Generic configuration;  all in one
 */
extern long	dumplo;
int	dmmin, dmmax, dmtext;

struct	genericconf {
	char	*gc_name;
	dev_t	gc_root;	/* NODEV means remote root */
} genericconf[] = {
	{ "sd", makedev(6, 0) },
	{ "hd", makedev(3, 0) },
	{ "fd", makedev(1, 0) },
	{ "en", NODEV },
	{ "tr", NODEV },
	{ 0 },
};

static struct genericconf *gc;
static int scsiControllerDetected(void);

#include <machdep/ppc/DeviceTree.h>

id
SearchForDeviceByPath( char * path, char ** firstArg )
{
    IOReturn	err;
    int		objectNum = 0;
    id		dev = nil;
    char    *	tail;
    char	c;

    if( firstArg)
        *firstArg = NULL;
    do {
        err = [IODevice lookupByObjectNumber:objectNum++ instance:&dev];
        if( err != IO_R_SUCCESS)
            continue;

        if( (tail = [dev matchDevicePath:path])) {
	    c = tail[ 0 ];
	    if( c) {
		if( c == ':') {
		    if( firstArg)
                        *firstArg = tail + 1;
		} else
		    dev = nil;
	    }
	} else
            dev = nil;

    } while( (dev == nil) && (err != IO_R_NO_DEVICE));

    return( dev);
}

setconf()
{
	int		devmajor, devminor;
	int 		unit = 0;
        int 		slice = 0;
        char	* 	firstArg;
	id		dev, disk;
	char 	*	name, stringBuf[ 32 ];
        char	*	chosen = NULL;
	char 		scsiName[ 10 ];
	int 		panelUp = 0;
	BOOL		sliceValid = NO;
        char		c;

        if( 0 == (boothowto & RB_ASKNAME)) do {
            DTEntry 		dtEntry;
	    int			size;

	    c = rootdevice[ 0 ];
	    if( c == '*')
                chosen = rootdevice + 1;
	    if( c)
                continue;
            sliceValid = NO;

            if( (kSuccess == DTLookupEntry( 0, "/chosen", &dtEntry))
             && (kSuccess == DTGetProperty( dtEntry, "rootpath", (void **)&chosen, &size)) )
                continue;

            if( kSuccess != DTLookupEntry( 0, "/options", &dtEntry))
                continue;
            if( kSuccess == DTGetProperty( dtEntry, "boot-file", (void **)&chosen, &size) )
                continue;

        } while( NO);

	if( chosen) {

            char *	path = NULL;
            enum { 	kPathSize = 256 };

            path = kalloc( kPathSize );
            if( path ) {
                IODealiasPath( path, chosen );
                dev = SearchForDeviceByPath( path, &firstArg );
	    } else
		dev = NULL;

	    if( dev) {
		printf("Root device for %s found: %s\n", chosen, [dev name]);

		if( sliceValid && firstArg) {
		    slice = strtol( firstArg, 0, 16);
		    if( (slice >= 8) || (slice < 0))
			slice = 0;
		}
		if( firstArg) {
		    char 	* tail;
		    extern char   boot_file[];

		    // look backwards for ",kernel-name"
		    tail = firstArg + strlen( firstArg);
		    while( (tail != firstArg) && (tail[ 0 ] != ','))
			tail--;
		    if( tail != firstArg) {
			strcpy( boot_file, tail + 1);
			kprintf("Kernel name: %s\n", boot_file);
		    }
		}

                if( [dev respondsTo:@selector(nextLogicalDisk)]) {
                    disk = [dev nextLogicalDisk];
                    if( [disk respondsTo:@selector(waitForProbe:)]) {
                        if( nil == [disk waitForProbe:MAX_DISK_PROBE_TIME])
                            dev = nil;
                    }
                }
	    }
            if( nil == dev)
                boothowto |= RB_ASKNAME;
	    else
                strcpy( rootdevice, [dev name]);
	    if( path)
		kfree( path, kPathSize );
	}

	if ((boothowto & RB_ASKNAME) || rootdevice[0]) {
retry:
		if (boothowto & RB_ASKNAME) {

			if( 0 == panelUp) {
                            DoSafeAlert("Root Device?", "", TRUE);
			    panelUp = 1;
			}
			safe_prf("root device? ");
			name = stringBuf;
			our_gets(name, name);
			if (*name == 0) {
			    safe_prf("defaulting to en0\n");
			    strcpy(name, "en0");
			}
			strcpy(rootdevice, name);
		} else {
			/* 
			 * If we've been asked for CDROM, find the 
			 * corresponding sd device.
			 */
			if(!strcmp("cdrom", rootdevice)) {
			    id scsiId = nil;
			    int i;
			    IOReturn rtn;
			    unsigned char inquiryType;
			    
			    for(i=0; i<16; i++) {
			    	sprintf(scsiName, "sd%d", i);
				rtn = IOGetObjectForDeviceName(scsiName,
					&scsiId);
				if(rtn) {
				    break;	// no more sd's
				}
				inquiryType = [scsiId inquiryDeviceType];
				if(inquiryType == DEVTYPE_CDROM) {
				    name = scsiName;
				    goto name_found;
				}
				/* else continue to next sd */
			    }
			    if (scsiControllerDetected())
				printf("No CD-ROM drive found\n");
			    else
				printf("No SCSI controller or CD-ROM drive found\n");
			    goto bad;
			}
			else {
			    name = rootdevice;
			}
name_found:
			printf ("root on %s\n", name);
		}
		for (gc = genericconf; gc->gc_name; gc++)
			if (gc->gc_name[0] == name[0] &&
			    gc->gc_name[1] == name[1])
				goto gotit;
		goto bad;

gotit:
		if (gc->gc_root == NODEV) {
			goto found;
		}
		if (name[2] >= '0' && name[2] <= '7') {
			if (name[3] >= 'a' && name[3] <= 'h') {
				slice = name[3] - 'a';
			} else if (name[3]) {
				printf("bad partition number\n");
				goto bad;
			}
			unit = name[2] - '0';
			goto found;
		}
		printf("bad/missing unit number\n");
bad:
		for (gc = genericconf; gc->gc_name; gc++)
			printf("%s%s%%d",
			       (gc == genericconf)?"use ":
				    (((gc+1)->gc_name)?", ":" or "),
			       gc->gc_name);
		printf("\n");
		boothowto |= RB_ASKNAME;
		goto retry;
found:
	       if (gc->gc_root == NODEV) {
				printf("mounting nfs root\n");
				nfsbootdevname = rootdevice;
				mountroot = nfs_mountroot;
				rootdev = NODEV;
	       } else {
				mountroot = ffs_mountroot;
				gc->gc_root = makedev(major(gc->gc_root), unit*8+slice);
				rootdev = gc->gc_root;
	       }
	}
	else
	{
#ifdef	BOOT_ARGS_PASSED

		boottype = kernBootStruct->rootdev;
		devmajor = (boottype >> B_TYPESHIFT) & B_TYPEMASK;
		devminor = (boottype >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
		devminor |= (((boottype >> B_UNITSHIFT) & B_UNITMASK) << 3);

		rootdev = makedev(devmajor, devminor);
#else
#if 0
		printf("mounting nfs root\n");
		if (!rootdevice[0])
		    strcpy(rootdevice, "en0");
		nfsbootdevname = rootdevice;
		mountroot = nfs_mountroot;
		rootdev = NODEV;
#else
		boothowto |= RB_ASKNAME;
		goto retry;
#endif
#endif
	}
		printf("rootdev %x, howto %x\n", rootdev, boothowto);

    if( panelUp)
	alert_done();
}

our_gets(cp, lp)
	char *cp, *lp;
{
	register c;

	for (;;) {
		c = cngetc() & 0177;
		switch (c) {
		case '\n':
		case '\r':
			*lp++ = '\0';
			return;
		case '\177':
			if (lp == cp) {
				cnputc('\b');
				continue;
			}
			cnputc('\b');
			cnputc('\b');
			/* fall into ... */
		case '\b':
			if (lp == cp) {
				cnputc('\b');
				continue;
			}
			cnputc(' ');
			cnputc('\b');
			lp--;
			continue;
		case '@':
		case 'u'&037:
			lp = cp;
			cnputc('\n');
			continue;
		default:
			*lp++ = c;
		}
	}
}

/*
 * If booted with ASKNAME, prompt on the console for a filesystem
 * name and return it.
 */
getfsname(askfor, name)
	char *askfor;
	char *name;
{

	if (boothowto & RB_ASKNAME) {
		printf("%s key [%s]: ", askfor, askfor);
		our_gets(name, name);
	}
}

static int
scsiControllerDetected(void)
{
    IOReturn rtn;
    IOObjectNumber i;
    IOString name, kind;
    Protocol **protos;
    id deviceId;
    int j;
    
    protos = [SCSIDisk requiredProtocols];
    if (protos == NULL || *protos == nil) {
	/*
	 * We can't search for a SCSI adapter,
	 * so don't say we didn't find one.
	 */
	return 1;
    }
    for(i = 0; ; i++) {
	rtn = [IODevice lookupByObjectNumber:i deviceKind:&kind 
		deviceName:&name];
	if (rtn != IO_R_SUCCESS && rtn != IO_R_OFFLINE)
	    break;
	rtn = IOGetObjectForDeviceName(name, &deviceId);
	if (rtn == IO_R_SUCCESS) {
	    int conforms = 1;
	    /* Check to see if it implements the correct protocols. */
	    for(j=0; protos[j]; j++) {
		    if(![deviceId conformsTo:protos[j]]) {
			conforms = 0;
			break;
		    }
	    }
	    if (conforms)
		return 1;
	}
    }
    return 0;
}

bsd_autoconf()
{
#if GDB
  if (IsPowerSurge())
    mace_init();
#endif
}