1/* 2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 File: UnpackPiData.c 25 Written by: Jeffrey Robbin 26 Copyright: � 1994, 1996 by Apple Computer, Inc., all rights reserved. 27 28 File: GetSymbolFromPEF.c 29 Written by: Jeffrey Robbin 30 Copyright: � 1994, 1996 by Apple Computer, Inc., all rights reserved. 31*/ 32 33#include <CoreFoundation/CoreFoundation.h> 34#include <IOKit/IOKitLib.h> 35#include <stdlib.h> 36#include <err.h> 37#include <sys/file.h> 38#include <nlist.h> 39#include <stdio.h> 40#include <unistd.h> 41#include <sys/param.h> 42#include <sys/stat.h> 43#include <sys/errno.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#include <IOKit/graphics/IOGraphicsLib.h> 51#include "IOGraphicsLibPrivate.h" 52#include "IOGraphicsLibInternal.h" 53 54enum 55{ 56 kIOPEFparamErr = 1001, 57 kIOPEFmemFullErr = 1002, 58 kIOPEFcfragFragmentFormatErr = 1003, 59 kIOPEFcfragNoSectionErr = 1004, 60 kIOPEFcfragNoSymbolErr = 1005, 61 kIOPEFcfragFragmentCorruptErr = 1006 62}; 63 64/******************************************************************************* 65* 66*******************************************************************************/ 67static unsigned char PEFGetNextByte( 68 unsigned char ** rawBuffer, 69 int * rawBufferRemaining) 70{ 71 *rawBufferRemaining = *rawBufferRemaining - 1; 72 return *(*rawBuffer)++; 73} 74 75 76/******************************************************************************* 77* 78*******************************************************************************/ 79static uint32_t PEFGetCount( 80 unsigned char ** rawBuffer, 81 int * rawBufferRemaining) 82{ 83 register unsigned char b; 84 register uint32_t value = 0UL; 85 86 /* Scan the count value. All required bytes MUST be present... */ 87 88 b = PEFGetNextByte(rawBuffer, rawBufferRemaining); 89 if (!IS_LAST_PICNT_BYTE(b)) { // if 1st byte is not that last... 90 value = CONCAT_PICNT(value, b); // ...init value using 1st byte 91 92 b = PEFGetNextByte(rawBuffer, rawBufferRemaining); 93 if (!IS_LAST_PICNT_BYTE(b)) { // if 2nd byte is not the last... 94 value = CONCAT_PICNT(value, b); // ...add in 2nd byte 95 96 b = PEFGetNextByte(rawBuffer, rawBufferRemaining); 97 if (!IS_LAST_PICNT_BYTE(b)) { // if 3rd byte is not the last... 98 value = CONCAT_PICNT(value, b); // ...add in 3rd byte 99 100 b = PEFGetNextByte(rawBuffer, rawBufferRemaining); 101 if (!IS_LAST_PICNT_BYTE(b)) { // if 4th is not the last... 102 value = CONCAT_PICNT(value, b); // ...add in 4th byte 103 104 // 5th byte is definitly last! 105 b = PEFGetNextByte(rawBuffer, rawBufferRemaining); 106 } 107 } 108 } 109 } 110 111 value = CONCAT_PICNT(value, b); /* add in "last" byte (whichever one) */ 112 113 return value; 114} 115 116 117 118/******************************************************************************* 119* UnpackPiData expands a compressed section into memory. 120*******************************************************************************/ 121static OSErr UnpackPiData( 122 LogicalAddress thePEFPtr, 123 SectionHeaderPtr sectionHeaderPtr, 124 LogicalAddress * theData) 125{ 126 int cntX, cnt, rpt, dcnt, delta; 127 unsigned char op, b; 128 unsigned char * unpackBuffer; 129 unsigned char * originalUnpackBuffer; 130 unsigned char * endUnpackBuffer; 131 unsigned char * oldRawBuffer; 132 int oldRawBufferRemaining; 133 unsigned char * rawBuffer; 134 int rawBufferRemaining; 135 136 // Verify incoming section is packed. 137 if (sectionHeaderPtr->regionKind != kPIDataSection) { 138 return kIOPEFparamErr; 139 } 140 141 // Allocate memory to unpack into 142 originalUnpackBuffer = (unsigned char*)NewPtrSys(sectionHeaderPtr->initSize); 143 if (originalUnpackBuffer == nil) { 144 return kIOPEFmemFullErr; 145 } 146 147 unpackBuffer = originalUnpackBuffer; 148 endUnpackBuffer = unpackBuffer + sectionHeaderPtr->initSize; 149 rawBuffer = (unsigned char*)((uintptr_t)thePEFPtr + 150 sectionHeaderPtr->containerOffset); 151 rawBufferRemaining = sectionHeaderPtr->rawSize; 152 153 154 /* Expand the pidata instructions. EOF will terminate processing 155 * through the setjmp on pidData_jmpbuf above... 156 */ 157 while (rawBufferRemaining > 0) { 158 159 /***** 160 * The first byte of each instruction contains the opcode and a count. 161 * If the countis 0, the count starts in the next byte... 162 */ 163 164 /* Pick up the opcode and first count operand... 165 */ 166 b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining); 167 168 op = PIOP(b); 169 cnt = PICNT(b); 170 171 if (cnt == 0) { 172 cnt = PEFGetCount(&rawBuffer, &rawBufferRemaining); 173 } 174 175 /* Unpack the data as a function of the opcode... 176 */ 177 switch (op) { 178 case kZero: // zero out cnt bytes... 179 if (unpackBuffer + cnt > endUnpackBuffer) { 180 goto Error; 181 } 182 memset(unpackBuffer, 0, cnt); 183 unpackBuffer += cnt; 184 break; 185 186 case kBlock: // copy cnt bytes... 187 if (unpackBuffer + cnt > endUnpackBuffer) { 188 goto Error; 189 } 190 while (--cnt >= 0) { 191 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining); 192 } 193 break; 194 195 case kRepeat: // copy cnt bytes rpt times... 196 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining) + 1; 197 198 if (cnt == 1) { 199 if (unpackBuffer + rpt > endUnpackBuffer) { 200 goto Error; 201 } 202 b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining); 203 memset(unpackBuffer, b, rpt); 204 unpackBuffer += rpt; 205 } else { 206 oldRawBufferRemaining = rawBufferRemaining; 207 oldRawBuffer = rawBuffer; 208 while (--rpt >= 0) { 209 if (unpackBuffer + cnt > endUnpackBuffer) { 210 goto Error; 211 } 212 rawBufferRemaining = oldRawBufferRemaining; 213 rawBuffer = oldRawBuffer; 214 cntX = cnt; 215 while (--cntX >= 0) { 216 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, 217 &rawBufferRemaining); 218 } 219 } 220 } 221 break; 222 223 case kRepeatZero: //copy cnt 0's and dcnt bytes rpt times 224 dcnt = PEFGetCount(&rawBuffer, &rawBufferRemaining); // ...then copy cnt more 0's 225 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining); 226 227 goto rptPart1; // jump into loop to copy 0's first... 228 229 while (--rpt >= 0) { 230 if (unpackBuffer + dcnt > endUnpackBuffer) { 231 goto Error; 232 } 233 cntX = dcnt; // cnt repeating parts follow each other 234 while (--cntX >= 0) { 235 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, 236 &rawBufferRemaining); 237 } 238 239rptPart1: // non-repeating part is always 0's... 240 if (unpackBuffer + cnt > endUnpackBuffer) { 241 goto Error; 242 } 243 memset(unpackBuffer, 0, cnt); 244 unpackBuffer += cnt; 245 } 246 break; 247 248 case kRepeatBlock: // copy cnt repeating bytes and dcnt 249 dcnt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* non-repating bytes rcnt times... */ 250 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* ...then copy cnt repeating bytes */ 251 252 oldRawBufferRemaining = rawBufferRemaining; 253 oldRawBuffer = rawBuffer; 254 delta = 0; /* the repeating part and each non-rep */ 255 256 goto rptPart2; /* jump into loop to copy rptng part 1st */ 257 258 while (--rpt >= 0) { 259 if (unpackBuffer + dcnt > endUnpackBuffer) { 260 goto Error; 261 } 262 263 rawBuffer = oldRawBuffer + cnt + delta; 264 rawBufferRemaining = oldRawBufferRemaining - (cnt + delta); 265 cntX = dcnt; 266 while (--cntX >= 0) { 267 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, 268 &rawBufferRemaining); 269 } 270 delta += dcnt; 271 272rptPart2: 273 if (unpackBuffer + cnt > endUnpackBuffer) { 274 goto Error; 275 } 276 rawBuffer = oldRawBuffer; 277 rawBufferRemaining = oldRawBufferRemaining; 278 cntX = cnt; 279 while (--cntX >= 0) { 280 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, 281 &rawBufferRemaining); 282 } 283 } 284 285 rawBuffer = oldRawBuffer + cnt + delta; 286 rawBufferRemaining = oldRawBufferRemaining - (cnt + delta); 287 break; 288 289 default: 290 goto Error; 291 break; 292 } /* switch */ 293 } /* for */ 294 295 *theData = originalUnpackBuffer; 296 297 return noErr; 298 299Error: 300 if (unpackBuffer) 301 DisposePtr((Ptr)originalUnpackBuffer); 302 303 *theData = nil; 304 305 return kIOPEFparamErr; 306} 307 308 309/******************************************************************************* 310* GetSymbolFromPEF will extract from a PEF container the data associated 311* with a given symbol name. It requires that the PEF file have been previously 312* loaded into memory. 313*******************************************************************************/ 314static OSStatus GetSymbolFromPEF( 315 char *inSymbolName, 316 const LogicalAddress thePEFPtr, 317 LogicalAddress theSymbolPtr, 318 ByteCount theSymbolSize) 319{ 320 StringPtr theSymbolName = (StringPtr) inSymbolName; 321 ContainerHeaderPtr containerHeaderPtr; // Pointer to the Container Header 322 SectionHeaderPtr loaderSectionPtr = 0; // Ptr to Loader Section Header 323 SectionHeaderPtr exportSectionPtr; // Ptr to Section Header with symbol 324 short currentSection; 325 Boolean foundSection; 326 Boolean foundSymbol; 327 int numExportSymbols; 328 LoaderHeaderPtr loaderHeaderPtr; 329 ExportSymbolEntryPtr exportSymbolEntryPtr; 330 LoaderExportChainEntryPtr exportChainEntryPtr; 331 StringPtr exportSymbolName; 332 LogicalAddress expandedDataPtr; 333 unsigned char * sourceDataPtr; 334 unsigned char * destDataPtr; 335 336 containerHeaderPtr = (ContainerHeaderPtr)thePEFPtr; 337 338 // Does the magic cookie match? 339 if (containerHeaderPtr->magicCookie != 'Joy!') { 340 return kIOPEFcfragFragmentFormatErr; 341 } 342 // Is this a known PEF container format? 343 if (containerHeaderPtr->containerID != 'peff') { 344 return kIOPEFcfragFragmentFormatErr; 345 } 346 347 // Validate parameters 348 if (theSymbolPtr == nil) { 349 return kIOPEFparamErr; 350 } 351 352 // Find the loader section. 353 foundSection = false; 354 for (currentSection = 0; 355 currentSection < containerHeaderPtr->nbrOfSections; 356 currentSection++) { 357 358 loaderSectionPtr = (SectionHeaderPtr)((uintptr_t)containerHeaderPtr + 359 sizeof(ContainerHeader) + 360 (sizeof(SectionHeader) * currentSection)); 361 362 if (loaderSectionPtr->regionKind == kLoaderSection) { 363 foundSection = true; 364 break; 365 } 366 } 367 368 if (foundSection == false) { 369 return kIOPEFcfragNoSectionErr; 370 } 371 372 // Get the number of export symbols. 373 loaderHeaderPtr = (LoaderHeaderPtr)((uintptr_t)thePEFPtr + 374 loaderSectionPtr->containerOffset); 375 numExportSymbols = loaderHeaderPtr->nbrExportSyms; 376 377 // Start at the first exported symbol. 378 exportSymbolEntryPtr = (ExportSymbolEntryPtr)((uintptr_t)loaderHeaderPtr + 379 loaderHeaderPtr->slotTblOffset + 380 (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz)) + 381 (sizeof(LoaderExportChainEntry) * numExportSymbols)); 382 383 exportChainEntryPtr = (LoaderExportChainEntryPtr) 384 ((uintptr_t)loaderHeaderPtr + 385 loaderHeaderPtr->slotTblOffset + 386 (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz))); 387 388 foundSymbol = false; 389 while (numExportSymbols-- > 0) { 390 exportSymbolName = (StringPtr)((uintptr_t)loaderHeaderPtr + 391 loaderHeaderPtr->strTblOffset + 392 (exportSymbolEntryPtr->class_and_name & 0x00FFFFFF)); 393 394 if (SymbolCompare(theSymbolName, exportSymbolName, 395 exportChainEntryPtr->_h._h_h._nameLength)) { 396 397 foundSymbol = true; 398 break; 399 } 400 exportSymbolEntryPtr = (ExportSymbolEntryPtr) 401 (((intptr_t) exportSymbolEntryPtr) + 10); 402 exportChainEntryPtr++; 403 } 404 405 if (foundSymbol == false) { 406 return kIOPEFcfragNoSymbolErr; 407 } 408 409 // Found the symbol, so... let's go get the data! 410 exportSectionPtr = (SectionHeaderPtr)((uintptr_t)containerHeaderPtr + 411 sizeof(ContainerHeader) + 412 (sizeof(SectionHeader) * exportSymbolEntryPtr->sectionNumber)); 413 414 expandedDataPtr = nil; 415 416 switch (exportSectionPtr -> regionKind) { 417 case kPIDataSection: 418 // Expand the data! (Not yet... :) 419 if (UnpackPiData(thePEFPtr, exportSectionPtr, &expandedDataPtr) != noErr) { 420 return kIOPEFcfragFragmentCorruptErr; 421 } 422 423 sourceDataPtr = (unsigned char*)((uintptr_t)expandedDataPtr + 424 exportSymbolEntryPtr->address); 425 break; 426 427 default: 428 sourceDataPtr = (unsigned char*)((uintptr_t)thePEFPtr + 429 exportSectionPtr->containerOffset + 430 exportSymbolEntryPtr->address); 431 break; 432 } 433 434 435 // Copy the data! 436 destDataPtr = (unsigned char*)theSymbolPtr; 437 438 while (theSymbolSize-- > 0) { 439 *destDataPtr++ = *sourceDataPtr++; 440 } 441 442 // Cleanup any expanded data 443 444 if (expandedDataPtr != nil) { 445 DisposePtr((Ptr)expandedDataPtr); 446 } 447 448 return noErr; 449} 450 451 452/******************************************************************************* 453* 454*******************************************************************************/ 455static IOByteCount GetPEFLen(LogicalAddress thePEFPtr) 456{ 457 ContainerHeaderPtr containerHeaderPtr; // Pointer to the Container Header 458 SectionHeaderPtr sections; 459 short currentSection; 460 int lastOffset = 0; 461 int len = 0; 462 463 containerHeaderPtr = (ContainerHeaderPtr)thePEFPtr; 464 465 // Does the magic cookie match? 466 if (containerHeaderPtr->magicCookie != 'Joy!') { 467 return 0; 468 } 469 470 // Is this a known PEF container format? 471 if (containerHeaderPtr->containerID != 'peff') { 472 return 0; 473 } 474 475 // Find the loader section. 476 sections = (SectionHeaderPtr) (containerHeaderPtr + 1); 477 for (currentSection = 0; 478 currentSection < containerHeaderPtr->nbrOfSections; 479 currentSection++) { 480 481 if (sections[currentSection].containerOffset > lastOffset) { 482 lastOffset = sections[currentSection].containerOffset; 483 len = sections[currentSection].rawSize; 484 } 485 } 486 487 return lastOffset + len; 488} 489 490/******************************************************************************* 491* theExportSymbol is NOT null-terminated, so use theExportSymbolLength. 492*******************************************************************************/ 493static Boolean SymbolCompare( 494 StringPtr theLookedForSymbol, 495 StringPtr theExportSymbol, 496 uint32_t theExportSymbolLength) 497{ 498 unsigned char * p1 = (unsigned char*)theLookedForSymbol; 499 unsigned char * p2 = (unsigned char*)theExportSymbol; 500 501 // Same length? 502 // (skip over p string len byte) 503 if (theExportSymbolLength != *p1++) { 504 return false; 505 } 506 507 while (theExportSymbolLength-- != 0) { 508 if (*p1++ != *p2++) { 509 return false; 510 } 511 } 512 513 return true; 514} 515 516 517/******************************************************************************* 518* 519*******************************************************************************/ 520// The Driver Description 521enum { 522 kInitialDriverDescriptor = 0, 523 kVersionOneDriverDescriptor = 1, 524 kTheDescriptionSignature = 'mtej', 525}; 526 527struct DriverType { 528 unsigned char nameInfoStr[32]; // Driver Name/Info String 529 uint32_t version; // Driver Version Number - really NumVersion 530}; 531typedef struct DriverType DriverType; 532 533struct DriverDescription { 534 uint32_t driverDescSignature; // Signature field of this structure 535 uint32_t driverDescVersion; // Version of this data structure 536 DriverType driverType; // Type of Driver 537 // other data follows... 538}; 539typedef struct DriverDescription DriverDescription; 540 541/******************************************************************************* 542* 543*******************************************************************************/ 544static void ExaminePEF( 545 mach_port_t masterPort, 546 char * pef, 547 IOByteCount pefLen, 548 CFDictionaryRef allMatching) 549{ 550 char descripName[] = "\pTheDriverDescription"; 551 int err; 552 DriverDescription descrip; 553 char matchName[40]; 554 uint32_t newVersion; 555 uint32_t curVersion; 556 IOReturn kr; 557 io_iterator_t iter; 558 io_service_t service; 559 io_string_t path; 560 CFStringRef ndrvPropName = CFSTR("driver,AAPL,MacOS,PowerPC"); 561 CFDataRef ndrv; 562 CFStringRef matchKey; 563 CFTypeRef value = 0; 564 CFDictionaryRef matching = 0; 565 CFMutableDictionaryRef dict; 566 567 err = GetSymbolFromPEF(descripName, pef, &descrip, sizeof(descrip)); 568 if (err != 0) { 569 printf("\nGetSymbolFromPEF returns %d\n",err); 570 return; 571 } 572 if ((descrip.driverDescSignature != kTheDescriptionSignature) || 573 (descrip.driverDescVersion != kInitialDriverDescriptor)) { 574 575 return; 576 } 577 578 strncpy(matchName, (char *) descrip.driverType.nameInfoStr + 1, 579 descrip.driverType.nameInfoStr[0]); 580 matchName[descrip.driverType.nameInfoStr[0]] = 0; 581 582 matchKey = CFStringCreateWithCString( kCFAllocatorDefault, matchName, 583 kCFStringEncodingMacRoman ); 584 if (!matchKey) 585 return; 586 587 if (allMatching) 588 { 589 value = CFDictionaryGetValue(allMatching, matchKey); 590 if (value) 591 { 592 if (value && (CFDictionaryGetTypeID() == CFGetTypeID(value))) 593 matching = CFRetain(value); 594 else if (value && (CFStringGetTypeID() == CFGetTypeID(value))) 595 { 596 CFRelease(matchKey); 597 matchKey = CFRetain(value); 598 } 599 } 600 } 601 602 if (!matching) 603 { 604 CFStringRef nameMatchKey = CFSTR(kIONameMatchKey); 605 matching = CFDictionaryCreate( kCFAllocatorDefault, 606 (const void **) &nameMatchKey, (const void **) &matchKey, 1, 607 &kCFTypeDictionaryKeyCallBacks, 608 &kCFTypeDictionaryValueCallBacks ); 609 } 610 CFRelease(matchKey); 611 if (!matching) 612 return; 613 614 kr = IOServiceGetMatchingServices(masterPort, matching, &iter); 615 if (kIOReturnSuccess != kr) 616 return; 617 618 newVersion = descrip.driverType.version; 619 if ((newVersion & 0xffff) == 0x8000) { 620 // final stage, release rev 621 newVersion |= 0xff; 622 } 623 624 for ( ; (service = IOIteratorNext(iter)); IOObjectRelease(service)) 625 { 626 kr = IORegistryEntryGetPath(service, kIOServicePlane, path); 627 if (kIOReturnSuccess == kr) 628 printf("Name %s matches %s, ", matchName, path); 629 630 ndrv = (CFDataRef) IORegistryEntryCreateCFProperty(service, ndrvPropName, 631 kCFAllocatorDefault, kNilOptions); 632 633 if (ndrv) 634 { 635 DriverDescription _curDesc; 636 DriverDescription * curDesc; 637 638 curDesc = (DriverDescription *) CFDataGetBytePtr(ndrv); 639 err = noErr; 640 641 if ((sizeof(DriverDescription) > (size_t) CFDataGetLength(ndrv)) 642 || (curDesc->driverDescSignature != kTheDescriptionSignature)) 643 { 644 curDesc = &_curDesc; 645 err = GetSymbolFromPEF(descripName, 646 (const LogicalAddress)CFDataGetBytePtr(ndrv), 647 curDesc, sizeof(DriverDescription)); 648 } 649 if (err != noErr) 650 printf("GetSymbolFromPEF returns %d\n",err); 651 else 652 { 653 if ((curDesc->driverDescSignature == kTheDescriptionSignature) && 654 (curDesc->driverDescVersion == kInitialDriverDescriptor)) 655 { 656 curVersion = curDesc->driverType.version; 657 printf("new version %08x, current version %08x\n", 658 newVersion, curVersion); 659 660 if ((curVersion & 0xffff) == 0x8000) { 661 // final stage, release rev 662 curVersion |= 0xff; 663 } 664 if (newVersion <= curVersion) { 665 pefLen = 0; 666 } 667 } 668 } 669 CFRelease(ndrv); 670 } 671 672 if (pefLen == 0) 673 continue; 674 675 ndrv = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, 676 (UInt8 *) pef, pefLen, kCFAllocatorNull); 677 if (ndrv == 0) 678 continue; 679 680 printf("Installing ndrv ("); 681 dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 682 &kCFTypeDictionaryKeyCallBacks, 683 &kCFTypeDictionaryValueCallBacks); 684 685 if (dict) 686 { 687 io_service_t child = MACH_PORT_NULL; 688 io_iterator_t iter; 689 690 CFDictionarySetValue(dict, ndrvPropName, ndrv); 691 692 kr = IORegistryEntryGetChildIterator(service, kIOServicePlane, &iter); 693 if (kr == kIOReturnSuccess) 694 { 695 kr = kIOReturnNotFound; 696 for( ; 697 (child = IOIteratorNext(iter)); 698 IOObjectRelease(child)) { 699 700 if (IOObjectConformsTo(child, "IOFramebuffer")) 701 break; 702 } 703 IOObjectRelease(iter); 704 } 705 if (child) 706 { 707 kr = IORegistryEntrySetCFProperties(child, dict); 708 IOObjectRelease(child); 709 } 710 CFRelease(dict); 711 } 712 else 713 kr = kIOReturnNoMemory; 714 715 CFRelease(ndrv); 716 printf("%08x)\n", kr); 717 } 718 IOObjectRelease(iter); 719 720 return; 721} 722 723/******************************************************************************* 724* 725*******************************************************************************/ 726 727static int PEFExamineFile(mach_port_t masterPort, CFURLRef file, CFDictionaryRef props) 728{ 729 vm_offset_t pefBytes; 730 vm_size_t pefFileLen; 731 char * pef; 732 IOByteCount pefLen, pos = 0; 733 int err; 734 CFDictionaryRef fileMatch; 735 CFDictionaryRef matching = 0; 736 Boolean matches = true; 737 char cFile[MAXPATHLEN]; 738 739 do 740 { 741 if (!props) 742 continue; 743 744 fileMatch = CFDictionaryGetValue(props, CFSTR("IONDRVFileMatching")); 745 if (fileMatch && (CFDictionaryGetTypeID() != CFGetTypeID(fileMatch))) 746 fileMatch = 0; 747 748 if (fileMatch) 749 { 750 io_service_t service; 751 752 CFRetain(fileMatch); 753 service = IOServiceGetMatchingService(masterPort, fileMatch); 754 matches = (MACH_PORT_NULL != service); 755 if (matches) 756 IOObjectRelease(service); 757 continue; 758 } 759 760 matching = CFDictionaryGetValue(props, CFSTR("IONDRVMatching")); 761 if (matching && (CFDictionaryGetTypeID() != CFGetTypeID(matching))) 762 matching = 0; 763 764 } 765 while (false); 766 767 if (!matches) 768 return (kIOReturnSuccess); 769 770 if (CFURLGetFileSystemRepresentation(file, TRUE, (UInt8 *) cFile, MAXPATHLEN)) 771 err = readFile(cFile, &pefBytes, &pefFileLen); 772 else 773 err = kIOReturnIOError; 774 775 if (kIOReturnSuccess != err) 776 return (err); 777 778 pef = (char *) pefBytes; 779 while ((pos < pefFileLen) && (pefLen = GetPEFLen(pef))) 780 { 781 ExaminePEF(masterPort, pef, pefLen, matching); 782 pefLen = (pefLen + 15) & ~15; 783 pef += pefLen; 784 pos += pefLen; 785 } 786 787 if (pefBytes) 788 vm_deallocate(mach_task_self(), pefBytes, pefFileLen); 789 790 return (0); 791} 792 793static void _PEFExamineFile(mach_port_t masterPort, CFURLRef ndrvURL, CFDictionaryRef plist) 794{ 795 if (PEFExamineFile(masterPort, ndrvURL, plist)) 796 { 797 char buf[PATH_MAX]; 798 char * ndrv_path; 799 if(CFURLGetFileSystemRepresentation(ndrvURL, true /*resolve*/, 800 (UInt8*)buf, PATH_MAX)) { 801 ndrv_path = buf; 802 } else { 803 ndrv_path = "(unknown)"; 804 } 805 806 printf("error processing NDRV \"%s\"", ndrv_path); 807 } 808} 809 810static void PEFExamineBundle( mach_port_t masterPort __unused, CFBundleRef bdl ) 811{ 812 CFURLRef ndrvURL; 813 CFDictionaryRef plist; 814 815 plist = CFBundleGetInfoDictionary(bdl); 816 if (!plist) 817 return; 818 ndrvURL = CFBundleCopyExecutableURL(bdl); 819 if (!ndrvURL) 820 return; 821 822 _PEFExamineFile(kIOMasterPortDefault, ndrvURL, plist); 823 824 CFRelease(ndrvURL); 825} 826 827void IOLoadPEFsFromURL( CFURLRef ndrvDirURL, io_service_t service __unused ) 828{ 829 CFIndex ndrvCount, n; 830 CFArrayRef ndrvDirContents = NULL; // must release 831 SInt32 error; 832 833 ndrvDirContents = (CFArrayRef) CFURLCreatePropertyFromResource( 834 kCFAllocatorDefault, ndrvDirURL, kCFURLFileDirectoryContents, 835 &error); 836 837 ndrvCount = ndrvDirContents ? CFArrayGetCount(ndrvDirContents) : 0; 838 839 for (n = 0; n < ndrvCount; n++) 840 { 841 CFURLRef ndrvURL = NULL; // don't release 842 CFNumberRef num; 843 CFBundleRef bdl; 844 CFStringRef ext; 845 SInt32 mode; 846 Boolean skip; 847 848 ndrvURL = (CFURLRef)CFArrayGetValueAtIndex(ndrvDirContents, n); 849 850 bdl = CFBundleCreate(kCFAllocatorDefault, ndrvURL); 851 if (bdl) 852 { 853 PEFExamineBundle(kIOMasterPortDefault, bdl); 854 CFRelease(bdl); 855 continue; 856 } 857 858 ext = CFURLCopyPathExtension(ndrvURL); 859 if (ext) 860 { 861 skip = CFEqual(ext, CFSTR(".plist")); 862 CFRelease(ext); 863 if (skip) 864 continue; 865 } 866 867 num = (CFNumberRef) CFURLCreatePropertyFromResource( 868 kCFAllocatorDefault, ndrvURL, kCFURLFilePOSIXMode, &error); 869 if (!num) 870 continue; 871 CFNumberGetValue(num, kCFNumberSInt32Type, (SInt32 *) &mode); 872 CFRelease(num); 873 if ((mode & S_IFMT) == S_IFREG) 874 _PEFExamineFile(kIOMasterPortDefault, ndrvURL, NULL); 875 } 876 877 if (ndrvDirContents) 878 CFRelease(ndrvDirContents); 879} 880 881