2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 #include <IOKit/IOLib.h> 
  30 #include <IOKit/IONVRAM.h> 
  31 #include <IOKit/IOPlatformExpert.h> 
  32 #include <IOKit/IOUserClient.h> 
  33 #include <IOKit/IOKitKeys.h> 
  35 #define super IOService 
  37 #define kIONVRAMPrivilege       kIOClientPrivilegeAdministrator 
  38 //#define kIONVRAMPrivilege     kIOClientPrivilegeLocalUser 
  41 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
); 
  43 bool IODTNVRAM::init(IORegistryEntry 
*old
, const IORegistryPlane 
*plane
) 
  47   if (!super::init(old
, plane
)) return false; 
  49   dict 
=  OSDictionary::withCapacity(1); 
  50   if (dict 
== 0) return false; 
  51   setPropertyTable(dict
); 
  53   _nvramImage 
= IONew(UInt8
, kIODTNVRAMImageSize
); 
  54   if (_nvramImage 
== 0) return false; 
  56   _nvramPartitionOffsets 
= OSDictionary::withCapacity(1); 
  57   if (_nvramPartitionOffsets 
== 0) return false; 
  59   _nvramPartitionLengths 
= OSDictionary::withCapacity(1); 
  60   if (_nvramPartitionLengths 
== 0) return false; 
  62   _registryPropertiesKey 
= OSSymbol::withCStringNoCopy("aapl,pci"); 
  63   if (_registryPropertiesKey 
== 0) return false; 
  68 void IODTNVRAM::registerNVRAMController(IONVRAMController 
*nvram
) 
  71   UInt32 partitionOffset
, partitionLength
; 
  72   UInt32 freePartitionOffset
, freePartitionSize
; 
  73   UInt32 currentLength
, currentOffset 
= 0; 
  74   OSNumber 
*partitionOffsetNumber
, *partitionLengthNumber
; 
  76   if (_nvramController 
!= 0) return; 
  78   _nvramController 
= nvram
; 
  80   _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
); 
  82   // Find the offsets for the OF, XPRAM, NameRegistry and PanicInfo partitions. 
  83   _ofPartitionOffset 
= 0xFFFFFFFF; 
  84   _xpramPartitionOffset 
= 0xFFFFFFFF; 
  85   _nrPartitionOffset 
= 0xFFFFFFFF; 
  86   _piPartitionOffset 
= 0xFFFFFFFF; 
  87   freePartitionOffset 
= 0xFFFFFFFF; 
  88   freePartitionSize 
= 0; 
  89   if (getPlatform()->getBootROMType()) { 
  90     // Look through the partitions to find the OF, MacOS partitions. 
  91     while (currentOffset 
< kIODTNVRAMImageSize
) { 
  92       currentLength 
= ((UInt16 
*)(_nvramImage 
+ currentOffset
))[1] * 16; 
  94       partitionOffset 
= currentOffset 
+ 16; 
  95       partitionLength 
= currentLength 
- 16; 
  97       if (strncmp((const char *)_nvramImage 
+ currentOffset 
+ 4, 
  98                   kIODTNVRAMOFPartitionName
, 12) == 0) { 
  99         _ofPartitionOffset 
= partitionOffset
; 
 100         _ofPartitionSize 
= partitionLength
; 
 101       } else if (strncmp((const char *)_nvramImage 
+ currentOffset 
+ 4, 
 102                          kIODTNVRAMXPRAMPartitionName
, 12) == 0) { 
 103         _xpramPartitionOffset 
= partitionOffset
; 
 104         _xpramPartitionSize 
= kIODTNVRAMXPRAMSize
; 
 105         _nrPartitionOffset 
= _xpramPartitionOffset 
+ _xpramPartitionSize
; 
 106         _nrPartitionSize 
= partitionLength 
- _xpramPartitionSize
; 
 107       } else if (strncmp((const char *)_nvramImage 
+ currentOffset 
+ 4, 
 108                          kIODTNVRAMPanicInfoPartitonName
, 12) == 0) { 
 109         _piPartitionOffset 
= partitionOffset
; 
 110         _piPartitionSize 
= partitionLength
; 
 111       } else if (strncmp((const char *)_nvramImage 
+ currentOffset 
+ 4, 
 112                          kIODTNVRAMFreePartitionName
, 12) == 0) { 
 113         freePartitionOffset 
= currentOffset
; 
 114         freePartitionSize 
= currentLength
; 
 116         // Construct the partition ID from the signature and name. 
 117         sprintf(partitionID
, "0x%02x,", 
 118                 *(UInt8 
*)(_nvramImage 
+ currentOffset
)); 
 119         strncpy(partitionID 
+ 5, 
 120                 (const char *)(_nvramImage 
+ currentOffset 
+ 4), 12); 
 121         partitionID
[17] = '\0'; 
 123         partitionOffsetNumber 
= OSNumber::withNumber(partitionOffset
, 32); 
 124         partitionLengthNumber 
= OSNumber::withNumber(partitionLength
, 32); 
 126         // Save the partition offset and length 
 127         _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
); 
 128         _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
); 
 130         partitionOffsetNumber
->release(); 
 131         partitionLengthNumber
->release(); 
 133       currentOffset 
+= currentLength
; 
 136     // Use the fixed address for old world machines. 
 137     _ofPartitionOffset    
= 0x1800; 
 138     _ofPartitionSize      
= 0x0800; 
 139     _xpramPartitionOffset 
= 0x1300; 
 140     _xpramPartitionSize   
= 0x0100; 
 141     _nrPartitionOffset    
= 0x1400; 
 142     _nrPartitionSize      
= 0x0400; 
 145   if (_ofPartitionOffset 
!= 0xFFFFFFFF) 
 146     _ofImage    
= _nvramImage 
+ _ofPartitionOffset
; 
 147   if (_xpramPartitionOffset 
!= 0xFFFFFFFF) 
 148     _xpramImage 
= _nvramImage 
+ _xpramPartitionOffset
; 
 149   if (_nrPartitionOffset 
!= 0xFFFFFFFF) 
 150     _nrImage    
= _nvramImage 
+ _nrPartitionOffset
; 
 152   if (_piPartitionOffset 
== 0xFFFFFFFF) { 
 153     if (freePartitionSize 
> 0x20) { 
 154       // Set the signature to 0xa1. 
 155       _nvramImage
[freePartitionOffset
] = 0xa1; 
 156       // Set the checksum to 0. 
 157       _nvramImage
[freePartitionOffset 
+ 1] = 0; 
 158       // Set the name for the Panic Info partition. 
 159       strncpy((char *)(_nvramImage 
+ freePartitionOffset 
+ 4), 
 160               kIODTNVRAMPanicInfoPartitonName
, 12); 
 162       // Calculate the partition offset and size. 
 163       _piPartitionOffset 
= freePartitionOffset 
+ 0x10; 
 164       _piPartitionSize 
= 0x800; 
 165       if (_piPartitionSize 
+ 0x20 > freePartitionSize
) 
 166         _piPartitionSize 
= freePartitionSize 
- 0x20; 
 168       _piImage 
= _nvramImage 
+ _piPartitionOffset
; 
 170       // Zero the new partition. 
 171       bzero(_piImage
, _piPartitionSize
); 
 173       // Set the partition size. 
 174       *(UInt16 
*)(_nvramImage 
+ freePartitionOffset 
+ 2) = 
 175         (_piPartitionSize 
/ 0x10) + 1; 
 177       // Set the partition checksum. 
 178       _nvramImage
[freePartitionOffset 
+ 1] = 
 179         calculatePartitionChecksum(_nvramImage 
+ freePartitionOffset
); 
 181       // Calculate the free partition offset and size. 
 182       freePartitionOffset 
+= _piPartitionSize 
+ 0x10; 
 183       freePartitionSize 
-= _piPartitionSize 
+ 0x10; 
 185       // Set the signature to 0x7f. 
 186       _nvramImage
[freePartitionOffset
] = 0x7f; 
 187       // Set the checksum to 0. 
 188       _nvramImage
[freePartitionOffset 
+ 1] = 0; 
 189       // Set the name for the free partition. 
 190       strncpy((char *)(_nvramImage 
+ freePartitionOffset 
+ 4), 
 191               kIODTNVRAMFreePartitionName
, 12); 
 192       // Set the partition size. 
 193       *(UInt16 
*)(_nvramImage 
+ freePartitionOffset 
+ 2) = 
 194         freePartitionSize 
/ 0x10; 
 195       // Set the partition checksum. 
 196       _nvramImage
[freePartitionOffset 
+ 1] = 
 197         calculatePartitionChecksum(_nvramImage 
+ freePartitionOffset
); 
 199       // Set the nvram image as dirty. 
 200       _nvramImageDirty 
= true; 
 203     _piImage 
= _nvramImage 
+ _piPartitionOffset
; 
 209 void IODTNVRAM::sync(void) 
 211   if (!_nvramImageDirty 
&& !_ofImageDirty
) return; 
 213   // Don't try to sync OF Variables if the system has already paniced. 
 214   if (!_systemPaniced
) syncOFVariables(); 
 216   _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
); 
 217   _nvramController
->sync(); 
 219   _nvramImageDirty 
= false; 
 222 bool IODTNVRAM::serializeProperties(OSSerialize 
*s
) const 
 227   OSDictionary         
*dict
, *tmpDict 
= 0; 
 228   OSCollectionIterator 
*iter 
= 0; 
 230   if (_ofDict 
== 0) return false; 
 232   // Verify permissions. 
 233   result 
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
); 
 234   if (result 
!= kIOReturnSuccess
) { 
 235     tmpDict 
= OSDictionary::withCapacity(1); 
 236     if (tmpDict 
== 0) return false; 
 238     iter 
= OSCollectionIterator::withCollection(_ofDict
); 
 239     if (iter 
== 0) return false; 
 242       key 
= OSDynamicCast(OSSymbol
, iter
->getNextObject()); 
 245       variablePerm 
= getOFVariablePerm(key
); 
 246       if (variablePerm 
!= kOFVariablePermRootOnly
) { 
 247         tmpDict
->setObject(key
, _ofDict
->getObject(key
)); 
 255   result 
= dict
->serialize(s
); 
 257   if (tmpDict 
!= 0) tmpDict
->release(); 
 258   if (iter 
!= 0) iter
->release(); 
 263 OSObject 
*IODTNVRAM::getProperty(const OSSymbol 
*aKey
) const 
 268   if (_ofDict 
== 0) return 0; 
 270   // Verify permissions. 
 271   result 
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
); 
 272   if (result 
!= kIOReturnSuccess
) { 
 273     variablePerm 
= getOFVariablePerm(aKey
); 
 274     if (variablePerm 
== kOFVariablePermRootOnly
) return 0; 
 277   return _ofDict
->getObject(aKey
); 
 280 OSObject 
*IODTNVRAM::getProperty(const char *aKey
) const 
 282   const OSSymbol 
*keySymbol
; 
 283   OSObject 
*theObject 
= 0; 
 285   keySymbol 
= OSSymbol::withCStringNoCopy(aKey
); 
 286   if (keySymbol 
!= 0) { 
 287     theObject 
= getProperty(keySymbol
); 
 288     keySymbol
->release(); 
 294 bool IODTNVRAM::setProperty(const OSSymbol 
*aKey
, OSObject 
*anObject
) 
 297   UInt32   propType
, propPerm
; 
 299   OSObject 
*propObject 
= 0; 
 301   if (_ofDict 
== 0) return false; 
 303   // Verify permissions. 
 304   result 
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
); 
 305   if (result 
!= kIOReturnSuccess
) { 
 306     propPerm 
= getOFVariablePerm(aKey
); 
 307     if (propPerm 
!= kOFVariablePermUserWrite
) return false; 
 310   // Don't allow creation of new properties on old world machines. 
 311   if (getPlatform()->getBootROMType() == 0) { 
 312     if (_ofDict
->getObject(aKey
) == 0) return false; 
 315   // Don't allow change of 'aapl,panic-info'. 
 316   if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return false; 
 318   // Make sure the object is of the correct type. 
 319   propType 
= getOFVariableType(aKey
); 
 321   case kOFVariableTypeBoolean 
: 
 322     propObject 
= OSDynamicCast(OSBoolean
, anObject
); 
 325   case kOFVariableTypeNumber 
: 
 326     propObject 
= OSDynamicCast(OSNumber
, anObject
); 
 329   case kOFVariableTypeString 
: 
 330     propObject 
= OSDynamicCast(OSString
, anObject
); 
 333   case kOFVariableTypeData 
: 
 334     propObject 
= OSDynamicCast(OSData
, anObject
); 
 335     if (propObject 
== 0) { 
 336       tmpString 
= OSDynamicCast(OSString
, anObject
); 
 337       if (tmpString 
!= 0) { 
 338         propObject 
= OSData::withBytes(tmpString
->getCStringNoCopy(), 
 339                                        tmpString
->getLength()); 
 345   if (propObject 
== 0) return false; 
 347   result 
= _ofDict
->setObject(aKey
, propObject
); 
 350     if (getPlatform()->getBootROMType() == 0) { 
 351       updateOWBootArgs(aKey
, propObject
); 
 354     _ofImageDirty 
= true; 
 360 void IODTNVRAM::removeProperty(const OSSymbol 
*aKey
) 
 365   if (_ofDict 
== 0) return; 
 367   // Verify permissions. 
 368   result 
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
); 
 369   if (result 
!= kIOReturnSuccess
) { 
 370     propPerm 
= getOFVariablePerm(aKey
); 
 371     if (propPerm 
!= kOFVariablePermUserWrite
) return; 
 374   // Don't allow removal of properties on old world machines. 
 375   if (getPlatform()->getBootROMType() == 0) return; 
 377   // Don't allow change of 'aapl,panic-info'. 
 378   if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return; 
 380   // If the object exists, remove it from the dictionary. 
 381   result 
= _ofDict
->getObject(aKey
) != 0; 
 383     _ofDict
->removeObject(aKey
); 
 385     _ofImageDirty 
= true; 
 389 IOReturn 
IODTNVRAM::setProperties(OSObject 
*properties
) 
 394   const OSString       
*tmpStr
; 
 396   OSCollectionIterator 
*iter
; 
 398   dict 
= OSDynamicCast(OSDictionary
, properties
); 
 399   if (dict 
== 0) return kIOReturnBadArgument
; 
 401   iter 
= OSCollectionIterator::withCollection(dict
); 
 402   if (iter 
== 0) return kIOReturnBadArgument
; 
 405     key 
= OSDynamicCast(OSSymbol
, iter
->getNextObject()); 
 408     object 
= dict
->getObject(key
); 
 409     if (object 
== 0) continue; 
 411     if (key
->isEqualTo(kIONVRAMDeletePropertyKey
)) { 
 412       tmpStr 
= OSDynamicCast(OSString
, object
); 
 414         key 
= OSSymbol::withString(tmpStr
); 
 422       result 
= setProperty(key
, object
); 
 428   if (result
) return kIOReturnSuccess
; 
 429   else return kIOReturnError
; 
 432 IOReturn 
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8 
*buffer
, 
 435   if (_xpramImage 
== 0) return kIOReturnUnsupported
; 
 437   if ((buffer 
== 0) || (length 
== 0) || 
 438       (offset 
+ length 
> kIODTNVRAMXPRAMSize
)) 
 439     return kIOReturnBadArgument
; 
 441   bcopy(_nvramImage 
+ _xpramPartitionOffset 
+ offset
, buffer
, length
); 
 443   return kIOReturnSuccess
; 
 446 IOReturn 
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8 
*buffer
, 
 449   if (_xpramImage 
== 0) return kIOReturnUnsupported
; 
 451   if ((buffer 
== 0) || (length 
== 0) || 
 452       (offset 
+ length 
> kIODTNVRAMXPRAMSize
)) 
 453     return kIOReturnBadArgument
; 
 455   bcopy(buffer
, _nvramImage 
+ _xpramPartitionOffset 
+ offset
, length
); 
 457   _nvramImageDirty 
= true; 
 459   return kIOReturnSuccess
; 
 462 IOReturn 
IODTNVRAM::readNVRAMProperty(IORegistryEntry 
*entry
, 
 463                                       const OSSymbol 
**name
, 
 468   if (getPlatform()->getBootROMType()) 
 469     err 
= readNVRAMPropertyType1(entry
, name
, value
); 
 471     err 
= readNVRAMPropertyType0(entry
, name
, value
); 
 476 IOReturn 
IODTNVRAM::writeNVRAMProperty(IORegistryEntry 
*entry
, 
 477                                        const OSSymbol 
*name
, 
 482   if (getPlatform()->getBootROMType()) 
 483     err 
= writeNVRAMPropertyType1(entry
, name
, value
); 
 485     err 
= writeNVRAMPropertyType0(entry
, name
, value
); 
 490 OSDictionary 
*IODTNVRAM::getNVRAMPartitions(void) 
 492   return _nvramPartitionLengths
; 
 495 IOReturn 
IODTNVRAM::readNVRAMPartition(const OSSymbol 
*partitionID
, 
 496                                        IOByteCount offset
, UInt8 
*buffer
, 
 499   OSNumber 
*partitionOffsetNumber
, *partitionLengthNumber
; 
 500   UInt32   partitionOffset
, partitionLength
; 
 502   partitionOffsetNumber 
= 
 503     (OSNumber 
*)_nvramPartitionOffsets
->getObject(partitionID
); 
 504   partitionLengthNumber 
= 
 505     (OSNumber 
*)_nvramPartitionLengths
->getObject(partitionID
); 
 507   if ((partitionOffsetNumber 
== 0) || (partitionLengthNumber 
== 0)) 
 508     return kIOReturnNotFound
; 
 510   partitionOffset 
= partitionOffsetNumber
->unsigned32BitValue(); 
 511   partitionLength 
= partitionLengthNumber
->unsigned32BitValue(); 
 513   if ((buffer 
== 0) || (length 
== 0) || 
 514       (offset 
+ length 
> partitionLength
)) 
 515     return kIOReturnBadArgument
; 
 517   bcopy(_nvramImage 
+ partitionOffset 
+ offset
, buffer
, length
); 
 519   return kIOReturnSuccess
; 
 522 IOReturn 
IODTNVRAM::writeNVRAMPartition(const OSSymbol 
*partitionID
, 
 523                                         IOByteCount offset
, UInt8 
*buffer
, 
 526   OSNumber 
*partitionOffsetNumber
, *partitionLengthNumber
; 
 527   UInt32   partitionOffset
, partitionLength
; 
 529   partitionOffsetNumber 
= 
 530     (OSNumber 
*)_nvramPartitionOffsets
->getObject(partitionID
); 
 531   partitionLengthNumber 
= 
 532     (OSNumber 
*)_nvramPartitionLengths
->getObject(partitionID
); 
 534   if ((partitionOffsetNumber 
== 0) || (partitionLengthNumber 
== 0)) 
 535     return kIOReturnNotFound
; 
 537   partitionOffset 
= partitionOffsetNumber
->unsigned32BitValue(); 
 538   partitionLength 
= partitionLengthNumber
->unsigned32BitValue(); 
 540   if ((buffer 
== 0) || (length 
== 0) || 
 541       (offset 
+ length 
> partitionLength
)) 
 542     return kIOReturnBadArgument
; 
 544   bcopy(buffer
, _nvramImage 
+ partitionOffset 
+ offset
, length
); 
 546   _nvramImageDirty 
= true; 
 548   return kIOReturnSuccess
; 
 551 UInt32 
IODTNVRAM::savePanicInfo(UInt8 
*buffer
, IOByteCount length
) 
 553   if ((_piImage 
== 0) || (length 
<= 0)) return 0; 
 555   if (length 
> (_piPartitionSize 
- 4)) 
 556     length 
= _piPartitionSize 
- 4; 
 558   // Save the Panic Info. 
 559   bcopy(buffer
, _piImage 
+ 4, length
); 
 561   // Save the Panic Info length. 
 562   *(UInt32 
*)_piImage 
= length
; 
 564   _nvramImageDirty 
= true; 
 566   _systemPaniced 
= true; 
 573 UInt8 
IODTNVRAM::calculatePartitionChecksum(UInt8 
*partitionHeader
) 
 575   UInt8 cnt
, isum
, csum 
= 0; 
 577   for (cnt 
= 0; cnt 
< 0x10; cnt
++) { 
 578     isum 
= csum 
+ partitionHeader
[cnt
]; 
 579     if (isum 
< csum
) isum
++; 
 586 struct OWVariablesHeader 
{ 
 601 typedef struct OWVariablesHeader OWVariablesHeader
; 
 603 IOReturn 
IODTNVRAM::initOFVariables(void) 
 605   UInt32            cnt
, propOffset
, propType
; 
 606   UInt8             
*propName
, *propData
; 
 607   UInt32            propNameLength
, propDataLength
; 
 608   const OSSymbol    
*propSymbol
; 
 609   OSObject          
*propObject
; 
 610   OWVariablesHeader 
*owHeader
; 
 612   if (_ofImage 
== 0) return kIOReturnNotReady
; 
 614   _ofDict 
=  OSDictionary::withCapacity(1); 
 615   if (_ofDict 
== 0) return kIOReturnNoMemory
; 
 617   if (getPlatform()->getBootROMType()) { 
 619     while (cnt 
< _ofPartitionSize
) { 
 620       // Break if there is no name. 
 621       if (_ofImage
[cnt
] == '\0') break; 
 623       // Find the length of the name. 
 624       propName 
= _ofImage 
+ cnt
; 
 625       for (propNameLength 
= 0; (cnt 
+ propNameLength
) < _ofPartitionSize
; 
 627         if (_ofImage
[cnt 
+ propNameLength
] == '=') break; 
 630       // Break if the name goes past the end of the partition. 
 631       if ((cnt 
+ propNameLength
) >= _ofPartitionSize
) break; 
 632       cnt 
+= propNameLength 
+ 1; 
 634       propData 
= _ofImage 
+ cnt
; 
 635       for (propDataLength 
= 0; (cnt 
+ propDataLength
) < _ofPartitionSize
; 
 637         if (_ofImage
[cnt 
+ propDataLength
] == '\0') break; 
 640       // Break if the data goes past the end of the partition. 
 641       if ((cnt 
+ propDataLength
) >= _ofPartitionSize
) break; 
 642       cnt 
+= propDataLength 
+ 1; 
 644       if (convertPropToObject(propName
, propNameLength
, 
 645                               propData
, propDataLength
, 
 646                               &propSymbol
, &propObject
)) { 
 647         _ofDict
->setObject(propSymbol
, propObject
); 
 648         propSymbol
->release(); 
 649         propObject
->release(); 
 653     // Create the boot-args property if it is not in the dictionary. 
 654     if (_ofDict
->getObject("boot-args") == 0) { 
 655       propObject 
= OSString::withCStringNoCopy(""); 
 656       if (propObject 
!= 0) { 
 657         _ofDict
->setObject("boot-args", propObject
); 
 658         propObject
->release(); 
 662     // Create the 'aapl,panic-info' property if needed. 
 664       propDataLength 
= *(UInt32 
*)_piImage
; 
 665       if ((propDataLength 
!= 0) && (propDataLength 
< (_piPartitionSize 
- 4))) { 
 666         propObject 
= OSData::withBytes(_piImage 
+ 4, propDataLength
); 
 667         _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
); 
 668         propObject
->release(); 
 670         // Clear the length from _piImage and mark dirty. 
 671         *(UInt32 
*)_piImage 
= 0; 
 672         _nvramImageDirty 
= true; 
 676     owHeader 
= (OWVariablesHeader 
*)_ofImage
; 
 677     if (!validateOWChecksum(_ofImage
)) { 
 680       return kIOReturnBadMedia
; 
 685       if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
)) 
 689       case kOFVariableTypeBoolean 
: 
 690         propObject 
= OSBoolean::withBoolean(owHeader
->owFlags 
& propOffset
); 
 693       case kOFVariableTypeNumber 
: 
 694         propObject 
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32); 
 697       case kOFVariableTypeString 
: 
 698         propData 
= _ofImage 
+ owHeader
->owStrings
[propOffset
].offset 
- 
 700         propDataLength 
= owHeader
->owStrings
[propOffset
].length
; 
 701         propName 
= IONew(UInt8
, propDataLength 
+ 1); 
 703           strncpy((char *)propName
, (const char *)propData
, propDataLength
); 
 704           propName
[propDataLength
] = '\0'; 
 705           propObject 
= OSString::withCString((const char *)propName
); 
 706           IODelete(propName
, UInt8
, propDataLength 
+ 1); 
 711       if (propObject 
== 0) break; 
 713       _ofDict
->setObject(propSymbol
, propObject
); 
 714       propSymbol
->release(); 
 715       propObject
->release(); 
 718     // Create the boot-args property. 
 719     propSymbol 
= OSSymbol::withCString("boot-command"); 
 720     if (propSymbol 
!= 0) { 
 721       propObject 
= _ofDict
->getObject(propSymbol
); 
 722       if (propObject 
!= 0) { 
 723         updateOWBootArgs(propSymbol
, propObject
); 
 725       propSymbol
->release(); 
 729   return kIOReturnSuccess
; 
 732 IOReturn 
IODTNVRAM::syncOFVariables(void) 
 735   UInt32               cnt
, length
, maxLength
; 
 736   UInt32               curOffset
, tmpOffset
, tmpType
, tmpDataLength
; 
 737   UInt8                
*buffer
, *tmpBuffer
; 
 738   const UInt8          
*tmpData
; 
 739   const OSSymbol       
*tmpSymbol
; 
 741   OSBoolean            
*tmpBoolean
; 
 744   OSCollectionIterator 
*iter
; 
 745   OWVariablesHeader    
*owHeader
, *owHeaderOld
; 
 747   if ((_ofImage 
== 0) || (_ofDict 
== 0)) return kIOReturnNotReady
; 
 749   if (!_ofImageDirty
) return kIOReturnSuccess
; 
 751   if (getPlatform()->getBootROMType()) { 
 752     buffer 
= tmpBuffer 
= IONew(UInt8
, _ofPartitionSize
); 
 753     if (buffer 
== 0) return kIOReturnNoMemory
; 
 754     bzero(buffer
, _ofPartitionSize
); 
 757     maxLength 
= _ofPartitionSize
; 
 759     iter 
= OSCollectionIterator::withCollection(_ofDict
); 
 760     if (iter 
== 0) ok 
= false; 
 763       tmpSymbol 
= OSDynamicCast(OSSymbol
, iter
->getNextObject()); 
 764       if (tmpSymbol 
== 0) break; 
 766       // Don't save 'aapl,panic-info'. 
 767       if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue; 
 769       tmpObject 
= _ofDict
->getObject(tmpSymbol
); 
 772       ok 
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
); 
 781       bcopy(buffer
, _ofImage
, _ofPartitionSize
); 
 784     IODelete(buffer
, UInt8
, _ofPartitionSize
); 
 786     if (!ok
) return kIOReturnBadArgument
; 
 788     buffer 
= IONew(UInt8
, _ofPartitionSize
); 
 789     if (buffer 
== 0) return kIOReturnNoMemory
; 
 790     bzero(buffer
, _ofPartitionSize
); 
 792     owHeader    
= (OWVariablesHeader 
*)buffer
; 
 793     owHeaderOld 
= (OWVariablesHeader 
*)_ofImage
; 
 795     owHeader
->owMagic 
= owHeaderOld
->owMagic
; 
 796     owHeader
->owVersion 
= owHeaderOld
->owVersion
; 
 797     owHeader
->owPages 
= owHeaderOld
->owPages
; 
 799     curOffset 
= _ofPartitionSize
; 
 804       if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
)) 
 807       tmpObject 
= _ofDict
->getObject(tmpSymbol
); 
 810       case kOFVariableTypeBoolean 
: 
 811         tmpBoolean 
= OSDynamicCast(OSBoolean
, tmpObject
); 
 812         if (tmpBoolean
->getValue()) owHeader
->owFlags 
|= tmpOffset
; 
 815       case kOFVariableTypeNumber 
: 
 816         tmpNumber 
= OSDynamicCast(OSNumber
, tmpObject
); 
 817         owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue(); 
 820       case kOFVariableTypeString 
: 
 821         tmpString 
= OSDynamicCast(OSString
, tmpObject
); 
 822         tmpData 
= (const UInt8 
*)tmpString
->getCStringNoCopy(); 
 823         tmpDataLength 
= tmpString
->getLength(); 
 825         if ((curOffset 
- tmpDataLength
) < sizeof(OWVariablesHeader
)) { 
 830         owHeader
->owStrings
[tmpOffset
].length 
= tmpDataLength
; 
 831         curOffset 
-= tmpDataLength
; 
 832         owHeader
->owStrings
[tmpOffset
].offset 
= curOffset 
+ _ofPartitionOffset
; 
 833         if (tmpDataLength 
!= 0) 
 834           bcopy(tmpData
, buffer 
+ curOffset
, tmpDataLength
); 
 840       owHeader
->owHere 
= _ofPartitionOffset 
+ sizeof(OWVariablesHeader
); 
 841       owHeader
->owTop 
= _ofPartitionOffset 
+ curOffset
; 
 842       owHeader
->owNext 
= 0; 
 844       owHeader
->owChecksum 
= 0; 
 845       owHeader
->owChecksum 
= ~generateOWChecksum(buffer
); 
 847       bcopy(buffer
, _ofImage
, _ofPartitionSize
); 
 850     IODelete(buffer
, UInt8
, _ofPartitionSize
); 
 852     if (!ok
) return kIOReturnBadArgument
; 
 855   _ofImageDirty 
= false; 
 856   _nvramImageDirty 
= true; 
 858   return kIOReturnSuccess
; 
 862   const char *variableName
; 
 865   SInt32     variableOffset
; 
 867 typedef struct OFVariable OFVariable
; 
 870   kOWVariableOffsetNumber 
= 8, 
 871   kOWVariableOffsetString 
= 17 
 874 OFVariable gOFVariables
[] = { 
 875   {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0}, 
 876   {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1}, 
 877   {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2}, 
 878   {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3}, 
 879   {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4}, 
 880   {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5}, 
 881   {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6}, 
 882   {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7}, 
 883   {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1}, 
 884   {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1}, 
 885   {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8}, 
 886   {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9}, 
 887   {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10}, 
 888   {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11}, 
 889   {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12}, 
 890   {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13}, 
 891   {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1}, 
 892   {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14}, 
 893   {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15}, 
 894   {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16}, 
 895   {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17}, 
 896   {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18}, 
 897   {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 898   {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 899   {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19}, 
 900   {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20}, 
 901   {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21}, 
 902   {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22}, 
 903   {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 904   {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 905   {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 906   {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23}, 
 907   {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24}, 
 908   {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25}, 
 909   {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26}, 
 910   {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 911   {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 912   {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 913   {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 914   {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 915   {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 916   {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 917   {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1}, 
 918   {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1}, 
 919   {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1}, 
 920   {"boot-image", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1}, 
 921   {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1} 
 924 UInt32 
IODTNVRAM::getOFVariableType(const OSSymbol 
*propSymbol
) const 
 928   ofVar 
= gOFVariables
; 
 930     if ((ofVar
->variableName 
== 0) || 
 931         propSymbol
->isEqualTo(ofVar
->variableName
)) break; 
 935   return ofVar
->variableType
; 
 938 UInt32 
IODTNVRAM::getOFVariablePerm(const OSSymbol 
*propSymbol
) const 
 942   ofVar 
= gOFVariables
; 
 944     if ((ofVar
->variableName 
== 0) || 
 945         propSymbol
->isEqualTo(ofVar
->variableName
)) break; 
 949   return ofVar
->variablePerm
; 
 952 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol 
**propSymbol
, 
 953                                   UInt32 
*propType
, UInt32 
*propOffset
) 
 957   ofVar 
= gOFVariables
; 
 959     if (ofVar
->variableName 
== 0) return false; 
 961     if (ofVar
->variableOffset 
== (SInt32
) variableNumber
) break; 
 966   *propSymbol 
= OSSymbol::withCStringNoCopy(ofVar
->variableName
); 
 967   *propType 
= ofVar
->variableType
; 
 970   case kOFVariableTypeBoolean 
: 
 971     *propOffset 
= 1 << (31 - variableNumber
); 
 974   case kOFVariableTypeNumber 
: 
 975     *propOffset 
= variableNumber 
- kOWVariableOffsetNumber
; 
 978   case kOFVariableTypeString 
: 
 979     *propOffset 
= variableNumber 
- kOWVariableOffsetString
; 
 986 bool IODTNVRAM::convertPropToObject(UInt8 
*propName
, UInt32 propNameLength
, 
 987                                     UInt8 
*propData
, UInt32 propDataLength
, 
 988                                     const OSSymbol 
**propSymbol
, 
 989                                     OSObject 
**propObject
) 
 992   const OSSymbol 
*tmpSymbol
; 
 997   // Create the symbol. 
 998   propName
[propNameLength
] = '\0'; 
 999   tmpSymbol 
= OSSymbol::withCString((const char *)propName
); 
1000   propName
[propNameLength
] = '='; 
1001   if (tmpSymbol 
== 0) { 
1005   propType 
= getOFVariableType(tmpSymbol
); 
1007   // Create the object. 
1010   case kOFVariableTypeBoolean 
: 
1011     if (!strncmp("true", (const char *)propData
, propDataLength
)) { 
1012       tmpObject 
= kOSBooleanTrue
; 
1013     } else if (!strncmp("false", (const char *)propData
, propDataLength
)) { 
1014       tmpObject 
= kOSBooleanFalse
; 
1018   case kOFVariableTypeNumber 
: 
1019     tmpNumber 
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32); 
1020     if (tmpNumber 
!= 0) tmpObject 
= tmpNumber
; 
1023   case kOFVariableTypeString 
: 
1024     tmpString 
= OSString::withCString((const char *)propData
); 
1025     if (tmpString 
!= 0) tmpObject 
= tmpString
; 
1028   case kOFVariableTypeData 
: 
1029     tmpObject 
= unescapeBytesToData(propData
, propDataLength
); 
1033   if (tmpObject 
== 0) { 
1034     tmpSymbol
->release(); 
1038   *propSymbol 
= tmpSymbol
; 
1039   *propObject 
= tmpObject
; 
1044 bool IODTNVRAM::convertObjectToProp(UInt8 
*buffer
, UInt32 
*length
, 
1045                                     const OSSymbol 
*propSymbol
, OSObject 
*propObject
) 
1047   const UInt8    
*propName
; 
1048   UInt32         propNameLength
, propDataLength
; 
1049   UInt32         propType
, tmpValue
; 
1050   OSBoolean      
*tmpBoolean 
= 0; 
1051   OSNumber       
*tmpNumber 
= 0; 
1052   OSString       
*tmpString 
= 0; 
1053   OSData         
*tmpData 
= 0; 
1055   propName 
= (const UInt8 
*)propSymbol
->getCStringNoCopy(); 
1056   propNameLength 
= propSymbol
->getLength(); 
1057   propType 
= getOFVariableType(propSymbol
); 
1059   // Get the size of the data. 
1060   propDataLength 
= 0xFFFFFFFF; 
1062   case kOFVariableTypeBoolean 
: 
1063     tmpBoolean 
= OSDynamicCast(OSBoolean
, propObject
); 
1064     if (tmpBoolean 
!= 0) propDataLength 
= 5; 
1067   case kOFVariableTypeNumber 
: 
1068     tmpNumber 
= OSDynamicCast(OSNumber
, propObject
); 
1069     if (tmpNumber 
!= 0) propDataLength 
= 10; 
1072   case kOFVariableTypeString 
: 
1073     tmpString 
= OSDynamicCast(OSString
, propObject
); 
1074     if (tmpString 
!= 0) propDataLength 
= tmpString
->getLength(); 
1077   case kOFVariableTypeData 
: 
1078     tmpData 
= OSDynamicCast(OSData
, propObject
);  
1080       tmpData 
= escapeDataToData(tmpData
); 
1081       propDataLength 
= tmpData
->getLength(); 
1086   // Make sure the propertySize is known and will fit. 
1087   if (propDataLength 
== 0xFFFFFFFF) return false; 
1088   if ((propNameLength 
+ propDataLength 
+ 2) > *length
) return false; 
1090   // Copy the property name equal sign. 
1091   sprintf((char *)buffer
, "%s=", propName
); 
1092   buffer 
+= propNameLength 
+ 1; 
1095   case kOFVariableTypeBoolean 
: 
1096     if (tmpBoolean
->getValue()) { 
1097       strcpy((char *)buffer
, "true"); 
1099       strcpy((char *)buffer
, "false"); 
1103   case kOFVariableTypeNumber 
: 
1104     tmpValue 
= tmpNumber
->unsigned32BitValue(); 
1105     if (tmpValue 
== 0xFFFFFFFF) { 
1106       strcpy((char *)buffer
, "-1"); 
1107     } else if (tmpValue 
< 1000) { 
1108       sprintf((char *)buffer
, "%ld", tmpValue
); 
1110       sprintf((char *)buffer
, "0x%lx", tmpValue
); 
1114   case kOFVariableTypeString 
: 
1115     strcpy((char *)buffer
, tmpString
->getCStringNoCopy()); 
1118   case kOFVariableTypeData 
: 
1119     bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
); 
1124   propDataLength 
= strlen((const char *)buffer
);   
1126   *length 
= propNameLength 
+ propDataLength 
+ 2; 
1132 UInt16 
IODTNVRAM::generateOWChecksum(UInt8 
*buffer
) 
1134   UInt32 cnt
, checksum 
= 0; 
1135   UInt16 
*tmpBuffer 
= (UInt16 
*)buffer
; 
1137   for (cnt 
= 0; cnt 
< _ofPartitionSize 
/ 2; cnt
++) 
1138     checksum 
+= tmpBuffer
[cnt
]; 
1140   return checksum 
% 0x0000FFFF; 
1143 bool IODTNVRAM::validateOWChecksum(UInt8 
*buffer
) 
1145   UInt32 cnt
, checksum
, sum 
= 0; 
1146   UInt16 
*tmpBuffer 
= (UInt16 
*)buffer
; 
1148   for (cnt 
= 0; cnt 
< _ofPartitionSize 
/ 2; cnt
++) 
1149     sum 
+= tmpBuffer
[cnt
]; 
1151   checksum 
= (sum 
>> 16) + (sum 
& 0x0000FFFF); 
1152   if (checksum 
== 0x10000) checksum
--; 
1153   checksum 
= (checksum 
^ 0x0000FFFF) & 0x0000FFFF; 
1155   return checksum 
== 0; 
1158 void IODTNVRAM::updateOWBootArgs(const OSSymbol 
*key
, OSObject 
*value
) 
1160   bool        wasBootArgs
, bootr 
= false; 
1162   OSString    
*tmpString
, *bootCommand
, *bootArgs 
= 0; 
1163   const UInt8 
*bootCommandData
, *bootArgsData
; 
1165   UInt32      bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
; 
1167   tmpString 
= OSDynamicCast(OSString
, value
); 
1168   if (tmpString 
== 0) return; 
1170   if (key
->isEqualTo("boot-command")) { 
1171     wasBootArgs 
= false; 
1172     bootCommand 
= tmpString
; 
1173   } else if (key
->isEqualTo("boot-args")) { 
1175     bootArgs 
= tmpString
; 
1176     bootCommand 
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command")); 
1177     if (bootCommand 
== 0) return; 
1180   bootCommandData 
= (const UInt8 
*)bootCommand
->getCStringNoCopy(); 
1181   bootCommandDataLength 
= bootCommand
->getLength(); 
1183   if (bootCommandData 
== 0) return; 
1185   for (cnt 
= 0; cnt 
< bootCommandDataLength
; cnt
++) { 
1186     if ((bootCommandData
[cnt
] == 'b') && 
1187         !strncmp("bootr", (const char *)bootCommandData 
+ cnt
, 5)) { 
1189       while (bootCommandData
[cnt
] == ' ') cnt
++; 
1195     _ofDict
->removeObject("boot-args"); 
1200     bootArgsData 
= (const UInt8 
*)bootArgs
->getCStringNoCopy(); 
1201     bootArgsDataLength 
= bootArgs
->getLength(); 
1202     if (bootArgsData 
== 0) return; 
1204     tmpDataLength 
= cnt 
+ bootArgsDataLength
; 
1205     tmpData 
= IONew(UInt8
, tmpDataLength 
+ 1); 
1206     if (tmpData 
== 0) return; 
1208     strncpy((char *)tmpData
, (const char *)bootCommandData
, cnt
); 
1209     tmpData
[cnt
] = '\0'; 
1210     strcat((char *)tmpData
, (const char *)bootArgsData
); 
1212     bootCommand 
= OSString::withCString((const char *)tmpData
); 
1213     if (bootCommand 
!= 0) { 
1214       _ofDict
->setObject("boot-command", bootCommand
); 
1215       bootCommand
->release(); 
1218     IODelete(tmpData
, UInt8
, tmpDataLength 
+ 1); 
1220     bootArgs 
= OSString::withCString((const char *)(bootCommandData 
+ cnt
)); 
1221     if (bootArgs 
!= 0) { 
1222       _ofDict
->setObject("boot-args", bootArgs
); 
1223       bootArgs
->release(); 
1229 // Private methods for Name Registry access. 
1232   kMaxNVNameLength 
= 4, 
1233   kMaxNVDataLength 
= 8 
1236 #pragma options align=mac68k 
1237 struct NVRAMProperty
 
1239   IONVRAMDescriptor   header
; 
1241   UInt8               name
[ kMaxNVNameLength 
]; 
1243   UInt8               data
[ kMaxNVDataLength 
]; 
1245 #pragma options align=reset 
1247 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor 
*hdr
, UInt32 
*where
) 
1252   nvEnd 
= *((UInt16 
*)_nrImage
); 
1253   if(getPlatform()->getBootROMType()) { 
1254     // on NewWorld, offset to partition start 
1257     // on old world, absolute 
1258     nvEnd 
-= _nrPartitionOffset
; 
1260   if((nvEnd 
< 0) || (nvEnd 
>= kIODTNVRAMNameRegistrySize
)) 
1264   while ((offset 
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) { 
1265     if (bcmp(_nrImage 
+ offset
, hdr
, sizeof(*hdr
)) == 0) { 
1269     offset 
+= sizeof(NVRAMProperty
); 
1272   if ((nvEnd 
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
) 
1280 IOReturn 
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry 
*entry
, 
1281                                            const OSSymbol 
**name
, 
1284   IONVRAMDescriptor hdr
; 
1285   NVRAMProperty     
*prop
; 
1289   char              nameBuf
[kMaxNVNameLength 
+ 1]; 
1291   if (_nrImage 
== 0) return kIOReturnUnsupported
; 
1292   if ((entry 
== 0) || (name 
== 0) || (value 
== 0)) return kIOReturnBadArgument
; 
1294   err 
= IODTMakeNVDescriptor(entry
, &hdr
); 
1295   if (err 
!= kIOReturnSuccess
) return err
; 
1297   if (searchNVRAMProperty(&hdr
, &offset
)) { 
1298     prop 
= (NVRAMProperty 
*)(_nrImage 
+ offset
); 
1300     length 
= prop
->nameLength
; 
1301     if (length 
> kMaxNVNameLength
) length 
= kMaxNVNameLength
; 
1302     strncpy(nameBuf
, (const char *)prop
->name
, length
); 
1303     nameBuf
[length
] = 0; 
1304     *name 
= OSSymbol::withCString(nameBuf
); 
1306     length 
= prop
->dataLength
; 
1307     if (length 
> kMaxNVDataLength
) length 
= kMaxNVDataLength
; 
1308     *value 
= OSData::withBytes(prop
->data
, length
); 
1310     if ((*name 
!= 0) && (*value 
!= 0)) return kIOReturnSuccess
; 
1311     else return kIOReturnNoMemory
; 
1314   return kIOReturnNoResources
; 
1317 IOReturn 
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry 
*entry
, 
1318                                             const OSSymbol 
*name
, 
1321   IONVRAMDescriptor hdr
; 
1322   NVRAMProperty     
*prop
; 
1323   IOByteCount       nameLength
; 
1324   IOByteCount       dataLength
; 
1330   if (_nrImage 
== 0) return kIOReturnUnsupported
; 
1331   if ((entry 
== 0) || (name 
== 0) || (value 
== 0)) return kIOReturnBadArgument
; 
1333   nameLength 
= name
->getLength(); 
1334   dataLength 
= value
->getLength(); 
1335   if (nameLength 
> kMaxNVNameLength
) return kIOReturnNoSpace
; 
1336   if (dataLength 
> kMaxNVDataLength
) return kIOReturnNoSpace
; 
1338   err 
= IODTMakeNVDescriptor(entry
, &hdr
); 
1339   if (err 
!= kIOReturnSuccess
) return err
; 
1341   exists 
= searchNVRAMProperty(&hdr
, &offset
); 
1342   if (offset 
== 0) return kIOReturnNoMemory
; 
1344   prop 
= (NVRAMProperty 
*)(_nrImage 
+ offset
); 
1345   if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
)); 
1347   prop
->nameLength 
= nameLength
; 
1348   bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
); 
1349   prop
->dataLength 
= dataLength
; 
1350   bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
); 
1353     nvLength 
= offset 
+ sizeof(NVRAMProperty
); 
1354     if (getPlatform()->getBootROMType()) 
1357       nvLength 
+= _nrPartitionOffset
; 
1358     *((UInt16 
*)_nrImage
) = nvLength
; 
1361   _nvramImageDirty 
= true; 
1366 OSData 
*IODTNVRAM::unescapeBytesToData(const UInt8 
*bytes
, UInt32 length
) 
1369   UInt32 totalLength 
= 0; 
1374   // Calculate the actual length of the data. 
1377   for (cnt 
= 0; cnt 
< length
;) { 
1378     byte 
= bytes
[cnt
++]; 
1380       byte 
= bytes
[cnt
++]; 
1388     totalLength 
+= cnt2
; 
1392     // Create an empty OSData of the correct size. 
1393     data 
= OSData::withCapacity(totalLength
); 
1395       for (cnt 
= 0; cnt 
< length
;) { 
1396         byte 
= bytes
[cnt
++]; 
1398           byte 
= bytes
[cnt
++]; 
1400           byte 
= (byte 
& 0x80) ? 0xFF : 0x00; 
1403         data
->appendByte(byte
, cnt2
); 
1411 OSData 
* IODTNVRAM::escapeDataToData(OSData 
* value
) 
1414   const UInt8 
*  startPtr
; 
1415   const UInt8 
*  endPtr
; 
1416   const UInt8 
*  wherePtr
; 
1420   wherePtr 
= (const UInt8 
*) value
->getBytesNoCopy(); 
1421   endPtr 
= wherePtr 
+ value
->getLength(); 
1423   result 
= OSData::withCapacity(endPtr 
- wherePtr
); 
1427   while (wherePtr 
< endPtr
) { 
1428     startPtr 
= wherePtr
; 
1430     if ((byte 
== 0x00) || (byte 
== 0xFF)) { 
1432             ((wherePtr 
- startPtr
) < 0x80) && (wherePtr 
< endPtr
) && (byte 
== *wherePtr
); 
1434       ok 
&= result
->appendByte(0xff, 1); 
1435       byte 
= (byte 
& 0x80) | (wherePtr 
- startPtr
); 
1437     ok 
&= result
->appendByte(byte
, 1); 
1439   ok 
&= result
->appendByte(0, 1); 
1449 static bool IsApplePropertyName(const char * propName
) 
1452   while ((c 
= *propName
++)) { 
1453     if ((c 
>= 'A') && (c 
<= 'Z')) 
1460 IOReturn 
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry 
*entry
, 
1461                                            const OSSymbol 
**name
, 
1464   IOReturn    err 
= kIOReturnNoResources
; 
1466   const UInt8 
*startPtr
; 
1467   const UInt8 
*endPtr
; 
1468   const UInt8 
*wherePtr
; 
1469   const UInt8 
*nvPath 
= 0; 
1470   const char  *nvName 
= 0; 
1471   const char  *resultName 
= 0; 
1472   const UInt8 
*resultValue 
= 0; 
1473   UInt32       resultValueLen 
= 0; 
1476   if (_ofDict 
== 0) return err
; 
1477   data 
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
)); 
1478   if (data 
== 0) return err
; 
1480   startPtr 
= (const UInt8 
*) data
->getBytesNoCopy(); 
1481   endPtr 
= startPtr 
+ data
->getLength(); 
1483   wherePtr 
= startPtr
; 
1484   while (wherePtr 
< endPtr
) { 
1485     byte 
= *(wherePtr
++); 
1491     else if (nvName 
== 0) 
1492       nvName 
= (const char *) startPtr
; 
1494       IORegistryEntry 
* compareEntry 
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
); 
1496         compareEntry
->release(); 
1497       if (entry 
== compareEntry
) { 
1498         bool appleProp 
= IsApplePropertyName(nvName
); 
1499         if (!appleProp 
|| !resultName
) { 
1500           resultName     
= nvName
; 
1501           resultValue    
= startPtr
; 
1502           resultValueLen 
= wherePtr 
- startPtr 
- 1; 
1510     startPtr 
= wherePtr
; 
1513     *name 
= OSSymbol::withCString(resultName
); 
1514     *value 
= unescapeBytesToData(resultValue
, resultValueLen
); 
1515     if ((*name 
!= 0) && (*value 
!= 0)) 
1516       err 
= kIOReturnSuccess
; 
1518       err 
= kIOReturnNoMemory
; 
1523 IOReturn 
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry 
*entry
, 
1524                                             const OSSymbol 
*propName
, 
1529   const UInt8  
*startPtr
; 
1530   const UInt8  
*propStart
; 
1531   const UInt8  
*endPtr
; 
1532   const UInt8  
*wherePtr
; 
1533   const UInt8  
*nvPath 
= 0; 
1534   const char   *nvName 
= 0; 
1539   bool         settingAppleProp
; 
1541   if (_ofDict 
== 0) return kIOReturnNoResources
; 
1543   settingAppleProp 
= IsApplePropertyName(propName
->getCStringNoCopy()); 
1545   // copy over existing properties for other entries 
1547   oldData 
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
)); 
1549     startPtr 
= (const UInt8 
*) oldData
->getBytesNoCopy(); 
1550     endPtr 
= startPtr 
+ oldData
->getLength(); 
1552     propStart 
= startPtr
; 
1553     wherePtr 
= startPtr
; 
1554     while (wherePtr 
< endPtr
) { 
1555       byte 
= *(wherePtr
++); 
1560       else if (nvName 
== 0) 
1561         nvName 
= (const char *) startPtr
; 
1563         IORegistryEntry 
* compareEntry 
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
); 
1565           compareEntry
->release(); 
1566         if (entry 
== compareEntry
) { 
1567           if ((settingAppleProp 
&& propName
->isEqualTo(nvName
)) 
1568            || (!settingAppleProp 
&& !IsApplePropertyName(nvName
))) { 
1569              // delete old property (nvPath -> wherePtr) 
1570              data 
= OSData::withBytes(propStart
, nvPath 
- propStart
); 
1572                ok 
&= data
->appendBytes(wherePtr
, endPtr 
- wherePtr
); 
1580       startPtr 
= wherePtr
; 
1584   // make the new property 
1588       data 
= OSData::withData(oldData
); 
1590       data 
= OSData::withCapacity(16); 
1592       return kIOReturnNoMemory
; 
1595   if (value 
&& value
->getLength()) { 
1596                 // get entries in path 
1597                 OSArray 
*array 
= OSArray::withCapacity(5); 
1600                         return kIOReturnNoMemory
; 
1603                         array
->setObject(entry
); 
1604                 while ((entry 
= entry
->getParentEntry(gIODTPlane
))); 
1607                 for (int i 
= array
->getCount() - 3; 
1608                                         (entry 
= (IORegistryEntry 
*) array
->getObject(i
)); 
1611                         name 
= entry
->getName(gIODTPlane
); 
1612                         comp 
= entry
->getLocation(gIODTPlane
); 
1613                         if( comp 
&& (0 == strcmp("pci", name
)) 
1614                          && (0 == strcmp("80000000", comp
))) { 
1616                                 comp 
= "/pci@80000000"; 
1619                                         ok 
&= data
->appendBytes("/@", 2); 
1623                                         ok 
&= data
->appendByte('/', 1); 
1627                         ok 
&= data
->appendBytes(comp
, strlen(comp
)); 
1629                 ok 
&= data
->appendByte(0, 1); 
1633                 ok 
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1); 
1635                 // append escaped data 
1636                 oldData 
= escapeDataToData(value
); 
1637                 ok 
&= (oldData 
!= 0); 
1639                         ok 
&= data
->appendBytes(oldData
); 
1642     ok 
= _ofDict
->setObject(_registryPropertiesKey
, data
); 
1644       _ofImageDirty 
= true; 
1648   return ok 
? kIOReturnSuccess 
: kIOReturnNoMemory
;