2 * Copyright (c) 1998-2006 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>
34 #include <kern/debug.h>
35 #include <pexpert/pexpert.h>
37 #define super IOService
39 #define kIONVRAMPrivilege kIOClientPrivilegeAdministrator
40 //#define kIONVRAMPrivilege kIOClientPrivilegeLocalUser
42 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
);
44 bool IODTNVRAM::init(IORegistryEntry
*old
, const IORegistryPlane
*plane
)
48 if (!super::init(old
, plane
)) return false;
50 dict
= OSDictionary::withCapacity(1);
51 if (dict
== 0) return false;
52 setPropertyTable(dict
);
54 _nvramImage
= IONew(UInt8
, kIODTNVRAMImageSize
);
55 if (_nvramImage
== 0) return false;
57 _nvramPartitionOffsets
= OSDictionary::withCapacity(1);
58 if (_nvramPartitionOffsets
== 0) return false;
60 _nvramPartitionLengths
= OSDictionary::withCapacity(1);
61 if (_nvramPartitionLengths
== 0) return false;
63 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
64 if (_registryPropertiesKey
== 0) return false;
69 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
72 UInt32 partitionOffset
, partitionLength
;
73 UInt32 freePartitionOffset
, freePartitionSize
;
74 UInt32 currentLength
, currentOffset
= 0;
75 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
77 if (_nvramController
!= 0) return;
79 _nvramController
= nvram
;
81 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
83 // Find the offsets for the OF, XPRAM, NameRegistry and PanicInfo partitions.
84 _ofPartitionOffset
= 0xFFFFFFFF;
85 _xpramPartitionOffset
= 0xFFFFFFFF;
86 _nrPartitionOffset
= 0xFFFFFFFF;
87 _piPartitionOffset
= 0xFFFFFFFF;
88 freePartitionOffset
= 0xFFFFFFFF;
89 freePartitionSize
= 0;
90 if (getPlatform()->getBootROMType()) {
91 // Look through the partitions to find the OF, MacOS partitions.
92 while (currentOffset
< kIODTNVRAMImageSize
) {
93 currentLength
= ((UInt16
*)(_nvramImage
+ currentOffset
))[1] * 16;
95 partitionOffset
= currentOffset
+ 16;
96 partitionLength
= currentLength
- 16;
98 if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
99 kIODTNVRAMOFPartitionName
, 12) == 0) {
100 _ofPartitionOffset
= partitionOffset
;
101 _ofPartitionSize
= partitionLength
;
102 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
103 kIODTNVRAMXPRAMPartitionName
, 12) == 0) {
104 _xpramPartitionOffset
= partitionOffset
;
105 _xpramPartitionSize
= kIODTNVRAMXPRAMSize
;
106 _nrPartitionOffset
= _xpramPartitionOffset
+ _xpramPartitionSize
;
107 _nrPartitionSize
= partitionLength
- _xpramPartitionSize
;
108 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
109 kIODTNVRAMPanicInfoPartitonName
, 12) == 0) {
110 _piPartitionOffset
= partitionOffset
;
111 _piPartitionSize
= partitionLength
;
112 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
113 kIODTNVRAMFreePartitionName
, 12) == 0) {
114 freePartitionOffset
= currentOffset
;
115 freePartitionSize
= currentLength
;
117 // Construct the partition ID from the signature and name.
118 snprintf(partitionID
, sizeof(partitionID
), "0x%02x,",
119 *(UInt8
*)(_nvramImage
+ currentOffset
));
120 strncpy(partitionID
+ 5,
121 (const char *)(_nvramImage
+ currentOffset
+ 4), 12);
122 partitionID
[17] = '\0';
124 partitionOffsetNumber
= OSNumber::withNumber(partitionOffset
, 32);
125 partitionLengthNumber
= OSNumber::withNumber(partitionLength
, 32);
127 // Save the partition offset and length
128 _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
);
129 _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
);
131 partitionOffsetNumber
->release();
132 partitionLengthNumber
->release();
134 currentOffset
+= currentLength
;
137 // Use the fixed address for old world machines.
138 _ofPartitionOffset
= 0x1800;
139 _ofPartitionSize
= 0x0800;
140 _xpramPartitionOffset
= 0x1300;
141 _xpramPartitionSize
= 0x0100;
142 _nrPartitionOffset
= 0x1400;
143 _nrPartitionSize
= 0x0400;
146 if (_ofPartitionOffset
!= 0xFFFFFFFF)
147 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
148 if (_xpramPartitionOffset
!= 0xFFFFFFFF)
149 _xpramImage
= _nvramImage
+ _xpramPartitionOffset
;
150 if (_nrPartitionOffset
!= 0xFFFFFFFF)
151 _nrImage
= _nvramImage
+ _nrPartitionOffset
;
153 if (_piPartitionOffset
== 0xFFFFFFFF) {
154 if (freePartitionSize
> 0x20) {
155 // Set the signature to 0xa1.
156 _nvramImage
[freePartitionOffset
] = 0xa1;
157 // Set the checksum to 0.
158 _nvramImage
[freePartitionOffset
+ 1] = 0;
159 // Set the name for the Panic Info partition.
160 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
161 kIODTNVRAMPanicInfoPartitonName
, 12);
163 // Calculate the partition offset and size.
164 _piPartitionOffset
= freePartitionOffset
+ 0x10;
165 _piPartitionSize
= 0x800;
166 if (_piPartitionSize
+ 0x20 > freePartitionSize
)
167 _piPartitionSize
= freePartitionSize
- 0x20;
169 _piImage
= _nvramImage
+ _piPartitionOffset
;
171 // Zero the new partition.
172 bzero(_piImage
, _piPartitionSize
);
174 // Set the partition size.
175 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
176 (_piPartitionSize
/ 0x10) + 1;
178 // Set the partition checksum.
179 _nvramImage
[freePartitionOffset
+ 1] =
180 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
182 // Calculate the free partition offset and size.
183 freePartitionOffset
+= _piPartitionSize
+ 0x10;
184 freePartitionSize
-= _piPartitionSize
+ 0x10;
186 // Set the signature to 0x7f.
187 _nvramImage
[freePartitionOffset
] = 0x7f;
188 // Set the checksum to 0.
189 _nvramImage
[freePartitionOffset
+ 1] = 0;
190 // Set the name for the free partition.
191 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
192 kIODTNVRAMFreePartitionName
, 12);
193 // Set the partition size.
194 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
195 freePartitionSize
/ 0x10;
196 // Set the partition checksum.
197 _nvramImage
[freePartitionOffset
+ 1] =
198 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
200 // Set the nvram image as dirty.
201 _nvramImageDirty
= true;
204 _piImage
= _nvramImage
+ _piPartitionOffset
;
208 _freshInterval
= TRUE
; // we will allow sync() even before the first 15 minutes have passed.
213 void IODTNVRAM::sync(void)
215 if (!_nvramImageDirty
&& !_ofImageDirty
) return;
217 // Don't try to sync OF Variables if the system has already paniced.
218 if (!_systemPaniced
) syncOFVariables();
220 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
221 _nvramController
->sync();
223 _nvramImageDirty
= false;
226 bool IODTNVRAM::serializeProperties(OSSerialize
*s
) const
228 bool result
, hasPrivilege
;
231 OSDictionary
*dict
= 0, *tmpDict
= 0;
232 OSCollectionIterator
*iter
= 0;
234 // Verify permissions.
235 hasPrivilege
= (kIOReturnSuccess
== IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
));
237 tmpDict
= OSDictionary::withCapacity(1);
238 if (tmpDict
== 0) return false;
241 /* No nvram. Return an empty dictionary. */
244 /* Copy properties with client privilege. */
245 iter
= OSCollectionIterator::withCollection(_ofDict
);
246 if (iter
== 0) return false;
249 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
252 variablePerm
= getOFVariablePerm(key
);
253 if ((hasPrivilege
|| (variablePerm
!= kOFVariablePermRootOnly
)) &&
254 ( ! (variablePerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) )) {
255 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
261 result
= dict
->serialize(s
);
263 if (tmpDict
!= 0) tmpDict
->release();
264 if (iter
!= 0) iter
->release();
269 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
274 if (_ofDict
== 0) return 0;
276 // Verify permissions.
277 variablePerm
= getOFVariablePerm(aKey
);
278 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
279 if (result
!= kIOReturnSuccess
) {
280 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
282 if (variablePerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return 0;
284 return _ofDict
->getObject(aKey
);
287 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
289 const OSSymbol
*keySymbol
;
290 OSObject
*theObject
= 0;
292 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
293 if (keySymbol
!= 0) {
294 theObject
= getProperty(keySymbol
);
295 keySymbol
->release();
301 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
304 UInt32 propType
, propPerm
;
306 OSObject
*propObject
= 0;
308 if (_ofDict
== 0) return false;
310 // Verify permissions.
311 propPerm
= getOFVariablePerm(aKey
);
312 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
313 if (result
!= kIOReturnSuccess
) {
314 if (propPerm
!= kOFVariablePermUserWrite
) return false;
316 if (propPerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return 0;
318 // Don't allow creation of new properties on old world machines.
319 if (getPlatform()->getBootROMType() == 0) {
320 if (_ofDict
->getObject(aKey
) == 0) return false;
323 // Don't allow change of 'aapl,panic-info'.
324 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return false;
326 // Make sure the object is of the correct type.
327 propType
= getOFVariableType(aKey
);
329 case kOFVariableTypeBoolean
:
330 propObject
= OSDynamicCast(OSBoolean
, anObject
);
333 case kOFVariableTypeNumber
:
334 propObject
= OSDynamicCast(OSNumber
, anObject
);
337 case kOFVariableTypeString
:
338 propObject
= OSDynamicCast(OSString
, anObject
);
341 case kOFVariableTypeData
:
342 propObject
= OSDynamicCast(OSData
, anObject
);
343 if (propObject
== 0) {
344 tmpString
= OSDynamicCast(OSString
, anObject
);
345 if (tmpString
!= 0) {
346 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
347 tmpString
->getLength());
353 if (propObject
== 0) return false;
355 result
= _ofDict
->setObject(aKey
, propObject
);
358 if (getPlatform()->getBootROMType() == 0) {
359 updateOWBootArgs(aKey
, propObject
);
362 _ofImageDirty
= true;
368 void IODTNVRAM::removeProperty(const OSSymbol
*aKey
)
373 if (_ofDict
== 0) return;
375 // Verify permissions.
376 propPerm
= getOFVariablePerm(aKey
);
377 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
378 if (result
!= kIOReturnSuccess
) {
379 if (propPerm
!= kOFVariablePermUserWrite
) return;
381 if (propPerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return;
383 // Don't allow removal of properties on old world machines.
384 if (getPlatform()->getBootROMType() == 0) return;
386 // Don't allow change of 'aapl,panic-info'.
387 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return;
389 // If the object exists, remove it from the dictionary.
390 result
= _ofDict
->getObject(aKey
) != 0;
392 _ofDict
->removeObject(aKey
);
394 _ofImageDirty
= true;
398 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
403 const OSString
*tmpStr
;
405 OSCollectionIterator
*iter
;
407 dict
= OSDynamicCast(OSDictionary
, properties
);
408 if (dict
== 0) return kIOReturnBadArgument
;
410 iter
= OSCollectionIterator::withCollection(dict
);
411 if (iter
== 0) return kIOReturnBadArgument
;
414 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
417 object
= dict
->getObject(key
);
418 if (object
== 0) continue;
420 if (key
->isEqualTo(kIONVRAMDeletePropertyKey
)) {
421 tmpStr
= OSDynamicCast(OSString
, object
);
423 key
= OSSymbol::withString(tmpStr
);
430 } else if(key
->isEqualTo(kIONVRAMSyncNowPropertyKey
)) {
431 tmpStr
= OSDynamicCast(OSString
, object
);
434 result
= true; // We are not going to gaurantee sync, this is best effort
444 result
= setProperty(key
, object
);
451 if (result
) return kIOReturnSuccess
;
452 else return kIOReturnError
;
455 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
458 if (_xpramImage
== 0) return kIOReturnUnsupported
;
460 if ((buffer
== 0) || (length
== 0) ||
461 (offset
+ length
> kIODTNVRAMXPRAMSize
))
462 return kIOReturnBadArgument
;
464 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
466 return kIOReturnSuccess
;
469 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
472 if (_xpramImage
== 0) return kIOReturnUnsupported
;
474 if ((buffer
== 0) || (length
== 0) ||
475 (offset
+ length
> kIODTNVRAMXPRAMSize
))
476 return kIOReturnBadArgument
;
478 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
480 _nvramImageDirty
= true;
482 return kIOReturnSuccess
;
485 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
486 const OSSymbol
**name
,
491 if (getPlatform()->getBootROMType())
492 err
= readNVRAMPropertyType1(entry
, name
, value
);
494 err
= readNVRAMPropertyType0(entry
, name
, value
);
499 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
500 const OSSymbol
*name
,
505 if (getPlatform()->getBootROMType())
506 err
= writeNVRAMPropertyType1(entry
, name
, value
);
508 err
= writeNVRAMPropertyType0(entry
, name
, value
);
513 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
515 return _nvramPartitionLengths
;
518 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
519 IOByteCount offset
, UInt8
*buffer
,
522 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
523 UInt32 partitionOffset
, partitionLength
;
525 partitionOffsetNumber
=
526 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
527 partitionLengthNumber
=
528 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
530 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
531 return kIOReturnNotFound
;
533 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
534 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
536 if ((buffer
== 0) || (length
== 0) ||
537 (offset
+ length
> partitionLength
))
538 return kIOReturnBadArgument
;
540 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
542 return kIOReturnSuccess
;
545 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
546 IOByteCount offset
, UInt8
*buffer
,
549 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
550 UInt32 partitionOffset
, partitionLength
;
552 partitionOffsetNumber
=
553 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
554 partitionLengthNumber
=
555 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
557 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
558 return kIOReturnNotFound
;
560 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
561 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
563 if ((buffer
== 0) || (length
== 0) ||
564 (offset
+ length
> partitionLength
))
565 return kIOReturnBadArgument
;
567 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
569 _nvramImageDirty
= true;
571 return kIOReturnSuccess
;
574 IOByteCount
IODTNVRAM::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
576 if ((_piImage
== 0) || (length
<= 0)) return 0;
578 if (length
> (_piPartitionSize
- 4))
579 length
= _piPartitionSize
- 4;
581 // Save the Panic Info.
582 bcopy(buffer
, _piImage
+ 4, length
);
584 // Save the Panic Info length.
585 *(UInt32
*)_piImage
= length
;
587 _nvramImageDirty
= true;
589 * This prevents OF variables from being committed if the system has panicked
591 _systemPaniced
= true;
592 /* The call to sync() forces the NVRAM controller to write the panic info
593 * partition to NVRAM.
602 UInt8
IODTNVRAM::calculatePartitionChecksum(UInt8
*partitionHeader
)
604 UInt8 cnt
, isum
, csum
= 0;
606 for (cnt
= 0; cnt
< 0x10; cnt
++) {
607 isum
= csum
+ partitionHeader
[cnt
];
608 if (isum
< csum
) isum
++;
615 struct OWVariablesHeader
{
630 typedef struct OWVariablesHeader OWVariablesHeader
;
632 IOReturn
IODTNVRAM::initOFVariables(void)
634 UInt32 cnt
, propOffset
, propType
;
635 UInt8
*propName
, *propData
;
636 UInt32 propNameLength
, propDataLength
;
637 const OSSymbol
*propSymbol
;
638 OSObject
*propObject
;
639 OWVariablesHeader
*owHeader
;
641 if (_ofImage
== 0) return kIOReturnNotReady
;
643 _ofDict
= OSDictionary::withCapacity(1);
644 if (_ofDict
== 0) return kIOReturnNoMemory
;
646 if (getPlatform()->getBootROMType()) {
648 while (cnt
< _ofPartitionSize
) {
649 // Break if there is no name.
650 if (_ofImage
[cnt
] == '\0') break;
652 // Find the length of the name.
653 propName
= _ofImage
+ cnt
;
654 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
656 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
659 // Break if the name goes past the end of the partition.
660 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
661 cnt
+= propNameLength
+ 1;
663 propData
= _ofImage
+ cnt
;
664 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
666 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
669 // Break if the data goes past the end of the partition.
670 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
671 cnt
+= propDataLength
+ 1;
673 if (convertPropToObject(propName
, propNameLength
,
674 propData
, propDataLength
,
675 &propSymbol
, &propObject
)) {
676 _ofDict
->setObject(propSymbol
, propObject
);
677 propSymbol
->release();
678 propObject
->release();
682 // Create the boot-args property if it is not in the dictionary.
683 if (_ofDict
->getObject("boot-args") == 0) {
684 propObject
= OSString::withCStringNoCopy("");
685 if (propObject
!= 0) {
686 _ofDict
->setObject("boot-args", propObject
);
687 propObject
->release();
691 // Create the 'aapl,panic-info' property if needed.
693 propDataLength
= *(UInt32
*)_piImage
;
694 if ((propDataLength
!= 0) && (propDataLength
<= (_piPartitionSize
- 4))) {
695 propObject
= OSData::withBytes(_piImage
+ 4, propDataLength
);
696 _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
);
697 propObject
->release();
699 // Clear the length from _piImage and mark dirty.
700 *(UInt32
*)_piImage
= 0;
701 _nvramImageDirty
= true;
705 owHeader
= (OWVariablesHeader
*)_ofImage
;
706 if (!validateOWChecksum(_ofImage
)) {
709 return kIOReturnBadMedia
;
714 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
718 case kOFVariableTypeBoolean
:
719 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
722 case kOFVariableTypeNumber
:
723 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
726 case kOFVariableTypeString
:
727 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
729 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
730 propName
= IONew(UInt8
, propDataLength
+ 1);
732 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
733 propName
[propDataLength
] = '\0';
734 propObject
= OSString::withCString((const char *)propName
);
735 IODelete(propName
, UInt8
, propDataLength
+ 1);
740 if (propObject
== 0) break;
742 _ofDict
->setObject(propSymbol
, propObject
);
743 propSymbol
->release();
744 propObject
->release();
747 // Create the boot-args property.
748 propSymbol
= OSSymbol::withCString("boot-command");
749 if (propSymbol
!= 0) {
750 propObject
= _ofDict
->getObject(propSymbol
);
751 if (propObject
!= 0) {
752 updateOWBootArgs(propSymbol
, propObject
);
754 propSymbol
->release();
758 return kIOReturnSuccess
;
761 IOReturn
IODTNVRAM::syncOFVariables(void)
764 UInt32 cnt
, length
, maxLength
;
765 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
766 UInt8
*buffer
, *tmpBuffer
;
767 const UInt8
*tmpData
;
768 const OSSymbol
*tmpSymbol
;
770 OSBoolean
*tmpBoolean
;
773 OSCollectionIterator
*iter
;
774 OWVariablesHeader
*owHeader
, *owHeaderOld
;
776 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
778 if (!_ofImageDirty
) return kIOReturnSuccess
;
780 if (getPlatform()->getBootROMType()) {
781 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
782 if (buffer
== 0) return kIOReturnNoMemory
;
783 bzero(buffer
, _ofPartitionSize
);
786 maxLength
= _ofPartitionSize
;
788 iter
= OSCollectionIterator::withCollection(_ofDict
);
789 if (iter
== 0) ok
= false;
792 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
793 if (tmpSymbol
== 0) break;
795 // Don't save 'aapl,panic-info'.
796 if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue;
798 tmpObject
= _ofDict
->getObject(tmpSymbol
);
801 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
810 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
813 IODelete(buffer
, UInt8
, _ofPartitionSize
);
815 if (!ok
) return kIOReturnBadArgument
;
817 buffer
= IONew(UInt8
, _ofPartitionSize
);
818 if (buffer
== 0) return kIOReturnNoMemory
;
819 bzero(buffer
, _ofPartitionSize
);
821 owHeader
= (OWVariablesHeader
*)buffer
;
822 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
824 owHeader
->owMagic
= owHeaderOld
->owMagic
;
825 owHeader
->owVersion
= owHeaderOld
->owVersion
;
826 owHeader
->owPages
= owHeaderOld
->owPages
;
828 curOffset
= _ofPartitionSize
;
833 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
836 tmpObject
= _ofDict
->getObject(tmpSymbol
);
839 case kOFVariableTypeBoolean
:
840 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
841 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
844 case kOFVariableTypeNumber
:
845 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
846 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
849 case kOFVariableTypeString
:
850 tmpString
= OSDynamicCast(OSString
, tmpObject
);
851 tmpData
= (const UInt8
*)tmpString
->getCStringNoCopy();
852 tmpDataLength
= tmpString
->getLength();
854 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
859 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
860 curOffset
-= tmpDataLength
;
861 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
862 if (tmpDataLength
!= 0)
863 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
869 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
870 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
871 owHeader
->owNext
= 0;
873 owHeader
->owChecksum
= 0;
874 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
876 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
879 IODelete(buffer
, UInt8
, _ofPartitionSize
);
881 if (!ok
) return kIOReturnBadArgument
;
884 _ofImageDirty
= false;
885 _nvramImageDirty
= true;
887 return kIOReturnSuccess
;
891 const char *variableName
;
894 SInt32 variableOffset
;
896 typedef struct OFVariable OFVariable
;
899 kOWVariableOffsetNumber
= 8,
900 kOWVariableOffsetString
= 17
903 OFVariable gOFVariables
[] = {
904 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
905 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
906 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
907 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
908 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
909 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
910 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
911 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
912 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
913 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
914 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
915 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
916 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
917 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
918 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
919 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
920 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
921 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
922 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
923 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
924 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
925 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
926 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
927 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
928 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
929 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
930 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
931 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
932 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
933 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
934 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
935 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
936 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
937 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
938 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
939 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
940 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
941 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
942 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
943 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
944 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
945 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
946 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
947 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
948 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
949 {"boot-image", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
950 {"com.apple.System.fp-state", kOFVariableTypeData
, kOFVariablePermKernelOnly
, -1},
952 {"backlight-level", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
954 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
957 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
961 ofVar
= gOFVariables
;
963 if ((ofVar
->variableName
== 0) ||
964 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
968 return ofVar
->variableType
;
971 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
975 ofVar
= gOFVariables
;
977 if ((ofVar
->variableName
== 0) ||
978 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
982 return ofVar
->variablePerm
;
985 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
986 UInt32
*propType
, UInt32
*propOffset
)
990 ofVar
= gOFVariables
;
992 if (ofVar
->variableName
== 0) return false;
994 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
999 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
1000 *propType
= ofVar
->variableType
;
1002 switch (*propType
) {
1003 case kOFVariableTypeBoolean
:
1004 *propOffset
= 1 << (31 - variableNumber
);
1007 case kOFVariableTypeNumber
:
1008 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
1011 case kOFVariableTypeString
:
1012 *propOffset
= variableNumber
- kOWVariableOffsetString
;
1019 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
1020 UInt8
*propData
, UInt32 propDataLength
,
1021 const OSSymbol
**propSymbol
,
1022 OSObject
**propObject
)
1025 const OSSymbol
*tmpSymbol
;
1026 OSObject
*tmpObject
;
1027 OSNumber
*tmpNumber
;
1028 OSString
*tmpString
;
1030 // Create the symbol.
1031 propName
[propNameLength
] = '\0';
1032 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
1033 propName
[propNameLength
] = '=';
1034 if (tmpSymbol
== 0) {
1038 propType
= getOFVariableType(tmpSymbol
);
1040 // Create the object.
1043 case kOFVariableTypeBoolean
:
1044 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
1045 tmpObject
= kOSBooleanTrue
;
1046 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
1047 tmpObject
= kOSBooleanFalse
;
1051 case kOFVariableTypeNumber
:
1052 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
1053 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
1056 case kOFVariableTypeString
:
1057 tmpString
= OSString::withCString((const char *)propData
);
1058 if (tmpString
!= 0) tmpObject
= tmpString
;
1061 case kOFVariableTypeData
:
1062 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
1066 if (tmpObject
== 0) {
1067 tmpSymbol
->release();
1071 *propSymbol
= tmpSymbol
;
1072 *propObject
= tmpObject
;
1077 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
1078 const OSSymbol
*propSymbol
, OSObject
*propObject
)
1080 const UInt8
*propName
;
1081 UInt32 propNameLength
, propDataLength
;
1082 UInt32 propType
, tmpValue
;
1083 OSBoolean
*tmpBoolean
= 0;
1084 OSNumber
*tmpNumber
= 0;
1085 OSString
*tmpString
= 0;
1086 OSData
*tmpData
= 0;
1088 propName
= (const UInt8
*)propSymbol
->getCStringNoCopy();
1089 propNameLength
= propSymbol
->getLength();
1090 propType
= getOFVariableType(propSymbol
);
1092 // Get the size of the data.
1093 propDataLength
= 0xFFFFFFFF;
1095 case kOFVariableTypeBoolean
:
1096 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
1097 if (tmpBoolean
!= 0) propDataLength
= 5;
1100 case kOFVariableTypeNumber
:
1101 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
1102 if (tmpNumber
!= 0) propDataLength
= 10;
1105 case kOFVariableTypeString
:
1106 tmpString
= OSDynamicCast(OSString
, propObject
);
1107 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
1110 case kOFVariableTypeData
:
1111 tmpData
= OSDynamicCast(OSData
, propObject
);
1113 tmpData
= escapeDataToData(tmpData
);
1114 propDataLength
= tmpData
->getLength();
1119 // Make sure the propertySize is known and will fit.
1120 if (propDataLength
== 0xFFFFFFFF) return false;
1121 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
1123 // Copy the property name equal sign.
1124 buffer
+= snprintf((char *)buffer
, *length
, "%s=", propName
);
1127 case kOFVariableTypeBoolean
:
1128 if (tmpBoolean
->getValue()) {
1129 strlcpy((char *)buffer
, "true", *length
- propNameLength
);
1131 strlcpy((char *)buffer
, "false", *length
- propNameLength
);
1135 case kOFVariableTypeNumber
:
1136 tmpValue
= tmpNumber
->unsigned32BitValue();
1137 if (tmpValue
== 0xFFFFFFFF) {
1138 strlcpy((char *)buffer
, "-1", *length
- propNameLength
);
1139 } else if (tmpValue
< 1000) {
1140 snprintf((char *)buffer
, *length
- propNameLength
, "%d", (uint32_t)tmpValue
);
1142 snprintf((char *)buffer
, *length
- propNameLength
, "0x%x", (uint32_t)tmpValue
);
1146 case kOFVariableTypeString
:
1147 strlcpy((char *)buffer
, tmpString
->getCStringNoCopy(), *length
- propNameLength
);
1150 case kOFVariableTypeData
:
1151 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
1156 propDataLength
= strlen((const char *)buffer
);
1158 *length
= propNameLength
+ propDataLength
+ 2;
1164 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
1166 UInt32 cnt
, checksum
= 0;
1167 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1169 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1170 checksum
+= tmpBuffer
[cnt
];
1172 return checksum
% 0x0000FFFF;
1175 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
1177 UInt32 cnt
, checksum
, sum
= 0;
1178 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1180 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1181 sum
+= tmpBuffer
[cnt
];
1183 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
1184 if (checksum
== 0x10000) checksum
--;
1185 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
1187 return checksum
== 0;
1190 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
1192 bool wasBootArgs
, bootr
= false;
1194 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
1195 const UInt8
*bootCommandData
, *bootArgsData
;
1197 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
1199 tmpString
= OSDynamicCast(OSString
, value
);
1200 if (tmpString
== 0) return;
1202 if (key
->isEqualTo("boot-command")) {
1203 wasBootArgs
= false;
1204 bootCommand
= tmpString
;
1205 } else if (key
->isEqualTo("boot-args")) {
1207 bootArgs
= tmpString
;
1208 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1209 if (bootCommand
== 0) return;
1212 bootCommandData
= (const UInt8
*)bootCommand
->getCStringNoCopy();
1213 bootCommandDataLength
= bootCommand
->getLength();
1215 if (bootCommandData
== 0) return;
1217 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1218 if ((bootCommandData
[cnt
] == 'b') &&
1219 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1221 while (bootCommandData
[cnt
] == ' ') cnt
++;
1227 _ofDict
->removeObject("boot-args");
1232 bootArgsData
= (const UInt8
*)bootArgs
->getCStringNoCopy();
1233 bootArgsDataLength
= bootArgs
->getLength();
1234 if (bootArgsData
== 0) return;
1236 tmpDataLength
= cnt
+ bootArgsDataLength
;
1237 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1238 if (tmpData
== 0) return;
1240 cnt
-= strlcpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1241 strlcat((char *)tmpData
, (const char *)bootArgsData
, cnt
);
1243 bootCommand
= OSString::withCString((const char *)tmpData
);
1244 if (bootCommand
!= 0) {
1245 _ofDict
->setObject("boot-command", bootCommand
);
1246 bootCommand
->release();
1249 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1251 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1252 if (bootArgs
!= 0) {
1253 _ofDict
->setObject("boot-args", bootArgs
);
1254 bootArgs
->release();
1260 // Private methods for Name Registry access.
1263 kMaxNVNameLength
= 4,
1264 kMaxNVDataLength
= 8
1267 struct NVRAMProperty
1269 IONVRAMDescriptor header
;
1271 UInt8 name
[ kMaxNVNameLength
];
1273 UInt8 data
[ kMaxNVDataLength
];
1276 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1281 nvEnd
= *((UInt16
*)_nrImage
);
1282 if(getPlatform()->getBootROMType()) {
1283 // on NewWorld, offset to partition start
1286 // on old world, absolute
1287 nvEnd
-= _nrPartitionOffset
;
1289 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1293 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1294 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1298 offset
+= sizeof(NVRAMProperty
);
1301 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1309 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1310 const OSSymbol
**name
,
1313 IONVRAMDescriptor hdr
;
1314 NVRAMProperty
*prop
;
1318 char nameBuf
[kMaxNVNameLength
+ 1];
1320 if (_nrImage
== 0) return kIOReturnUnsupported
;
1321 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1323 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1324 if (err
!= kIOReturnSuccess
) return err
;
1326 if (searchNVRAMProperty(&hdr
, &offset
)) {
1327 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1329 length
= prop
->nameLength
;
1330 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1331 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1332 nameBuf
[length
] = 0;
1333 *name
= OSSymbol::withCString(nameBuf
);
1335 length
= prop
->dataLength
;
1336 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1337 *value
= OSData::withBytes(prop
->data
, length
);
1339 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1340 else return kIOReturnNoMemory
;
1343 return kIOReturnNoResources
;
1346 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1347 const OSSymbol
*name
,
1350 IONVRAMDescriptor hdr
;
1351 NVRAMProperty
*prop
;
1352 IOByteCount nameLength
;
1353 IOByteCount dataLength
;
1359 if (_nrImage
== 0) return kIOReturnUnsupported
;
1360 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1362 nameLength
= name
->getLength();
1363 dataLength
= value
->getLength();
1364 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1365 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1367 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1368 if (err
!= kIOReturnSuccess
) return err
;
1370 exists
= searchNVRAMProperty(&hdr
, &offset
);
1371 if (offset
== 0) return kIOReturnNoMemory
;
1373 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1374 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1376 prop
->nameLength
= nameLength
;
1377 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1378 prop
->dataLength
= dataLength
;
1379 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1382 nvLength
= offset
+ sizeof(NVRAMProperty
);
1383 if (getPlatform()->getBootROMType())
1386 nvLength
+= _nrPartitionOffset
;
1387 *((UInt16
*)_nrImage
) = nvLength
;
1390 _nvramImageDirty
= true;
1395 OSData
*IODTNVRAM::unescapeBytesToData(const UInt8
*bytes
, UInt32 length
)
1398 UInt32 totalLength
= 0;
1403 // Calculate the actual length of the data.
1406 for (cnt
= 0; cnt
< length
;) {
1407 byte
= bytes
[cnt
++];
1409 byte
= bytes
[cnt
++];
1417 totalLength
+= cnt2
;
1421 // Create an empty OSData of the correct size.
1422 data
= OSData::withCapacity(totalLength
);
1424 for (cnt
= 0; cnt
< length
;) {
1425 byte
= bytes
[cnt
++];
1427 byte
= bytes
[cnt
++];
1429 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1432 data
->appendByte(byte
, cnt2
);
1440 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1443 const UInt8
* startPtr
;
1444 const UInt8
* endPtr
;
1445 const UInt8
* wherePtr
;
1449 wherePtr
= (const UInt8
*) value
->getBytesNoCopy();
1450 endPtr
= wherePtr
+ value
->getLength();
1452 result
= OSData::withCapacity(endPtr
- wherePtr
);
1456 while (wherePtr
< endPtr
) {
1457 startPtr
= wherePtr
;
1459 if ((byte
== 0x00) || (byte
== 0xFF)) {
1461 ((wherePtr
- startPtr
) < 0x80) && (wherePtr
< endPtr
) && (byte
== *wherePtr
);
1463 ok
&= result
->appendByte(0xff, 1);
1464 byte
= (byte
& 0x80) | (wherePtr
- startPtr
);
1466 ok
&= result
->appendByte(byte
, 1);
1468 ok
&= result
->appendByte(0, 1);
1478 static bool IsApplePropertyName(const char * propName
)
1481 while ((c
= *propName
++)) {
1482 if ((c
>= 'A') && (c
<= 'Z'))
1489 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1490 const OSSymbol
**name
,
1493 IOReturn err
= kIOReturnNoResources
;
1495 const UInt8
*startPtr
;
1496 const UInt8
*endPtr
;
1497 const UInt8
*wherePtr
;
1498 const UInt8
*nvPath
= 0;
1499 const char *nvName
= 0;
1500 const char *resultName
= 0;
1501 const UInt8
*resultValue
= 0;
1502 UInt32 resultValueLen
= 0;
1505 if (_ofDict
== 0) return err
;
1506 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1507 if (data
== 0) return err
;
1509 startPtr
= (const UInt8
*) data
->getBytesNoCopy();
1510 endPtr
= startPtr
+ data
->getLength();
1512 wherePtr
= startPtr
;
1513 while (wherePtr
< endPtr
) {
1514 byte
= *(wherePtr
++);
1520 else if (nvName
== 0)
1521 nvName
= (const char *) startPtr
;
1523 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1525 compareEntry
->release();
1526 if (entry
== compareEntry
) {
1527 bool appleProp
= IsApplePropertyName(nvName
);
1528 if (!appleProp
|| !resultName
) {
1529 resultName
= nvName
;
1530 resultValue
= startPtr
;
1531 resultValueLen
= wherePtr
- startPtr
- 1;
1539 startPtr
= wherePtr
;
1542 *name
= OSSymbol::withCString(resultName
);
1543 *value
= unescapeBytesToData(resultValue
, resultValueLen
);
1544 if ((*name
!= 0) && (*value
!= 0))
1545 err
= kIOReturnSuccess
;
1547 err
= kIOReturnNoMemory
;
1552 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1553 const OSSymbol
*propName
,
1558 const UInt8
*startPtr
;
1559 const UInt8
*propStart
;
1560 const UInt8
*endPtr
;
1561 const UInt8
*wherePtr
;
1562 const UInt8
*nvPath
= 0;
1563 const char *nvName
= 0;
1568 bool settingAppleProp
;
1570 if (_ofDict
== 0) return kIOReturnNoResources
;
1572 settingAppleProp
= IsApplePropertyName(propName
->getCStringNoCopy());
1574 // copy over existing properties for other entries
1576 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1578 startPtr
= (const UInt8
*) oldData
->getBytesNoCopy();
1579 endPtr
= startPtr
+ oldData
->getLength();
1581 propStart
= startPtr
;
1582 wherePtr
= startPtr
;
1583 while (wherePtr
< endPtr
) {
1584 byte
= *(wherePtr
++);
1589 else if (nvName
== 0)
1590 nvName
= (const char *) startPtr
;
1592 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1594 compareEntry
->release();
1595 if (entry
== compareEntry
) {
1596 if ((settingAppleProp
&& propName
->isEqualTo(nvName
))
1597 || (!settingAppleProp
&& !IsApplePropertyName(nvName
))) {
1598 // delete old property (nvPath -> wherePtr)
1599 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1601 ok
&= data
->appendBytes(wherePtr
, endPtr
- wherePtr
);
1609 startPtr
= wherePtr
;
1613 // make the new property
1617 data
= OSData::withData(oldData
);
1619 data
= OSData::withCapacity(16);
1621 return kIOReturnNoMemory
;
1624 if (value
&& value
->getLength()) {
1625 // get entries in path
1626 OSArray
*array
= OSArray::withCapacity(5);
1629 return kIOReturnNoMemory
;
1632 array
->setObject(entry
);
1633 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1636 for (int i
= array
->getCount() - 3;
1637 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1640 name
= entry
->getName(gIODTPlane
);
1641 comp
= entry
->getLocation(gIODTPlane
);
1642 if( comp
&& (0 == strncmp("pci", name
, sizeof("pci")))
1643 && (0 == strncmp("80000000", comp
, sizeof("80000000")))) {
1645 comp
= "/pci@80000000";
1648 ok
&= data
->appendBytes("/@", 2);
1652 ok
&= data
->appendByte('/', 1);
1656 ok
&= data
->appendBytes(comp
, strlen(comp
));
1658 ok
&= data
->appendByte(0, 1);
1662 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1664 // append escaped data
1665 oldData
= escapeDataToData(value
);
1666 ok
&= (oldData
!= 0);
1668 ok
&= data
->appendBytes(oldData
);
1671 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1673 _ofImageDirty
= true;
1677 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;
1680 bool IODTNVRAM::safeToSync(void)
1686 // delta interval went by
1687 clock_get_uptime(&delta
);
1689 // Figure it in seconds.
1690 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1691 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1693 if ((delta_secs
> (_lastDeviceSync
+ MIN_SYNC_NOW_INTERVAL
)) || _freshInterval
)
1695 _lastDeviceSync
= delta_secs
;
1696 _freshInterval
= FALSE
;