|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: #include <IOKit/IOBSD.h>
23: #include <IOKit/IOLib.h>
24: #include <IOKit/IOService.h>
25: #include <IOKit/IODeviceTreeSupport.h>
26: #include <IOKit/IOKitKeys.h>
27: #include <IOKit/storage/IOMedia.h>
28:
29: #include <sys/disklabel.h>
30:
31: extern "C" {
32:
33: #include <pexpert/pexpert.h>
34: #include <kern/clock.h>
35:
36: // how long to wait for matching root device, secs
37: #define ROOTDEVICETIMEOUT 60
38:
39:
40: kern_return_t
41: IOKitBSDInit( void )
42: {
43: IOLog("IOKitBSDInit\n");
44:
45: IOService::publishResource("IOBSD");
46:
47: return( kIOReturnSuccess );
48: }
49:
50: OSDictionary * IOBSDNameMatching( const char * name )
51: {
52: OSDictionary * dict;
53: const OSSymbol * str = 0;
54:
55: do {
56:
57: dict = IOService::serviceMatching( gIOServiceKey );
58: if( !dict)
59: continue;
60: str = OSSymbol::withCString( name );
61: if( !str)
62: continue;
63: dict->setObject( kIOBSDName, (OSObject *) str );
64: str->release();
65:
66: return( dict );
67:
68: } while( false );
69:
70: if( dict)
71: dict->release();
72: if( str)
73: str->release();
74:
75: return( 0 );
76: }
77:
78: OSDictionary * IONetworkMatching( const char * path,
79: char * buf, int maxLen )
80: {
81: OSDictionary * matching = 0;
82: OSDictionary * dict;
83: OSString * str;
84: char * comp;
85: const char * skip;
86: int len;
87:
88: do {
89:
90: len = strlen( kIODeviceTreePlane ":" );
91: maxLen -= len;
92: if( maxLen < 0)
93: continue;
94:
95: strcpy( buf, kIODeviceTreePlane ":" );
96: comp = buf + len;
97:
98: // remove parameters following ':' from the path
99: skip = strchr( path, ':');
100: if( !skip)
101: continue;
102:
103: len = skip - path;
104: maxLen -= len;
105: if( maxLen < 0)
106: continue;
107: strncpy( comp, path, len );
108: comp[ len ] = 0;
109:
110: matching = IOService::serviceMatching( "IONetworkInterface" );
111: if( !matching)
112: continue;
113: dict = IOService::addLocation( matching );
114: if( !dict)
115: continue;
116:
117: str = OSString::withCString( buf );
118: if( !str)
119: continue;
120: dict->setObject( kIOPathMatchKey, str );
121: str->release();
122:
123: return( matching );
124:
125: } while( false );
126:
127: if( matching)
128: matching->release();
129:
130: return( 0 );
131: }
132:
133: OSDictionary * IODiskMatching( const char * path, char * buf, int maxLen )
134: {
135: OSDictionary * matching = 0;
136: const char * look;
137: const char * skip;
138: const char * alias;
139: char * comp;
140: UInt32 unit = 0x99;
141: UInt32 partition = 0xaa;
142: int len;
143: char c;
144:
145: // scan the tail of the path for "@unit:partition"
146: do {
147: // Have to get the full path to the controller - an alias may
148: // tell us next to nothing, like "hd:8"
149: skip = path;
150: alias = IORegistryEntry::dealiasPath( &skip, gIODTPlane );
151:
152: look = skip + strlen( skip);
153: c = ':';
154: while( c && (look != skip)) {
155: if( *(--look) == c) {
156: if( c == ':') {
157: partition = strtol( look + 1, 0, 0 );
158: c = '@';
159: } else if( c == '@') {
160: unit = strtol( look + 1, 0, 16 );
161: c = '/';
162: } else if( c == '/')
163: c = 0;
164: }
165:
166: if( alias && (look == skip)) {
167: skip = alias;
168: look = skip + strlen( skip);
169: alias = 0;
170: }
171: }
172: if( c)
173: continue;
174:
175: #define diskMatch1 \
176: "{" \
177: kIOProviderClassKey"=IOMedia;" \
178: "'IOPath Separator'=':';" \
179: "'IOPath Extension'='%ld';" \
180: kIOLocationMatchKey"={" \
181: "IOUnit=%ld:32;" \
182: kIOLocationMatchKey"={" \
183: kIOPathMatchKey"='"
184: #define diskMatch2 \
185: "';" \
186: "};" \
187: "};" \
188: "}"
189:
190: sprintf( buf, diskMatch1, partition, unit );
191:
192: len = strlen( buf );
193: comp = buf + len;
194:
195: maxLen -= len;
196: maxLen -= (look - skip) + strlen( kIODeviceTreePlane) + 1;
197: if( alias) {
198: len = strlen( alias );
199: maxLen -= len;
200: }
201: if( maxLen > 0) {
202: strcpy( comp, kIODeviceTreePlane);
203: comp += strlen( kIODeviceTreePlane);
204: *(comp++) = ':';
205: if( alias) {
206: strcpy( comp, alias );
207: comp += len;
208: }
209: len = look - skip;
210: strncpy( comp, skip, len);
211: comp += len;
212: } else
213: continue;
214:
215: strcpy( comp, diskMatch2 );
216:
217: matching = OSDynamicCast(OSDictionary, OSUnserialize( buf, 0 ));
218: if (!matching)
219: continue;
220:
221: return( matching );
222:
223: } while( false );
224:
225: if( matching)
226: matching->release();
227:
228: return( 0 );
229: }
230:
231: kern_return_t IOFindBSDRoot( char * rootName,
232: dev_t * root, u_int32_t * oflags )
233: {
234: mach_timespec_t t;
235: IOService * service;
236: IORegistryEntry * regEntry;
237: OSDictionary * matching = 0;
238: OSString * iostr;
239: OSNumber * off;
240: OSData * data = 0;
241:
242: UInt32 flags = 0;
243: int minor, major;
244: char * rdBootVar;
245: enum { kMaxPathBuf = 512, kMaxBootVar = 128 };
246: char * str;
247: const char * look = 0;
248: int len;
249: bool forceNet = false;
250:
251: static int mountAttempts = 0;
252:
253: if( mountAttempts++)
254: IOSleep( 5 * 1000 );
255:
256: str = (char *) IOMalloc( kMaxPathBuf + kMaxBootVar );
257: if( !str)
258: return( kIOReturnNoMemory );
259: rdBootVar = str + kMaxPathBuf;
260:
261: if (!PE_parse_boot_arg("rd", rdBootVar )
262: && !PE_parse_boot_arg("rootdev", rdBootVar ))
263: rdBootVar[0] = 0;
264:
265: do {
266: if( (regEntry = IORegistryEntry::fromPath( "/chosen", gIODTPlane ))) {
267: data = (OSData *) regEntry->getProperty( "rootpath" );
268: regEntry->release();
269: if( data)
270: continue;
271: }
272: if( (regEntry = IORegistryEntry::fromPath( "/options", gIODTPlane ))) {
273: data = (OSData *) regEntry->getProperty( "boot-file" );
274: regEntry->release();
275: if( data)
276: continue;
277: }
278: } while( false );
279:
280: if( data)
281: look = (const char *) data->getBytesNoCopy();
282:
283: if( rdBootVar[0] == '*') {
284: look = rdBootVar + 1;
285: forceNet = false;
286: } else {
287: if( (regEntry = IORegistryEntry::fromPath( "/", gIODTPlane ))) {
288: forceNet = (0 != regEntry->getProperty( "net-boot" ));
289: regEntry->release();
290: }
291: }
292:
293: if( look) {
294: // from OpenFirmware path
295: IOLog("From path: \"%s\", ", look);
296:
297: if( forceNet || (0 == strncmp( look, "enet", strlen( "enet" ))) )
298: matching = IONetworkMatching( look, str, kMaxPathBuf );
299: else
300: matching = IODiskMatching( look, str, kMaxPathBuf );
301: }
302:
303: if( (!matching) && rdBootVar[0] ) {
304: // by BSD name
305: look = rdBootVar;
306: if( look[0] == '*')
307: look++;
308: matching = IOBSDNameMatching( look );
309: }
310:
311: if( !matching) {
312: OSString * astring;
313: // any UFS
314: matching = IOService::serviceMatching( "IOMedia" );
315: astring = OSString::withCStringNoCopy("Apple_UFS");
316: if ( astring ) {
317: matching->setObject(kIOMediaContent, astring);
318: astring->release(); // XXX -- svail: added.
319: }
320: }
321:
322: if( true && matching) {
323: OSSerialize * s = OSSerialize::withCapacity( 5 );
324:
325: if( matching->serialize( s )) {
326: IOLog( "Waiting on %s\n", s->text() );
327: s->release();
328: }
329: }
330:
331: IOService::waitForService(IOService::serviceMatching("IOMediaBSDClient"));
332:
333: do {
334: t.tv_sec = ROOTDEVICETIMEOUT;
335: t.tv_nsec = 0;
336: matching->retain();
337: service = IOService::waitForService( matching, &t );
338: if( (!service) || (mountAttempts == 10)) {
339: PE_display_icon( 0, "noroot");
340: IOLog( "Still waiting for root device\n" );
341: }
342: } while( !service);
343: matching->release();
344:
345: major = 0;
346: minor = 0;
347:
348: if( service) {
349:
350: len = kMaxPathBuf;
351: service->getPath( str, &len, gIOServicePlane );
352: IOLog( "Got boot device = %s\n", str );
353:
354: iostr = (OSString *) service->getProperty( kIOBSDName );
355: if( iostr)
356: strcpy( rootName, iostr->getCStringNoCopy() );
357: off = (OSNumber *) service->getProperty( kIOBSDMajor );
358: if( off)
359: major = off->unsigned32BitValue();
360: off = (OSNumber *) service->getProperty( kIOBSDMinor );
361: if( off)
362: minor = off->unsigned32BitValue();
363:
364: if( service->metaCast( "IONetworkInterface" ))
365: flags |= 1;
366:
367: } else {
368:
369: IOLog( "Wait for root failed\n" );
370: strcpy( rootName, "en0");
371: flags |= 1;
372: }
373:
374: IOLog( "BSD root: %s", rootName );
375: if( major)
376: IOLog(", major %d, minor %d\n", major, minor );
377: else
378: IOLog("\n");
379:
380: *root = makedev( major, minor );
381: *oflags = flags;
382:
383: IOFree( str, kMaxPathBuf + kMaxBootVar );
384:
385: if( gIOKitDebug & (kIOLogDTree | kIOLogServiceTree | kIOLogMemory)) {
386:
387: IOSleep(10 * 1000);
388: // IOService::getPlatform()->waitQuiet();
389: if( gIOKitDebug & kIOLogDTree) {
390: IOLog("\nDT plane:\n");
391: IOPrintPlane( gIODTPlane );
392: }
393: if( gIOKitDebug & kIOLogServiceTree) {
394: IOLog("\nService plane:\n");
395: IOPrintPlane( gIOServicePlane );
396: }
397: if( gIOKitDebug & kIOLogMemory)
398: IOPrintMemory();
399: }
400:
401: return( kIOReturnSuccess );
402: }
403:
404: } /* extern "C" */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.