2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
3 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
5 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. The rights granted to you under the License
11 * may not be used to create, or enable the creation or redistribution of,
12 * unlawful or unlicensed copies of an Apple operating system, or to
13 * circumvent, violate, or enable the circumvention or violation of, any
14 * terms of an Apple operating system software license agreement.
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this file.
19 * The Original Code and all software distributed under the License are
20 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24 * Please see the License for the specific language governing rights and
25 * limitations under the License.
27 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 #include <IOKit/IOLib.h>
31 #include <IOKit/IONVRAM.h>
32 #include <IOKit/IOPlatformExpert.h>
33 #include <IOKit/IOUserClient.h>
34 #include <IOKit/IOKitKeys.h>
35 #include <IOKit/IOKitKeysPrivate.h>
36 #include <kern/debug.h>
37 #include <pexpert/pexpert.h>
39 #define super IOService
41 #define kIONVRAMPrivilege kIOClientPrivilegeAdministrator
42 //#define kIONVRAMPrivilege kIOClientPrivilegeLocalUser
44 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
);
46 bool IODTNVRAM::init(IORegistryEntry
*old
, const IORegistryPlane
*plane
)
50 if (!super::init(old
, plane
)) return false;
52 dict
= OSDictionary::withCapacity(1);
53 if (dict
== 0) return false;
54 setPropertyTable(dict
);
56 _nvramImage
= IONew(UInt8
, kIODTNVRAMImageSize
);
57 if (_nvramImage
== 0) return false;
59 _nvramPartitionOffsets
= OSDictionary::withCapacity(1);
60 if (_nvramPartitionOffsets
== 0) return false;
62 _nvramPartitionLengths
= OSDictionary::withCapacity(1);
63 if (_nvramPartitionLengths
== 0) return false;
65 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
66 if (_registryPropertiesKey
== 0) return false;
68 // <rdar://problem/9529235> race condition possible between
69 // IODTNVRAM and IONVRAMController (restore loses boot-args)
75 void IODTNVRAM::initProxyData(void)
77 IORegistryEntry
*entry
;
78 const char *key
= "nvram-proxy-data";
83 entry
= IORegistryEntry::fromPath("/chosen", gIODTPlane
);
85 prop
= entry
->getProperty(key
);
87 data
= OSDynamicCast(OSData
, prop
);
89 bytes
= data
->getBytesNoCopy();
90 if ((bytes
!= 0) && (data
->getLength() <= kIODTNVRAMImageSize
)) {
91 bcopy(bytes
, _nvramImage
, data
->getLength());
97 entry
->removeProperty(key
);
102 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
104 if (_nvramController
!= 0) return;
106 _nvramController
= nvram
;
108 // <rdar://problem/9529235> race condition possible between
109 // IODTNVRAM and IONVRAMController (restore loses boot-args)
111 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
115 (void) syncVariables();
116 IOLockUnlock(_ofLock
);
120 void IODTNVRAM::initNVRAMImage(void)
122 char partitionID
[18];
123 UInt32 partitionOffset
, partitionLength
;
124 UInt32 freePartitionOffset
, freePartitionSize
;
125 UInt32 currentLength
, currentOffset
= 0;
126 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
128 // Find the offsets for the OF, XPRAM, NameRegistry and PanicInfo partitions.
129 _ofPartitionOffset
= 0xFFFFFFFF;
130 _piPartitionOffset
= 0xFFFFFFFF;
131 freePartitionOffset
= 0xFFFFFFFF;
132 freePartitionSize
= 0;
134 // Look through the partitions to find the OF, MacOS partitions.
135 while (currentOffset
< kIODTNVRAMImageSize
) {
136 currentLength
= ((UInt16
*)(_nvramImage
+ currentOffset
))[1] * 16;
138 if (currentLength
< 16) break;
139 partitionOffset
= currentOffset
+ 16;
140 partitionLength
= currentLength
- 16;
141 if ((partitionOffset
+ partitionLength
) > kIODTNVRAMImageSize
) break;
143 if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
144 kIODTNVRAMOFPartitionName
, 12) == 0) {
145 _ofPartitionOffset
= partitionOffset
;
146 _ofPartitionSize
= partitionLength
;
147 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
148 kIODTNVRAMXPRAMPartitionName
, 12) == 0) {
149 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
150 kIODTNVRAMPanicInfoPartitonName
, 12) == 0) {
151 _piPartitionOffset
= partitionOffset
;
152 _piPartitionSize
= partitionLength
;
153 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
154 kIODTNVRAMFreePartitionName
, 12) == 0) {
155 freePartitionOffset
= currentOffset
;
156 freePartitionSize
= currentLength
;
158 // Construct the partition ID from the signature and name.
159 snprintf(partitionID
, sizeof(partitionID
), "0x%02x,",
160 *(UInt8
*)(_nvramImage
+ currentOffset
));
161 strncpy(partitionID
+ 5,
162 (const char *)(_nvramImage
+ currentOffset
+ 4), 12);
163 partitionID
[17] = '\0';
165 partitionOffsetNumber
= OSNumber::withNumber(partitionOffset
, 32);
166 partitionLengthNumber
= OSNumber::withNumber(partitionLength
, 32);
168 // Save the partition offset and length
169 _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
);
170 _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
);
172 partitionOffsetNumber
->release();
173 partitionLengthNumber
->release();
175 currentOffset
+= currentLength
;
178 if (_ofPartitionOffset
!= 0xFFFFFFFF)
179 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
181 if (_piPartitionOffset
== 0xFFFFFFFF) {
182 if (freePartitionSize
> 0x20) {
183 // Set the signature to 0xa1.
184 _nvramImage
[freePartitionOffset
] = 0xa1;
185 // Set the checksum to 0.
186 _nvramImage
[freePartitionOffset
+ 1] = 0;
187 // Set the name for the Panic Info partition.
188 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
189 kIODTNVRAMPanicInfoPartitonName
, 12);
191 // Calculate the partition offset and size.
192 _piPartitionOffset
= freePartitionOffset
+ 0x10;
193 _piPartitionSize
= 0x800;
194 if (_piPartitionSize
+ 0x20 > freePartitionSize
)
195 _piPartitionSize
= freePartitionSize
- 0x20;
197 _piImage
= _nvramImage
+ _piPartitionOffset
;
199 // Zero the new partition.
200 bzero(_piImage
, _piPartitionSize
);
202 // Set the partition size.
203 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
204 (_piPartitionSize
/ 0x10) + 1;
206 // Set the partition checksum.
207 _nvramImage
[freePartitionOffset
+ 1] =
208 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
210 // Calculate the free partition offset and size.
211 freePartitionOffset
+= _piPartitionSize
+ 0x10;
212 freePartitionSize
-= _piPartitionSize
+ 0x10;
214 // Set the signature to 0x7f.
215 _nvramImage
[freePartitionOffset
] = 0x7f;
216 // Set the checksum to 0.
217 _nvramImage
[freePartitionOffset
+ 1] = 0;
218 // Set the name for the free partition.
219 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
220 kIODTNVRAMFreePartitionName
, 12);
221 // Set the partition size.
222 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
223 freePartitionSize
/ 0x10;
224 // Set the partition checksum.
225 _nvramImage
[freePartitionOffset
+ 1] =
226 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
228 if (_nvramController
!= 0) {
229 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
233 _piImage
= _nvramImage
+ _piPartitionOffset
;
237 _freshInterval
= TRUE
; // we will allow sync() even before the first 15 minutes have passed.
242 void IODTNVRAM::syncInternal(bool rateLimit
)
244 // Don't try to perform controller operations if none has been registered.
245 if (_nvramController
== 0) return;
247 // Rate limit requests to sync. Drivers that need this rate limiting will
248 // shadow the data and only write to flash when they get a sync call
249 if (rateLimit
&& !safeToSync()) return;
251 _nvramController
->sync();
254 void IODTNVRAM::sync(void)
259 bool IODTNVRAM::serializeProperties(OSSerialize
*s
) const
261 bool result
, hasPrivilege
;
265 OSCollectionIterator
*iter
= 0;
267 // Verify permissions.
268 hasPrivilege
= (kIOReturnSuccess
== IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
));
271 /* No nvram. Return an empty dictionary. */
272 dict
= OSDictionary::withCapacity(1);
273 if (dict
== 0) return false;
276 dict
= OSDictionary::withDictionary(_ofDict
);
277 IOLockUnlock(_ofLock
);
278 if (dict
== 0) return false;
280 /* Copy properties with client privilege. */
281 iter
= OSCollectionIterator::withCollection(dict
);
287 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
290 variablePerm
= getOFVariablePerm(key
);
291 if ((hasPrivilege
|| (variablePerm
!= kOFVariablePermRootOnly
)) &&
292 ( ! (variablePerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) )) { }
294 dict
->removeObject(key
);
300 result
= dict
->serialize(s
);
303 if (iter
!= 0) iter
->release();
308 OSObject
*IODTNVRAM::copyProperty(const OSSymbol
*aKey
) const
314 if (_ofDict
== 0) return 0;
316 // Verify permissions.
317 variablePerm
= getOFVariablePerm(aKey
);
318 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
319 if (result
!= kIOReturnSuccess
) {
320 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
322 if (variablePerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return 0;
325 theObject
= _ofDict
->getObject(aKey
);
326 if (theObject
) theObject
->retain();
327 IOLockUnlock(_ofLock
);
332 OSObject
*IODTNVRAM::copyProperty(const char *aKey
) const
334 const OSSymbol
*keySymbol
;
335 OSObject
*theObject
= 0;
337 keySymbol
= OSSymbol::withCString(aKey
);
338 if (keySymbol
!= 0) {
339 theObject
= copyProperty(keySymbol
);
340 keySymbol
->release();
346 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
350 theObject
= copyProperty(aKey
);
351 if (theObject
) theObject
->release();
356 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
360 theObject
= copyProperty(aKey
);
361 if (theObject
) theObject
->release();
366 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
369 UInt32 propType
, propPerm
;
370 OSString
*tmpString
= 0;
371 OSObject
*propObject
= 0, *oldObject
;
373 if (_ofDict
== 0) return false;
375 // Verify permissions.
376 propPerm
= getOFVariablePerm(aKey
);
377 if (IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
) != kIOReturnSuccess
) {
378 if (propPerm
!= kOFVariablePermUserWrite
) return false;
380 if (propPerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return 0;
382 // Don't allow change of 'aapl,panic-info'.
383 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return false;
385 // Make sure the object is of the correct type.
386 propType
= getOFVariableType(aKey
);
388 case kOFVariableTypeBoolean
:
389 propObject
= OSDynamicCast(OSBoolean
, anObject
);
392 case kOFVariableTypeNumber
:
393 propObject
= OSDynamicCast(OSNumber
, anObject
);
396 case kOFVariableTypeString
:
397 propObject
= OSDynamicCast(OSString
, anObject
);
400 case kOFVariableTypeData
:
401 propObject
= OSDynamicCast(OSData
, anObject
);
402 if (propObject
== 0) {
403 tmpString
= OSDynamicCast(OSString
, anObject
);
404 if (tmpString
!= 0) {
405 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
406 tmpString
->getLength());
412 if (propObject
== 0) return false;
416 oldObject
= _ofDict
->getObject(aKey
);
420 result
= _ofDict
->setObject(aKey
, propObject
);
423 if (syncVariables() != kIOReturnSuccess
) {
425 _ofDict
->setObject(aKey
, oldObject
);
428 _ofDict
->removeObject(aKey
);
430 (void) syncVariables();
436 oldObject
->release();
439 propObject
->release();
442 IOLockUnlock(_ofLock
);
447 void IODTNVRAM::removeProperty(const OSSymbol
*aKey
)
452 if (_ofDict
== 0) return;
454 // Verify permissions.
455 propPerm
= getOFVariablePerm(aKey
);
456 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
457 if (result
!= kIOReturnSuccess
) {
458 if (propPerm
!= kOFVariablePermUserWrite
) return;
460 if (propPerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return;
462 // Don't allow change of 'aapl,panic-info'.
463 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return;
465 // If the object exists, remove it from the dictionary.
468 result
= _ofDict
->getObject(aKey
) != 0;
470 _ofDict
->removeObject(aKey
);
474 (void) syncVariables();
477 IOLockUnlock(_ofLock
);
480 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
485 const OSString
*tmpStr
;
487 OSCollectionIterator
*iter
;
489 dict
= OSDynamicCast(OSDictionary
, properties
);
490 if (dict
== 0) return kIOReturnBadArgument
;
492 iter
= OSCollectionIterator::withCollection(dict
);
493 if (iter
== 0) return kIOReturnBadArgument
;
496 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
499 object
= dict
->getObject(key
);
500 if (object
== 0) continue;
502 if (key
->isEqualTo(kIONVRAMDeletePropertyKey
)) {
503 tmpStr
= OSDynamicCast(OSString
, object
);
505 key
= OSSymbol::withString(tmpStr
);
512 } else if(key
->isEqualTo(kIONVRAMSyncNowPropertyKey
) || key
->isEqualTo(kIONVRAMForceSyncNowPropertyKey
)) {
513 tmpStr
= OSDynamicCast(OSString
, object
);
518 // We still want to throttle NVRAM commit rate for SyncNow. ForceSyncNow is provided as a really big hammer.
520 syncInternal(key
->isEqualTo(kIONVRAMSyncNowPropertyKey
));
527 result
= setProperty(key
, object
);
534 if (result
) return kIOReturnSuccess
;
535 else return kIOReturnError
;
538 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
541 return kIOReturnUnsupported
;
544 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
547 return kIOReturnUnsupported
;
550 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
551 const OSSymbol
**name
,
556 err
= readNVRAMPropertyType1(entry
, name
, value
);
561 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
562 const OSSymbol
*name
,
567 err
= writeNVRAMPropertyType1(entry
, name
, value
);
572 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
574 return _nvramPartitionLengths
;
577 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
578 IOByteCount offset
, UInt8
*buffer
,
581 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
582 UInt32 partitionOffset
, partitionLength
, end
;
584 partitionOffsetNumber
=
585 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
586 partitionLengthNumber
=
587 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
589 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
590 return kIOReturnNotFound
;
592 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
593 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
595 if (os_add_overflow(offset
, length
, &end
)) return kIOReturnBadArgument
;
596 if ((buffer
== 0) || (length
== 0) || (end
> partitionLength
))
597 return kIOReturnBadArgument
;
599 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
601 return kIOReturnSuccess
;
604 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
605 IOByteCount offset
, UInt8
*buffer
,
608 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
609 UInt32 partitionOffset
, partitionLength
, end
;
611 partitionOffsetNumber
=
612 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
613 partitionLengthNumber
=
614 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
616 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
617 return kIOReturnNotFound
;
619 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
620 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
622 if (os_add_overflow(offset
, length
, &end
)) return kIOReturnBadArgument
;
623 if ((buffer
== 0) || (length
== 0) || (end
> partitionLength
))
624 return kIOReturnBadArgument
;
626 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
628 if (_nvramController
!= 0) {
629 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
632 return kIOReturnSuccess
;
635 IOByteCount
IODTNVRAM::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
637 if ((_piImage
== 0) || (length
<= 0)) return 0;
639 if (length
> (_piPartitionSize
- 4))
640 length
= _piPartitionSize
- 4;
642 // Save the Panic Info.
643 bcopy(buffer
, _piImage
+ 4, length
);
645 // Save the Panic Info length.
646 *(UInt32
*)_piImage
= length
;
648 if (_nvramController
!= 0) {
649 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
652 * This prevents OF variables from being committed if the system has panicked
654 _systemPaniced
= true;
655 /* The call to sync() forces the NVRAM controller to write the panic info
656 * partition to NVRAM.
665 UInt8
IODTNVRAM::calculatePartitionChecksum(UInt8
*partitionHeader
)
667 UInt8 cnt
, isum
, csum
= 0;
669 for (cnt
= 0; cnt
< 0x10; cnt
++) {
670 isum
= csum
+ partitionHeader
[cnt
];
671 if (isum
< csum
) isum
++;
678 IOReturn
IODTNVRAM::initOFVariables(void)
681 UInt8
*propName
, *propData
;
682 UInt32 propNameLength
, propDataLength
;
683 const OSSymbol
*propSymbol
;
684 OSObject
*propObject
;
686 if (_ofImage
== 0) return kIOReturnNotReady
;
688 _ofDict
= OSDictionary::withCapacity(1);
689 _ofLock
= IOLockAlloc();
690 if (!_ofDict
|| !_ofLock
) return kIOReturnNoMemory
;
693 while (cnt
< _ofPartitionSize
) {
694 // Break if there is no name.
695 if (_ofImage
[cnt
] == '\0') break;
697 // Find the length of the name.
698 propName
= _ofImage
+ cnt
;
699 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
701 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
704 // Break if the name goes past the end of the partition.
705 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
706 cnt
+= propNameLength
+ 1;
708 propData
= _ofImage
+ cnt
;
709 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
711 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
714 // Break if the data goes past the end of the partition.
715 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
716 cnt
+= propDataLength
+ 1;
718 if (convertPropToObject(propName
, propNameLength
,
719 propData
, propDataLength
,
720 &propSymbol
, &propObject
)) {
721 _ofDict
->setObject(propSymbol
, propObject
);
722 propSymbol
->release();
723 propObject
->release();
727 // Create the boot-args property if it is not in the dictionary.
728 if (_ofDict
->getObject("boot-args") == 0) {
729 propObject
= OSString::withCStringNoCopy("");
730 if (propObject
!= 0) {
731 _ofDict
->setObject("boot-args", propObject
);
732 propObject
->release();
737 propDataLength
= *(UInt32
*)_piImage
;
738 if ((propDataLength
!= 0) && (propDataLength
<= (_piPartitionSize
- 4))) {
739 propObject
= OSData::withBytes(_piImage
+ 4, propDataLength
);
740 _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
);
741 propObject
->release();
743 // Clear the length from _piImage and mark dirty.
744 *(UInt32
*)_piImage
= 0;
745 if (_nvramController
!= 0) {
746 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
751 return kIOReturnSuccess
;
754 IOReturn
IODTNVRAM::syncOFVariables(void)
756 return kIOReturnUnsupported
;
759 IOReturn
IODTNVRAM::syncVariables(void)
762 UInt32 length
, maxLength
;
763 UInt8
*buffer
, *tmpBuffer
;
764 const OSSymbol
*tmpSymbol
;
766 OSCollectionIterator
*iter
;
768 IOLockAssert(_ofLock
, kIOLockAssertOwned
);
770 if ((_ofImage
== 0) || (_ofDict
== 0) || _systemPaniced
) return kIOReturnNotReady
;
772 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
773 if (buffer
== 0) return kIOReturnNoMemory
;
774 bzero(buffer
, _ofPartitionSize
);
777 maxLength
= _ofPartitionSize
;
779 iter
= OSCollectionIterator::withCollection(_ofDict
);
780 if (iter
== 0) ok
= false;
783 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
784 if (tmpSymbol
== 0) break;
786 // Don't save 'aapl,panic-info'.
787 if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue;
789 tmpObject
= _ofDict
->getObject(tmpSymbol
);
792 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
801 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
804 IODelete(buffer
, UInt8
, _ofPartitionSize
);
806 if (!ok
) return kIOReturnBadArgument
;
808 if (_nvramController
!= 0) {
809 return _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
812 return kIOReturnNotReady
;
816 const char *variableName
;
819 SInt32 variableOffset
;
821 typedef struct OFVariable OFVariable
;
824 kOWVariableOffsetNumber
= 8,
825 kOWVariableOffsetString
= 17
829 OFVariable gOFVariables
[] = {
830 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
831 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
832 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
833 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
834 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
835 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
836 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
837 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
838 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
839 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
840 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
841 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
842 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
843 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
844 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
845 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
846 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
847 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
848 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
849 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
850 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
851 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
852 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
853 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
854 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
855 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
856 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
857 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
858 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
859 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
860 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
861 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
862 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
863 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
864 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
865 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
866 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
867 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
868 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
869 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
870 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
871 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
872 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
873 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
874 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
875 {"boot-image", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
876 {"com.apple.System.fp-state", kOFVariableTypeData
, kOFVariablePermKernelOnly
, -1},
878 {"backlight-level", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
879 {"com.apple.System.sep.art", kOFVariableTypeData
, kOFVariablePermKernelOnly
, -1},
880 {"com.apple.System.boot-nonce", kOFVariableTypeString
, kOFVariablePermKernelOnly
, -1},
881 {"darkboot", kOFVariableTypeBoolean
, kOFVariablePermUserWrite
, -1},
882 {"acc-mb-ld-lifetime", kOFVariableTypeNumber
, kOFVariablePermKernelOnly
, -1},
883 {"acc-cm-override-charger-count", kOFVariableTypeNumber
, kOFVariablePermKernelOnly
, -1},
884 {"acc-cm-override-count", kOFVariableTypeNumber
, kOFVariablePermKernelOnly
, -1},
885 {"enter-tdm-mode", kOFVariableTypeBoolean
, kOFVariablePermUserWrite
, -1},
887 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
890 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
892 const OFVariable
*ofVar
;
894 ofVar
= gOFVariables
;
896 if ((ofVar
->variableName
== 0) ||
897 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
901 return ofVar
->variableType
;
904 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
906 const OFVariable
*ofVar
;
908 ofVar
= gOFVariables
;
910 if ((ofVar
->variableName
== 0) ||
911 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
915 return ofVar
->variablePerm
;
918 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
919 UInt32
*propType
, UInt32
*propOffset
)
921 const OFVariable
*ofVar
;
923 ofVar
= gOFVariables
;
925 if (ofVar
->variableName
== 0) return false;
927 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
932 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
933 *propType
= ofVar
->variableType
;
936 case kOFVariableTypeBoolean
:
937 *propOffset
= 1 << (31 - variableNumber
);
940 case kOFVariableTypeNumber
:
941 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
944 case kOFVariableTypeString
:
945 *propOffset
= variableNumber
- kOWVariableOffsetString
;
952 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
953 UInt8
*propData
, UInt32 propDataLength
,
954 const OSSymbol
**propSymbol
,
955 OSObject
**propObject
)
958 const OSSymbol
*tmpSymbol
;
963 // Create the symbol.
964 propName
[propNameLength
] = '\0';
965 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
966 propName
[propNameLength
] = '=';
967 if (tmpSymbol
== 0) {
971 propType
= getOFVariableType(tmpSymbol
);
973 // Create the object.
976 case kOFVariableTypeBoolean
:
977 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
978 tmpObject
= kOSBooleanTrue
;
979 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
980 tmpObject
= kOSBooleanFalse
;
984 case kOFVariableTypeNumber
:
985 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
986 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
989 case kOFVariableTypeString
:
990 tmpString
= OSString::withCString((const char *)propData
);
991 if (tmpString
!= 0) tmpObject
= tmpString
;
994 case kOFVariableTypeData
:
995 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
999 if (tmpObject
== 0) {
1000 tmpSymbol
->release();
1004 *propSymbol
= tmpSymbol
;
1005 *propObject
= tmpObject
;
1010 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
1011 const OSSymbol
*propSymbol
, OSObject
*propObject
)
1013 const UInt8
*propName
;
1014 UInt32 propNameLength
, propDataLength
, remaining
;
1015 UInt32 propType
, tmpValue
;
1016 OSBoolean
*tmpBoolean
= 0;
1017 OSNumber
*tmpNumber
= 0;
1018 OSString
*tmpString
= 0;
1019 OSData
*tmpData
= 0;
1021 propName
= (const UInt8
*)propSymbol
->getCStringNoCopy();
1022 propNameLength
= propSymbol
->getLength();
1023 propType
= getOFVariableType(propSymbol
);
1025 // Get the size of the data.
1026 propDataLength
= 0xFFFFFFFF;
1028 case kOFVariableTypeBoolean
:
1029 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
1030 if (tmpBoolean
!= 0) propDataLength
= 5;
1033 case kOFVariableTypeNumber
:
1034 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
1035 if (tmpNumber
!= 0) propDataLength
= 10;
1038 case kOFVariableTypeString
:
1039 tmpString
= OSDynamicCast(OSString
, propObject
);
1040 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
1043 case kOFVariableTypeData
:
1044 tmpData
= OSDynamicCast(OSData
, propObject
);
1046 tmpData
= escapeDataToData(tmpData
);
1047 propDataLength
= tmpData
->getLength();
1052 // Make sure the propertySize is known and will fit.
1053 if (propDataLength
== 0xFFFFFFFF) return false;
1054 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
1056 // Copy the property name equal sign.
1057 buffer
+= snprintf((char *)buffer
, *length
, "%s=", propName
);
1058 remaining
= *length
- propNameLength
- 1;
1061 case kOFVariableTypeBoolean
:
1062 if (tmpBoolean
->getValue()) {
1063 strlcpy((char *)buffer
, "true", remaining
);
1065 strlcpy((char *)buffer
, "false", remaining
);
1069 case kOFVariableTypeNumber
:
1070 tmpValue
= tmpNumber
->unsigned32BitValue();
1071 if (tmpValue
== 0xFFFFFFFF) {
1072 strlcpy((char *)buffer
, "-1", remaining
);
1073 } else if (tmpValue
< 1000) {
1074 snprintf((char *)buffer
, remaining
, "%d", (uint32_t)tmpValue
);
1076 snprintf((char *)buffer
, remaining
, "0x%x", (uint32_t)tmpValue
);
1080 case kOFVariableTypeString
:
1081 strlcpy((char *)buffer
, tmpString
->getCStringNoCopy(), remaining
);
1084 case kOFVariableTypeData
:
1085 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
1090 propDataLength
= strlen((const char *)buffer
);
1092 *length
= propNameLength
+ propDataLength
+ 2;
1098 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
1100 UInt32 cnt
, checksum
= 0;
1101 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1103 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1104 checksum
+= tmpBuffer
[cnt
];
1106 return checksum
% 0x0000FFFF;
1109 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
1111 UInt32 cnt
, checksum
, sum
= 0;
1112 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1114 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1115 sum
+= tmpBuffer
[cnt
];
1117 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
1118 if (checksum
== 0x10000) checksum
--;
1119 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
1121 return checksum
== 0;
1124 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
1126 bool wasBootArgs
, bootr
= false;
1128 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
1129 const UInt8
*bootCommandData
, *bootArgsData
;
1131 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
1133 tmpString
= OSDynamicCast(OSString
, value
);
1134 if (tmpString
== 0) return;
1136 if (key
->isEqualTo("boot-command")) {
1137 wasBootArgs
= false;
1138 bootCommand
= tmpString
;
1139 } else if (key
->isEqualTo("boot-args")) {
1141 bootArgs
= tmpString
;
1142 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1143 if (bootCommand
== 0) return;
1146 bootCommandData
= (const UInt8
*)bootCommand
->getCStringNoCopy();
1147 bootCommandDataLength
= bootCommand
->getLength();
1149 if (bootCommandData
== 0) return;
1151 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1152 if ((bootCommandData
[cnt
] == 'b') &&
1153 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1155 while (bootCommandData
[cnt
] == ' ') cnt
++;
1161 _ofDict
->removeObject("boot-args");
1166 bootArgsData
= (const UInt8
*)bootArgs
->getCStringNoCopy();
1167 bootArgsDataLength
= bootArgs
->getLength();
1168 if (bootArgsData
== 0) return;
1170 tmpDataLength
= cnt
+ bootArgsDataLength
;
1171 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1172 if (tmpData
== 0) return;
1174 cnt
-= strlcpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1175 strlcat((char *)tmpData
, (const char *)bootArgsData
, cnt
);
1177 bootCommand
= OSString::withCString((const char *)tmpData
);
1178 if (bootCommand
!= 0) {
1179 _ofDict
->setObject("boot-command", bootCommand
);
1180 bootCommand
->release();
1183 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1185 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1186 if (bootArgs
!= 0) {
1187 _ofDict
->setObject("boot-args", bootArgs
);
1188 bootArgs
->release();
1193 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1198 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1199 const OSSymbol
**name
,
1202 return kIOReturnUnsupported
;
1206 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1207 const OSSymbol
*name
,
1210 return kIOReturnUnsupported
;
1214 OSData
*IODTNVRAM::unescapeBytesToData(const UInt8
*bytes
, UInt32 length
)
1217 UInt32 totalLength
= 0;
1222 // Calculate the actual length of the data.
1225 for (cnt
= 0; cnt
< length
;) {
1226 byte
= bytes
[cnt
++];
1228 byte
= bytes
[cnt
++];
1236 totalLength
+= cnt2
;
1240 // Create an empty OSData of the correct size.
1241 data
= OSData::withCapacity(totalLength
);
1243 for (cnt
= 0; cnt
< length
;) {
1244 byte
= bytes
[cnt
++];
1246 byte
= bytes
[cnt
++];
1248 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1251 data
->appendByte(byte
, cnt2
);
1259 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1262 const UInt8
* startPtr
;
1263 const UInt8
* endPtr
;
1264 const UInt8
* wherePtr
;
1268 wherePtr
= (const UInt8
*) value
->getBytesNoCopy();
1269 endPtr
= wherePtr
+ value
->getLength();
1271 result
= OSData::withCapacity(endPtr
- wherePtr
);
1275 while (wherePtr
< endPtr
) {
1276 startPtr
= wherePtr
;
1278 if ((byte
== 0x00) || (byte
== 0xFF)) {
1280 ((wherePtr
- startPtr
) < 0x80) && (wherePtr
< endPtr
) && (byte
== *wherePtr
);
1282 ok
&= result
->appendByte(0xff, 1);
1283 byte
= (byte
& 0x80) | (wherePtr
- startPtr
);
1285 ok
&= result
->appendByte(byte
, 1);
1287 ok
&= result
->appendByte(0, 1);
1297 static bool IsApplePropertyName(const char * propName
)
1300 while ((c
= *propName
++)) {
1301 if ((c
>= 'A') && (c
<= 'Z'))
1308 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1309 const OSSymbol
**name
,
1312 IOReturn err
= kIOReturnNoResources
;
1314 const UInt8
*startPtr
;
1315 const UInt8
*endPtr
;
1316 const UInt8
*wherePtr
;
1317 const UInt8
*nvPath
= 0;
1318 const char *nvName
= 0;
1319 const char *resultName
= 0;
1320 const UInt8
*resultValue
= 0;
1321 UInt32 resultValueLen
= 0;
1324 if (_ofDict
== 0) return err
;
1326 IOLockLock(_ofLock
);
1327 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1328 IOLockUnlock(_ofLock
);
1330 if (data
== 0) return err
;
1332 startPtr
= (const UInt8
*) data
->getBytesNoCopy();
1333 endPtr
= startPtr
+ data
->getLength();
1335 wherePtr
= startPtr
;
1336 while (wherePtr
< endPtr
) {
1337 byte
= *(wherePtr
++);
1343 else if (nvName
== 0)
1344 nvName
= (const char *) startPtr
;
1346 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1348 compareEntry
->release();
1349 if (entry
== compareEntry
) {
1350 bool appleProp
= IsApplePropertyName(nvName
);
1351 if (!appleProp
|| !resultName
) {
1352 resultName
= nvName
;
1353 resultValue
= startPtr
;
1354 resultValueLen
= wherePtr
- startPtr
- 1;
1362 startPtr
= wherePtr
;
1365 *name
= OSSymbol::withCString(resultName
);
1366 *value
= unescapeBytesToData(resultValue
, resultValueLen
);
1367 if ((*name
!= 0) && (*value
!= 0))
1368 err
= kIOReturnSuccess
;
1370 err
= kIOReturnNoMemory
;
1375 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1376 const OSSymbol
*propName
,
1379 OSData
*oldData
, *escapedData
;
1381 const UInt8
*startPtr
;
1382 const UInt8
*propStart
;
1383 const UInt8
*endPtr
;
1384 const UInt8
*wherePtr
;
1385 const UInt8
*nvPath
= 0;
1386 const char *nvName
= 0;
1391 bool settingAppleProp
;
1393 if (_ofDict
== 0) return kIOReturnNoResources
;
1395 settingAppleProp
= IsApplePropertyName(propName
->getCStringNoCopy());
1397 // copy over existing properties for other entries
1399 IOLockLock(_ofLock
);
1401 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1404 startPtr
= (const UInt8
*) oldData
->getBytesNoCopy();
1405 endPtr
= startPtr
+ oldData
->getLength();
1407 propStart
= startPtr
;
1408 wherePtr
= startPtr
;
1409 while (wherePtr
< endPtr
) {
1410 byte
= *(wherePtr
++);
1415 else if (nvName
== 0)
1416 nvName
= (const char *) startPtr
;
1418 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1420 compareEntry
->release();
1421 if (entry
== compareEntry
) {
1422 if ((settingAppleProp
&& propName
->isEqualTo(nvName
))
1423 || (!settingAppleProp
&& !IsApplePropertyName(nvName
))) {
1424 // delete old property (nvPath -> wherePtr)
1425 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1427 ok
&= data
->appendBytes(wherePtr
, endPtr
- wherePtr
);
1435 startPtr
= wherePtr
;
1439 // make the new property
1443 data
= OSData::withData(oldData
);
1445 data
= OSData::withCapacity(16);
1446 if (!data
) ok
= false;
1449 if (ok
&& value
&& value
->getLength()) do {
1450 // get entries in path
1451 OSArray
*array
= OSArray::withCapacity(5);
1457 array
->setObject(entry
);
1458 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1461 for (int i
= array
->getCount() - 3;
1462 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1465 name
= entry
->getName(gIODTPlane
);
1466 comp
= entry
->getLocation(gIODTPlane
);
1467 if (comp
) ok
&= data
->appendBytes("/@", 2);
1469 if (!name
) continue;
1470 ok
&= data
->appendByte('/', 1);
1473 ok
&= data
->appendBytes(comp
, strlen(comp
));
1475 ok
&= data
->appendByte(0, 1);
1479 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1481 // append escaped data
1482 escapedData
= escapeDataToData(value
);
1483 ok
&= (escapedData
!= 0);
1484 if (ok
) ok
&= data
->appendBytes(escapedData
);
1490 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1493 if (data
) data
->release();
1496 if (syncVariables() != kIOReturnSuccess
) {
1498 _ofDict
->setObject(_registryPropertiesKey
, oldData
);
1501 _ofDict
->removeObject(_registryPropertiesKey
);
1503 (void) syncVariables();
1512 IOLockUnlock(_ofLock
);
1514 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;
1517 bool IODTNVRAM::safeToSync(void)
1523 // delta interval went by
1524 clock_get_uptime(&delta
);
1526 // Figure it in seconds.
1527 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1528 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1530 if ((delta_secs
> (_lastDeviceSync
+ MIN_SYNC_NOW_INTERVAL
)) || _freshInterval
)
1532 _lastDeviceSync
= delta_secs
;
1533 _freshInterval
= FALSE
;