]> git.saurik.com Git - apple/system_cmds.git/blob - kextd.tproj/PEFSupport.c
system_cmds-175.tar.gz
[apple/system_cmds.git] / kextd.tproj / PEFSupport.c
1 /*
2 * Copyright (c) 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 /*
23 File: UnpackPiData.c
24 Written by: Jeffrey Robbin
25 Copyright: © 1994, 1996 by Apple Computer, Inc., all rights reserved.
26
27 File: GetSymbolFromPEF.c
28 Written by: Jeffrey Robbin
29 Copyright: © 1994, 1996 by Apple Computer, Inc., all rights reserved.
30 */
31
32 #include <IOKit/IOKitLib.h>
33 #include <IOKit/kext/KEXTManager.h>
34 #include <stdlib.h>
35 #include <err.h>
36 #include <sys/file.h>
37 #include <nlist.h>
38 #include <stdio.h>
39 #include <unistd.h>
40 #include <sys/param.h>
41 #include <sys/stat.h>
42 #include <sys/errno.h>
43 #include <paths.h>
44
45 #include <mach/mach.h>
46 #include <mach/mach_error.h>
47 #include <mach/mach_host.h>
48
49 #include "GetSymbolFromPEF.h"
50
51 static unsigned char
52 PEFGetNextByte (unsigned char** rawBuffer, long* rawBufferRemaining)
53 {
54 *rawBufferRemaining = *rawBufferRemaining - 1;
55 return *(*rawBuffer)++;
56 }
57
58
59 static unsigned long
60 PEFGetCount(unsigned char** rawBuffer, long* rawBufferRemaining)
61 {
62 register unsigned char b;
63 register unsigned long value = 0UL;
64
65 /* Scan the count value. All required bytes MUST be present... */
66
67 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
68 if (!IS_LAST_PICNT_BYTE(b)) { /* if 1st byte is not that last... */
69 value = CONCAT_PICNT(value, b); /* ...init value using 1st byte */
70
71 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
72 if (!IS_LAST_PICNT_BYTE(b)) { /* if 2nd byte is not the last... */
73 value = CONCAT_PICNT(value, b); /* ...add in 2nd byte */
74
75 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
76 if (!IS_LAST_PICNT_BYTE(b)) { /* if 3rd byte is not the last... */
77 value = CONCAT_PICNT(value, b); /* ...add in 3rd byte */
78
79 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
80 if (!IS_LAST_PICNT_BYTE(b)) { /* if 4th byte is not the last... */
81 value = CONCAT_PICNT(value, b); /* ...add in 4th byte */
82
83 /* 5th byte is definitly last! */
84 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
85 }
86 }
87 }
88 }
89
90 value = CONCAT_PICNT(value, b); /* add in "last" byte (whichever one) */
91
92 return (value);
93 }
94
95
96
97 // UnpackPiData expands a compressed section into memory.
98
99 static OSErr
100 UnpackPiData (LogicalAddress thePEFPtr,
101 SectionHeaderPtr sectionHeaderPtr,
102 LogicalAddress* theData)
103 {
104 long cntX, cnt, rpt, dcnt, delta;
105 unsigned char op, b;
106 unsigned char* unpackBuffer;
107 unsigned char* originalUnpackBuffer;
108 unsigned char* endUnpackBuffer;
109 unsigned char* oldRawBuffer;
110 long oldRawBufferRemaining;
111 unsigned char* rawBuffer;
112 long rawBufferRemaining;
113
114 // Verify incoming section is packed.
115 if (sectionHeaderPtr->regionKind != kPIDataSection)
116 return (paramErr);
117
118
119 // Allocate memory to unpack into
120 originalUnpackBuffer = (unsigned char*)NewPtrSys(sectionHeaderPtr->initSize);
121 if (originalUnpackBuffer == nil)
122 return memFullErr;
123
124 unpackBuffer = originalUnpackBuffer;
125 endUnpackBuffer = unpackBuffer + sectionHeaderPtr->initSize;
126 rawBuffer = (unsigned char*)((unsigned long)thePEFPtr + sectionHeaderPtr->containerOffset);
127 rawBufferRemaining = sectionHeaderPtr->rawSize;
128
129
130 /* Expand the pidata instructions. EOF will terminate processing through the setjmp */
131 /* on pidData_jmpbuf above... */
132
133 while (rawBufferRemaining > 0) {
134
135 /* The first byte of each instruction contains the opcode and a count. If the count */
136 /* is 0, the count starts in the next byte... */
137
138 /* Pick up the opcode and first count operand... */
139
140 b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
141
142 op = PIOP(b);
143 cnt = PICNT(b);
144
145 if (cnt == 0)
146 cnt = PEFGetCount(&rawBuffer, &rawBufferRemaining);
147
148 /* Unpack the data as a function of the opcode... */
149
150 switch (op) {
151 case kZero: /* zero out cnt bytes...*/
152 if (unpackBuffer + cnt > endUnpackBuffer)
153 goto Error;
154 memset(unpackBuffer, 0, cnt);
155 unpackBuffer += cnt;
156 break;
157
158 case kBlock: /* copy cnt bytes...*/
159 if (unpackBuffer + cnt > endUnpackBuffer)
160 goto Error;
161 while (--cnt >= 0)
162 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
163 break;
164
165 case kRepeat: /* copy cnt bytes rpt times...*/
166 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining) + 1;
167
168 if (cnt == 1)
169 {
170 if (unpackBuffer + rpt > endUnpackBuffer)
171 goto Error;
172 b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
173 memset(unpackBuffer, b, rpt);
174 unpackBuffer += rpt;
175 }
176 else
177 {
178 oldRawBufferRemaining = rawBufferRemaining;
179 oldRawBuffer = rawBuffer;
180 while (--rpt >= 0) {
181 if (unpackBuffer + cnt > endUnpackBuffer)
182 goto Error;
183 rawBufferRemaining = oldRawBufferRemaining;
184 rawBuffer = oldRawBuffer;
185 cntX = cnt;
186 while (--cntX >= 0)
187 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
188 }
189 }
190 break;
191
192 case kRepeatZero: /* copy cnt 0's and dcnt bytes rpt times*/
193 dcnt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* ...then copy cnt more 0's */
194 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining);
195
196 goto rptPart1; /* jump into loop to copy 0's first... */
197
198 while (--rpt >= 0) {
199 if (unpackBuffer + dcnt > endUnpackBuffer)
200 goto Error;
201 cntX = dcnt; /* cnt repeating parts follow each other*/
202 while (--cntX >= 0)
203 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
204 rptPart1: /* non-repeating part is always 0's... */
205 if (unpackBuffer + cnt > endUnpackBuffer)
206 goto Error;
207 memset(unpackBuffer, 0, cnt);
208 unpackBuffer += cnt;
209 }
210
211 break;
212
213 case kRepeatBlock: /* copy cnt repeating bytes and dcnt */
214 dcnt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* non-repating bytes rcnt times... */
215 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* ...then copy cnt repeating bytes */
216
217 oldRawBufferRemaining = rawBufferRemaining;
218 oldRawBuffer = rawBuffer;
219 delta = 0; /* the repeating part and each non-rep */
220
221 goto rptPart2; /* jump into loop to copy rptng part 1st*/
222
223 while (--rpt >= 0) {
224 if (unpackBuffer + dcnt > endUnpackBuffer)
225 goto Error;
226
227 rawBuffer = oldRawBuffer + cnt + delta;
228 rawBufferRemaining = oldRawBufferRemaining - (cnt + delta);
229 cntX = dcnt;
230 while (--cntX >= 0)
231 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
232 delta += dcnt;
233 rptPart2:
234 if (unpackBuffer + cnt > endUnpackBuffer)
235 goto Error;
236 rawBuffer = oldRawBuffer;
237 rawBufferRemaining = oldRawBufferRemaining;
238 cntX = cnt;
239 while (--cntX >= 0)
240 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
241 }
242
243 rawBuffer = oldRawBuffer + cnt + delta;
244 rawBufferRemaining = oldRawBufferRemaining - (cnt + delta);
245 break;
246
247 default:
248 goto Error;
249 } /* switch */
250 } /* for */
251
252 *theData = originalUnpackBuffer;
253
254 return noErr;
255
256 Error:
257 if (unpackBuffer)
258 DisposePtr((Ptr)originalUnpackBuffer);
259
260 *theData = nil;
261
262 return paramErr;
263 }
264
265 // GetSymbolFromPEF will extract from a PEF container the data associated
266 // with a given symbol name. It requires that the PEF file have been previously
267 // loaded into memory.
268
269 static OSStatus
270 GetSymbolFromPEF( StringPtr theSymbolName,
271 const LogicalAddress thePEFPtr,
272 LogicalAddress theSymbolPtr,
273 ByteCount theSymbolSize )
274 {
275 ContainerHeaderPtr containerHeaderPtr; // Pointer to the Container Header
276 SectionHeaderPtr loaderSectionPtr; // Pointer to the Loader Section Header
277 SectionHeaderPtr exportSectionPtr; // Pointer to the Section Header with the symbol
278 short currentSection;
279 Boolean foundSection;
280 Boolean foundSymbol;
281 long numExportSymbols;
282 LoaderHeaderPtr loaderHeaderPtr;
283 ExportSymbolEntryPtr exportSymbolEntryPtr;
284 LoaderExportChainEntryPtr exportChainEntryPtr;
285 StringPtr exportSymbolName;
286 LogicalAddress expandedDataPtr;
287 unsigned char* sourceDataPtr;
288 unsigned char* destDataPtr;
289
290
291 containerHeaderPtr = (ContainerHeaderPtr)thePEFPtr;
292
293 // Does the magic cookie match?
294 if (containerHeaderPtr->magicCookie != 'Joy!')
295 return cfragFragmentFormatErr;
296
297 // Is this a known PEF container format?
298 if (containerHeaderPtr->containerID != 'peff')
299 return cfragFragmentFormatErr;
300
301 // Validate parameters
302 if (theSymbolPtr == nil)
303 return paramErr;
304
305
306 // Find the loader section.
307 foundSection = false;
308 for (currentSection = 0; currentSection < containerHeaderPtr->nbrOfSections; currentSection++)
309 {
310 loaderSectionPtr = (SectionHeaderPtr)( (unsigned long)containerHeaderPtr +
311 sizeof(ContainerHeader) +
312 (sizeof(SectionHeader) * currentSection));
313 if (loaderSectionPtr->regionKind == kLoaderSection)
314 {
315 foundSection = true;
316 break;
317 }
318 }
319
320 if (foundSection == false)
321 return cfragNoSectionErr;
322
323 // Get the number of export symbols.
324 loaderHeaderPtr = (LoaderHeaderPtr)((unsigned long)thePEFPtr + loaderSectionPtr->containerOffset);
325 numExportSymbols = loaderHeaderPtr->nbrExportSyms;
326
327 // Start at the first exported symbol.
328 exportSymbolEntryPtr = (ExportSymbolEntryPtr)( (unsigned long)loaderHeaderPtr +
329 loaderHeaderPtr->slotTblOffset +
330 (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz)) +
331 (sizeof(LoaderExportChainEntry) * numExportSymbols));
332
333 exportChainEntryPtr = (LoaderExportChainEntryPtr)( (unsigned long)loaderHeaderPtr +
334 loaderHeaderPtr->slotTblOffset +
335 (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz)));
336
337 foundSymbol = false;
338 while (numExportSymbols-- > 0)
339 {
340 exportSymbolName = (StringPtr)( (unsigned long)loaderHeaderPtr +
341 loaderHeaderPtr->strTblOffset +
342 (exportSymbolEntryPtr->class_and_name & 0x00FFFFFF));
343 if (SymbolCompare(theSymbolName, exportSymbolName, exportChainEntryPtr->_h._h_h._nameLength))
344 {
345 foundSymbol = true;
346 break;
347 }
348 exportSymbolEntryPtr = (ExportSymbolEntryPtr)(((int)exportSymbolEntryPtr) + 10);
349 exportChainEntryPtr++;
350 }
351
352 if (foundSymbol == false)
353 return cfragNoSymbolErr;
354
355
356 // Found the symbol, so... let's go get the data!
357
358 exportSectionPtr = (SectionHeaderPtr)( (unsigned long)containerHeaderPtr +
359 sizeof(ContainerHeader) +
360 (sizeof(SectionHeader) * exportSymbolEntryPtr->sectionNumber));
361
362 expandedDataPtr = nil;
363
364 switch (exportSectionPtr -> regionKind)
365 {
366 case kPIDataSection:
367
368 // Expand the data! (Not yet... :)
369
370 if (UnpackPiData (thePEFPtr, exportSectionPtr, &expandedDataPtr) != noErr)
371 return cfragFragmentCorruptErr;
372
373 sourceDataPtr = (unsigned char*)((unsigned long)expandedDataPtr +
374 exportSymbolEntryPtr->address);
375 break;
376
377 default:
378 sourceDataPtr = (unsigned char*)((unsigned long)thePEFPtr +
379 exportSectionPtr->containerOffset +
380 exportSymbolEntryPtr->address);
381 break;
382 }
383
384
385 // Copy the data!
386
387 destDataPtr = (unsigned char*)theSymbolPtr;
388
389
390 while (theSymbolSize-- > 0)
391 *destDataPtr++ = *sourceDataPtr++;
392
393
394 // Cleanup any expanded data
395
396 if (expandedDataPtr != nil)
397 DisposePtr((Ptr)expandedDataPtr);
398
399 return noErr;
400 }
401
402
403 static IOByteCount GetPEFLen ( LogicalAddress thePEFPtr)
404 {
405 ContainerHeaderPtr containerHeaderPtr; // Pointer to the Container Header
406 SectionHeaderPtr sections;
407 short currentSection;
408 long lastOffset = 0;
409 long len = 0;
410
411 containerHeaderPtr = (ContainerHeaderPtr)thePEFPtr;
412
413 // Does the magic cookie match?
414 if (containerHeaderPtr->magicCookie != 'Joy!')
415 return 0;
416
417 // Is this a known PEF container format?
418 if (containerHeaderPtr->containerID != 'peff')
419 return 0;
420
421 // Find the loader section.
422 sections = (SectionHeaderPtr) (containerHeaderPtr + 1);
423 for (currentSection = 0; currentSection < containerHeaderPtr->nbrOfSections; currentSection++)
424 {
425 if( sections[currentSection].containerOffset > lastOffset) {
426 lastOffset = sections[currentSection].containerOffset;
427 len = sections[currentSection].rawSize;
428 }
429 }
430
431 return( lastOffset + len );
432 }
433
434 //
435 // SymbolCompare
436 //
437 // theExportSymbol is NOT null-terminated, so use theExportSymbolLength.
438 //
439 static Boolean SymbolCompare ( StringPtr theLookedForSymbol,
440 StringPtr theExportSymbol,
441 unsigned long theExportSymbolLength)
442 {
443 unsigned char* p1 = (unsigned char*)theLookedForSymbol;
444 unsigned char* p2 = (unsigned char*)theExportSymbol;
445
446 // Same length?
447 // (skip over p string len byte)
448 if ( theExportSymbolLength != *p1++ )
449 return false;
450
451 while ( theExportSymbolLength-- != 0 )
452 {
453 if ( *p1++ != *p2++ )
454 return false;
455 }
456
457 return true;
458 }
459
460 static int
461 readFile(char *path, char **objAddr, long *objSize)
462 {
463 int fd;
464 int err;
465 struct stat stat_buf;
466
467 *objAddr = 0;
468 *objSize = 0;
469
470 if((fd = open(path, O_RDONLY)) == -1)
471 return errno;
472
473 do {
474 if(fstat(fd, &stat_buf) == -1) {
475 err = errno;
476 continue;
477 }
478 *objSize = stat_buf.st_size;
479
480 if( KERN_SUCCESS != map_fd(fd, 0, (vm_offset_t *) objAddr, TRUE, *objSize)) {
481 *objAddr = 0;
482 *objSize = 0;
483 err = errno;
484 continue;
485 }
486
487 err = 0;
488
489 } while( false );
490
491 close(fd);
492
493 return( err );
494 }
495
496
497 // The Driver Description
498 enum {
499 kInitialDriverDescriptor = 0,
500 kVersionOneDriverDescriptor = 1,
501 kTheDescriptionSignature = 'mtej',
502 };
503
504 struct DriverType {
505 unsigned char nameInfoStr[32]; // Driver Name/Info String
506 unsigned long version; // Driver Version Number - really NumVersion
507 };
508 typedef struct DriverType DriverType;
509
510 struct DriverDescription {
511 unsigned long driverDescSignature; // Signature field of this structure
512 unsigned long driverDescVersion; // Version of this data structure
513 DriverType driverType; // Type of Driver
514 char otherStuff[512];
515 };
516 typedef struct DriverDescription DriverDescription;
517
518 static void
519 ExaminePEF( mach_port_t masterPort, char *pef, IOByteCount pefLen, CFArrayRef okList )
520 {
521 char descripName[] = "\pTheDriverDescription";
522 long err;
523 DriverDescription descrip;
524 DriverDescription curDesc;
525 char matchName[40];
526 char okName[40];
527 unsigned long newVersion;
528 unsigned long curVersion;
529 IOReturn kr;
530 io_iterator_t iter;
531 io_service_t service;
532 io_service_t child;
533 io_string_t path;
534 CFStringRef ndrvPropName = CFSTR("driver,AAPL,MacOS,PowerPC");
535 CFDataRef ndrv;
536 CFMutableDictionaryRef dict;
537 CFIndex index;
538 CFStringRef okStr;
539 Boolean ok;
540
541 err = GetSymbolFromPEF(descripName, pef, &descrip, sizeof(descrip));
542 if(err != 0) {
543 printf("\nGetSymbolFromPEF returns %ld\n",err);
544 return;
545 }
546 if((descrip.driverDescSignature != kTheDescriptionSignature) ||
547 (descrip.driverDescVersion != kInitialDriverDescriptor))
548 return;
549
550 strncpy(matchName, descrip.driverType.nameInfoStr + 1,
551 descrip.driverType.nameInfoStr[0]);
552 matchName[ descrip.driverType.nameInfoStr[0] ] = 0;
553
554 ok = (!okList);
555 for( index = 0; (!ok) && (index < CFArrayGetCount(okList)); index++) {
556 okStr = CFArrayGetValueAtIndex( okList, index);
557 if( CFStringGetTypeID() != CFGetTypeID(okStr))
558 continue;
559 ok = CFStringGetCString( okStr, okName, sizeof(okName),
560 kCFStringEncodingMacRoman)
561 && (0 == strcmp( okName, matchName));
562 }
563
564 newVersion = descrip.driverType.version;
565 if((newVersion & 0xffff) == 0x8000) // final stage, release rev
566 newVersion |= 0xff;
567
568 IOMasterPort(mach_task_self(), &masterPort);
569
570 kr = IOServiceGetMatchingServices(masterPort,
571 IOServiceNameMatching(matchName),
572 &iter);
573 if( kIOReturnSuccess != kr)
574 return;
575
576 for(
577 ;
578 (service = IOIteratorNext(iter));
579 IOObjectRelease(service)) {
580
581 kr = IORegistryEntryGetPath( service, kIOServicePlane, path );
582 if( kIOReturnSuccess == kr)
583 printf("Name %s matches %s, ", matchName, path);
584 if( !ok) {
585 printf("(skipping)\n");
586 continue;
587 }
588
589 ndrv = (CFDataRef) IORegistryEntryCreateCFProperty( service, ndrvPropName,
590 kCFAllocatorDefault, kNilOptions );
591
592 if( ndrv) {
593 err = GetSymbolFromPEF( descripName, CFDataGetBytePtr(ndrv),
594 &curDesc, sizeof(curDesc));
595 if (err != noErr)
596 printf("GetSymbolFromPEF returns %ld\n",err);
597 else {
598 if((curDesc.driverDescSignature == kTheDescriptionSignature) &&
599 (curDesc.driverDescVersion == kInitialDriverDescriptor)) {
600
601 curVersion = curDesc.driverType.version;
602 printf("new version %08lx, current version %08lx\n", newVersion, curVersion);
603 if((curVersion & 0xffff) == 0x8000) // final stage, release rev
604 curVersion |= 0xff;
605
606 if( newVersion <= curVersion)
607 pefLen = 0;
608 }
609 }
610 CFRelease(ndrv);
611 }
612
613 if( pefLen == 0)
614 continue;
615
616 ndrv = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
617 pef, pefLen, kCFAllocatorNull);
618 if( ndrv == 0)
619 continue;
620 printf("Installing ndrv (");
621 dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
622 &kCFTypeDictionaryKeyCallBacks,
623 &kCFTypeDictionaryValueCallBacks);
624
625 if( dict) {
626 CFDictionarySetValue(dict, ndrvPropName, ndrv);
627 kr = IORegistryEntryGetChildEntry( service, kIOServicePlane, &child );
628 if( kr == kIOReturnSuccess) {
629 kr = IORegistryEntrySetCFProperties( child, dict );
630 IOObjectRelease( child );
631 }
632 CFRelease( dict);
633 } else
634 kr = kIOReturnNoMemory;
635
636 CFRelease(ndrv);
637 printf("%08x)\n", kr);
638 }
639 IOObjectRelease( iter );
640
641 return;
642 }
643
644 int
645 PEFExamineFile( mach_port_t masterPort, CFURLRef file )
646 {
647 char * pefBytes;
648 char * plistBytes;
649 char * pef;
650 long pefFileLen, plistLen;
651 IOByteCount pefLen, pos = 0;
652 int err;
653 CFDictionaryRef props = 0;
654 CFDataRef data = 0;
655 CFArrayRef okList = 0;
656 enum { kIOCFMaxPathSize = 1026 };
657 char cFile[kIOCFMaxPathSize];
658
659 if (CFURLGetFileSystemRepresentation(file, TRUE, cFile, kIOCFMaxPathSize))
660 err = readFile(cFile, &pefBytes, &pefFileLen);
661 else
662 err = kIOReturnIOError;
663 if( err)
664 return( err);
665
666 do {
667 strcat( cFile, ".plist");
668 err = readFile(cFile, &plistBytes, &plistLen);
669 if( err)
670 continue;
671
672 data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault,
673 plistBytes, plistLen, kCFAllocatorNull);
674 if( !data)
675 continue;
676 props = (CFDictionaryRef) CFPropertyListCreateFromXMLData(
677 kCFAllocatorDefault, data, kCFPropertyListImmutable, 0 );
678 if( !props)
679 continue;
680 if( CFDictionaryGetTypeID() != CFGetTypeID(props))
681 continue;
682
683 okList = CFDictionaryGetValue( props, CFSTR("IONDRVList") );
684 if( CFArrayGetTypeID() != CFGetTypeID(okList))
685 okList = 0;
686
687 } while( false );
688
689 pef = pefBytes;
690 while( (pos < pefFileLen) && (pefLen = GetPEFLen( pef ))) {
691 ExaminePEF( masterPort, pef, pefLen, okList );
692 pefLen = (pefLen + 15) & ~15;
693 pef += pefLen;
694 pos += pefLen;
695 }
696
697 if( data)
698 CFRelease(data);
699 if( props)
700 CFRelease(props);
701
702 if( plistBytes)
703 vm_deallocate( mach_task_self(), (vm_address_t) plistBytes, plistLen );
704 if( pefBytes)
705 vm_deallocate( mach_task_self(), (vm_address_t) pefBytes, pefFileLen );
706
707 return( 0 );
708 }
709
710
711