X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/0b4e3aa066abc0728aacb4bbeb86f53f9737156e..3a60a9f5b85abb8c2cf24e1926c5c7b3f608a5e2:/iokit/bsddev/IOKitBSDInit.cpp diff --git a/iokit/bsddev/IOKitBSDInit.cpp b/iokit/bsddev/IOKitBSDInit.cpp index ff860483f..d93930dd0 100644 --- a/iokit/bsddev/IOKitBSDInit.cpp +++ b/iokit/bsddev/IOKitBSDInit.cpp @@ -26,8 +26,6 @@ #include #include -#include - extern "C" { #include @@ -36,12 +34,12 @@ extern "C" { // how long to wait for matching root device, secs #define ROOTDEVICETIMEOUT 60 +extern dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys); +extern dev_t mdevlookup(int devid); kern_return_t IOKitBSDInit( void ) { - IOLog("IOKitBSDInit\n"); - IOService::publishResource("IOBSD"); return( kIOReturnSuccess ); @@ -75,26 +73,32 @@ OSDictionary * IOBSDNameMatching( const char * name ) return( 0 ); } -OSDictionary * IOCDMatching( const char * name ) +OSDictionary * IOUUIDMatching( void ) { - OSDictionary * dict; - const OSSymbol * str; - - dict = IOService::serviceMatching( "IOMedia" ); - if( dict == 0 ) { - IOLog("Unable to find IOMedia\n"); - return 0; - } + return IOService::resourceMatching( "boot-uuid-media" ); +} - str = OSSymbol::withCString( "CD_ROM_Mode_1" ); - if( str == 0 ) { - dict->release(); - return 0; - } - dict->setObject( "Content", (OSObject *)str ); - str->release(); - return( dict ); +OSDictionary * IOCDMatching( void ) +{ + OSDictionary * dict; + const OSSymbol * str; + + dict = IOService::serviceMatching( "IOMedia" ); + if( dict == 0 ) { + IOLog("Unable to find IOMedia\n"); + return 0; + } + + str = OSSymbol::withCString( "CD_ROM_Mode_1" ); + if( str == 0 ) { + dict->release(); + return 0; + } + + dict->setObject( "Content Hint", (OSObject *)str ); + str->release(); + return( dict ); } OSDictionary * IONetworkMatching( const char * path, @@ -253,6 +257,7 @@ OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) char * comp; long unit = -1; long partition = -1; + long lun = -1; char c; // scan the tail of the path for "@unit:partition" @@ -260,7 +265,7 @@ OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) // Have to get the full path to the controller - an alias may // tell us next to nothing, like "hd:8" alias = IORegistryEntry::dealiasPath( &path, gIODTPlane ); - + look = path + strlen( path); c = ':'; while( look != path) { @@ -269,7 +274,12 @@ OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) partition = strtol( look + 1, 0, 0 ); c = '@'; } else if( c == '@') { - unit = strtol( look + 1, 0, 16 ); + unit = strtol( look + 1, &comp, 16 ); + + if( *comp == ',') { + lun = strtol( comp + 1, 0, 16 ); + } + c = '/'; } else if( c == '/') { c = 0; @@ -285,29 +295,36 @@ OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) } if( c || unit == -1 || partition == -1) continue; - + maxLen -= strlen( "{" kIOPathMatchKey "='" kIODeviceTreePlane ":" ); maxLen -= ( alias ? strlen( alias ) : 0 ) + (look - path); - maxLen -= strlen( "/@hhhhhhhh:dddddddddd';}" ); + maxLen -= strlen( "/@hhhhhhhh,hhhhhhhh:dddddddddd';}" ); if( maxLen > 0) { sprintf( buf, "{" kIOPathMatchKey "='" kIODeviceTreePlane ":" ); comp = buf + strlen( buf ); - + if( alias) { strcpy( comp, alias ); comp += strlen( alias ); } - + if ( (look - path)) { strncpy( comp, path, look - path); comp += look - path; } - - sprintf( comp, "/@%lx:%ld';}", unit, partition ); + + if ( lun != -1 ) + { + sprintf ( comp, "/@%lx,%lx:%ld';}", unit, lun, partition ); + } + else + { + sprintf( comp, "/@%lx:%ld';}", unit, partition ); + } } else continue; - + return( OSDynamicCast(OSDictionary, OSUnserialize( buf, 0 )) ); } while( false ); @@ -317,13 +334,93 @@ OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen ) OSDictionary * IOOFPathMatching( const char * path, char * buf, int maxLen ) { + OSDictionary * matching; + OSString * str; + char * comp; + int len; + /* need to look up path, get device type, call matching help based on device type */ - return( IODiskMatching( path, buf, maxLen )); + matching = IODiskMatching( path, buf, maxLen ); + if( matching) + return( matching ); + + do { + + len = strlen( kIODeviceTreePlane ":" ); + maxLen -= len; + if( maxLen < 0) + continue; + + strcpy( buf, kIODeviceTreePlane ":" ); + comp = buf + len; + + len = strlen( path ); + maxLen -= len; + if( maxLen < 0) + continue; + strncpy( comp, path, len ); + comp[ len ] = 0; + + matching = OSDictionary::withCapacity( 1 ); + if( !matching) + continue; + + str = OSString::withCString( buf ); + if( !str) + continue; + matching->setObject( kIOPathMatchKey, str ); + str->release(); + + return( matching ); + + } while( false ); + + if( matching) + matching->release(); + + return( 0 ); +} +IOService * IOFindMatchingChild( IOService * service ) +{ + // find a matching child service + IOService * child = 0; + OSIterator * iter = service->getClientIterator(); + if ( iter ) { + while( ( child = (IOService *) iter->getNextObject() ) ) { + OSDictionary * dict = OSDictionary::withCapacity( 1 ); + if( dict == 0 ) { + iter->release(); + return 0; + } + const OSSymbol * str = OSSymbol::withCString( "Apple_HFS" ); + if( str == 0 ) { + dict->release(); + iter->release(); + return 0; + } + dict->setObject( "Content", (OSObject *)str ); + str->release(); + if ( child->compareProperty( dict, "Content" ) ) { + dict->release(); + break; + } + dict->release(); + IOService * subchild = IOFindMatchingChild( child ); + if ( subchild ) { + child = subchild; + break; + } + } + iter->release(); + } + return child; } +static int didRam = 0; + kern_return_t IOFindBSDRoot( char * rootName, dev_t * root, u_int32_t * oflags ) { @@ -334,9 +431,12 @@ kern_return_t IOFindBSDRoot( char * rootName, OSString * iostr; OSNumber * off; OSData * data = 0; + UInt32 *ramdParms = 0; UInt32 flags = 0; int minor, major; + bool findHFSChild = false; + char * mediaProperty = 0; char * rdBootVar; enum { kMaxPathBuf = 512, kMaxBootVar = 128 }; char * str; @@ -344,8 +444,12 @@ kern_return_t IOFindBSDRoot( char * rootName, int len; bool forceNet = false; bool debugInfoPrintedOnce = false; + const char * uuidStr = NULL; static int mountAttempts = 0; + + int xchar, dchar; + if( mountAttempts++) IOSleep( 5 * 1000 ); @@ -360,33 +464,102 @@ kern_return_t IOFindBSDRoot( char * rootName, rdBootVar[0] = 0; do { - if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) { + if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) { + data = (OSData *) regEntry->getProperty( "boot-uuid" ); + if( data) { + uuidStr = (const char*)data->getBytesNoCopy(); + OSString *uuidString = OSString::withCString( uuidStr ); + + // match the boot-args boot-uuid processing below + if( uuidString) { + IOLog("rooting via boot-uuid from /chosen: %s\n", uuidStr); + IOService::publishResource( "boot-uuid", uuidString ); + uuidString->release(); + matching = IOUUIDMatching(); + mediaProperty = "boot-uuid-media"; + regEntry->release(); + continue; + } else { + uuidStr = NULL; + } + } + + // else try for an OF Path data = (OSData *) regEntry->getProperty( "rootpath" ); regEntry->release(); - if( data) - continue; + if( data) continue; } if( (regEntry = IORegistryEntry::fromPath( "/options", gIODTPlane ))) { data = (OSData *) regEntry->getProperty( "boot-file" ); regEntry->release(); - if( data) - continue; + if( data) continue; } } while( false ); - if( data) + if( data && !uuidStr) look = (const char *) data->getBytesNoCopy(); if( rdBootVar[0] == '*') { look = rdBootVar + 1; - forceNet = false; + forceNet = false; } else { if( (regEntry = IORegistryEntry::fromPath( "/", gIODTPlane ))) { forceNet = (0 != regEntry->getProperty( "net-boot" )); - regEntry->release(); - } + regEntry->release(); + } } + + +// +// See if we have a RAMDisk property in /chosen/memory-map. If so, make it into a device. +// It will become /dev/mdx, where x is 0-f. +// + + if(!didRam) { /* Have we already build this ram disk? */ + didRam = 1; /* Remember we did this */ + if((regEntry = IORegistryEntry::fromPath( "/chosen/memory-map", gIODTPlane ))) { /* Find the map node */ + data = (OSData *)regEntry->getProperty("RAMDisk"); /* Find the ram disk, if there */ + if(data) { /* We found one */ + + ramdParms = (UInt32 *)data->getBytesNoCopy(); /* Point to the ram disk base and size */ + (void)mdevadd(-1, ramdParms[0] >> 12, ramdParms[1] >> 12, 0); /* Initialize it and pass back the device number */ + } + regEntry->release(); /* Toss the entry */ + } + } + +// +// Now check if we are trying to root on a memory device +// + + if((rdBootVar[0] == 'm') && (rdBootVar[1] == 'd') && (rdBootVar[3] == 0)) { + dchar = xchar = rdBootVar[2]; /* Get the actual device */ + if((xchar >= '0') && (xchar <= '9')) xchar = xchar - '0'; /* If digit, convert */ + else { + xchar = xchar & ~' '; /* Fold to upper case */ + if((xchar >= 'A') && (xchar <= 'F')) { /* Is this a valid digit? */ + xchar = (xchar & 0xF) + 9; /* Convert the hex digit */ + dchar = dchar | ' '; /* Fold to lower case */ + } + else xchar = -1; /* Show bogus */ + } + if(xchar >= 0) { /* Do we have a valid memory device name? */ + *root = mdevlookup(xchar); /* Find the device number */ + if(*root >= 0) { /* Did we find one? */ + + rootName[0] = 'm'; /* Build root name */ + rootName[1] = 'd'; /* Build root name */ + rootName[2] = dchar; /* Build root name */ + rootName[3] = 0; /* Build root name */ + IOLog("BSD root: %s, major %d, minor %d\n", rootName, major(*root), minor(*root)); + *oflags = 0; /* Show that this is not network */ + goto iofrootx; /* Join common exit... */ + } + panic("IOFindBSDRoot: specified root memory device, %s, has not been configured\n", rdBootVar); /* Not there */ + } + } + if( look) { // from OpenFirmware path IOLog("From path: \"%s\", ", look); @@ -397,8 +570,8 @@ kern_return_t IOFindBSDRoot( char * rootName, matching = IODiskMatching( look, str, kMaxPathBuf ); } } - - if( (!matching) && rdBootVar[0] ) { + + if( (!matching) && rdBootVar[0] ) { // by BSD name look = rdBootVar; if( look[0] == '*') @@ -406,8 +579,29 @@ kern_return_t IOFindBSDRoot( char * rootName, if ( strncmp( look, "en", strlen( "en" )) == 0 ) { matching = IONetworkNamePrefixMatching( "en" ); - } else if ( strncmp( look, "cdrom", strlen( "cdrom" )) == 0 ) { - matching = IOCDMatching( look ); + } else if ( strncmp( look, "cdrom", strlen( "cdrom" )) == 0 ) { + matching = IOCDMatching(); + findHFSChild = true; + } else if ( strncmp( look, "uuid", strlen( "uuid" )) == 0 ) { + char *uuid; + OSString *uuidString; + + uuid = (char *)IOMalloc( kMaxBootVar ); + + if ( uuid ) { + if (!PE_parse_boot_arg( "boot-uuid", uuid )) { + panic( "rd=uuid but no boot-uuid= specified" ); + } + uuidString = OSString::withCString( uuid ); + if ( uuidString ) { + IOService::publishResource( "boot-uuid", uuidString ); + uuidString->release(); + IOLog( "\nWaiting for boot volume with UUID %s\n", uuid ); + matching = IOUUIDMatching(); + mediaProperty = "boot-uuid-media"; + } + IOFree( uuid, kMaxBootVar ); + } } else { matching = IOBSDNameMatching( look ); } @@ -415,9 +609,9 @@ kern_return_t IOFindBSDRoot( char * rootName, if( !matching) { OSString * astring; - // any UFS + // any HFS matching = IOService::serviceMatching( "IOMedia" ); - astring = OSString::withCStringNoCopy("Apple_UFS"); + astring = OSString::withCStringNoCopy("Apple_HFS"); if ( astring ) { matching->setObject("Content", astring); astring->release(); @@ -459,6 +653,25 @@ kern_return_t IOFindBSDRoot( char * rootName, } while( !service); matching->release(); + if ( service && findHFSChild ) { + bool waiting = true; + // wait for children services to finish registering + while ( waiting ) { + t.tv_sec = ROOTDEVICETIMEOUT; + t.tv_nsec = 0; + if ( service->waitQuiet( &t ) == kIOReturnSuccess ) { + waiting = false; + } else { + IOLog( "Waiting for child registration\n" ); + } + } + // look for a subservice with an Apple_HFS child + IOService * subservice = IOFindMatchingChild( service ); + if ( subservice ) service = subservice; + } else if ( service && mediaProperty ) { + service = service->getProperty(mediaProperty); + } + major = 0; minor = 0; @@ -510,6 +723,7 @@ kern_return_t IOFindBSDRoot( char * rootName, IOFree( str, kMaxPathBuf + kMaxBootVar ); +iofrootx: if( (gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) && !debugInfoPrintedOnce) { IOService::getPlatform()->waitQuiet(); @@ -528,4 +742,35 @@ kern_return_t IOFindBSDRoot( char * rootName, return( kIOReturnSuccess ); } +void * +IOBSDRegistryEntryForDeviceTree(char * path) +{ + return (IORegistryEntry::fromPath(path, gIODTPlane)); +} + +void +IOBSDRegistryEntryRelease(void * entry) +{ + IORegistryEntry * regEntry = (IORegistryEntry *)entry; + + if (regEntry) + regEntry->release(); + return; +} + +const void * +IOBSDRegistryEntryGetData(void * entry, char * property_name, + int * packet_length) +{ + OSData * data; + IORegistryEntry * regEntry = (IORegistryEntry *)entry; + + data = (OSData *) regEntry->getProperty(property_name); + if (data) { + *packet_length = data->getLength(); + return (data->getBytesNoCopy()); + } + return (NULL); +} + } /* extern "C" */