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>
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 snprintf(partitionID
, sizeof(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
224 bool result
, hasPrivilege
;
227 OSDictionary
*dict
= 0, *tmpDict
= 0;
228 OSCollectionIterator
*iter
= 0;
230 if (_ofDict
== 0) return false;
232 // Verify permissions.
233 hasPrivilege
= (kIOReturnSuccess
== IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
));
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 ((hasPrivilege
|| (variablePerm
!= kOFVariablePermRootOnly
)) &&
247 ( ! (variablePerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) )) {
248 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
253 result
= dict
->serialize(s
);
255 if (tmpDict
!= 0) tmpDict
->release();
256 if (iter
!= 0) iter
->release();
261 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
266 if (_ofDict
== 0) return 0;
268 // Verify permissions.
269 variablePerm
= getOFVariablePerm(aKey
);
270 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
271 if (result
!= kIOReturnSuccess
) {
272 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
274 if (variablePerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return 0;
276 return _ofDict
->getObject(aKey
);
279 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
281 const OSSymbol
*keySymbol
;
282 OSObject
*theObject
= 0;
284 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
285 if (keySymbol
!= 0) {
286 theObject
= getProperty(keySymbol
);
287 keySymbol
->release();
293 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
296 UInt32 propType
, propPerm
;
298 OSObject
*propObject
= 0;
300 if (_ofDict
== 0) return false;
302 // Verify permissions.
303 propPerm
= getOFVariablePerm(aKey
);
304 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
305 if (result
!= kIOReturnSuccess
) {
306 if (propPerm
!= kOFVariablePermUserWrite
) return false;
308 if (propPerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return 0;
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 propPerm
= getOFVariablePerm(aKey
);
369 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
370 if (result
!= kIOReturnSuccess
) {
371 if (propPerm
!= kOFVariablePermUserWrite
) return;
373 if (propPerm
== kOFVariablePermKernelOnly
&& current_task() != kernel_task
) return;
375 // Don't allow removal of properties on old world machines.
376 if (getPlatform()->getBootROMType() == 0) return;
378 // Don't allow change of 'aapl,panic-info'.
379 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return;
381 // If the object exists, remove it from the dictionary.
382 result
= _ofDict
->getObject(aKey
) != 0;
384 _ofDict
->removeObject(aKey
);
386 _ofImageDirty
= true;
390 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
395 const OSString
*tmpStr
;
397 OSCollectionIterator
*iter
;
399 dict
= OSDynamicCast(OSDictionary
, properties
);
400 if (dict
== 0) return kIOReturnBadArgument
;
402 iter
= OSCollectionIterator::withCollection(dict
);
403 if (iter
== 0) return kIOReturnBadArgument
;
406 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
409 object
= dict
->getObject(key
);
410 if (object
== 0) continue;
412 if (key
->isEqualTo(kIONVRAMDeletePropertyKey
)) {
413 tmpStr
= OSDynamicCast(OSString
, object
);
415 key
= OSSymbol::withString(tmpStr
);
423 result
= setProperty(key
, object
);
429 if (result
) return kIOReturnSuccess
;
430 else return kIOReturnError
;
433 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
436 if (_xpramImage
== 0) return kIOReturnUnsupported
;
438 if ((buffer
== 0) || (length
== 0) ||
439 (offset
+ length
> kIODTNVRAMXPRAMSize
))
440 return kIOReturnBadArgument
;
442 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
444 return kIOReturnSuccess
;
447 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
450 if (_xpramImage
== 0) return kIOReturnUnsupported
;
452 if ((buffer
== 0) || (length
== 0) ||
453 (offset
+ length
> kIODTNVRAMXPRAMSize
))
454 return kIOReturnBadArgument
;
456 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
458 _nvramImageDirty
= true;
460 return kIOReturnSuccess
;
463 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
464 const OSSymbol
**name
,
469 if (getPlatform()->getBootROMType())
470 err
= readNVRAMPropertyType1(entry
, name
, value
);
472 err
= readNVRAMPropertyType0(entry
, name
, value
);
477 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
478 const OSSymbol
*name
,
483 if (getPlatform()->getBootROMType())
484 err
= writeNVRAMPropertyType1(entry
, name
, value
);
486 err
= writeNVRAMPropertyType0(entry
, name
, value
);
491 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
493 return _nvramPartitionLengths
;
496 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
497 IOByteCount offset
, UInt8
*buffer
,
500 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
501 UInt32 partitionOffset
, partitionLength
;
503 partitionOffsetNumber
=
504 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
505 partitionLengthNumber
=
506 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
508 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
509 return kIOReturnNotFound
;
511 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
512 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
514 if ((buffer
== 0) || (length
== 0) ||
515 (offset
+ length
> partitionLength
))
516 return kIOReturnBadArgument
;
518 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
520 return kIOReturnSuccess
;
523 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
524 IOByteCount offset
, UInt8
*buffer
,
527 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
528 UInt32 partitionOffset
, partitionLength
;
530 partitionOffsetNumber
=
531 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
532 partitionLengthNumber
=
533 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
535 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
536 return kIOReturnNotFound
;
538 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
539 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
541 if ((buffer
== 0) || (length
== 0) ||
542 (offset
+ length
> partitionLength
))
543 return kIOReturnBadArgument
;
545 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
547 _nvramImageDirty
= true;
549 return kIOReturnSuccess
;
552 UInt32
IODTNVRAM::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
554 if ((_piImage
== 0) || (length
<= 0)) return 0;
556 if (length
> (_piPartitionSize
- 4))
557 length
= _piPartitionSize
- 4;
559 // Save the Panic Info.
560 bcopy(buffer
, _piImage
+ 4, length
);
562 // Save the Panic Info length.
563 *(UInt32
*)_piImage
= length
;
565 _nvramImageDirty
= true;
567 * This prevents OF variables from being committed if the system has panicked
569 _systemPaniced
= true;
570 /* The call to sync() forces the NVRAM controller to write the panic info
571 * partition to NVRAM.
580 UInt8
IODTNVRAM::calculatePartitionChecksum(UInt8
*partitionHeader
)
582 UInt8 cnt
, isum
, csum
= 0;
584 for (cnt
= 0; cnt
< 0x10; cnt
++) {
585 isum
= csum
+ partitionHeader
[cnt
];
586 if (isum
< csum
) isum
++;
593 struct OWVariablesHeader
{
608 typedef struct OWVariablesHeader OWVariablesHeader
;
610 IOReturn
IODTNVRAM::initOFVariables(void)
612 UInt32 cnt
, propOffset
, propType
;
613 UInt8
*propName
, *propData
;
614 UInt32 propNameLength
, propDataLength
;
615 const OSSymbol
*propSymbol
;
616 OSObject
*propObject
;
617 OWVariablesHeader
*owHeader
;
619 if (_ofImage
== 0) return kIOReturnNotReady
;
621 _ofDict
= OSDictionary::withCapacity(1);
622 if (_ofDict
== 0) return kIOReturnNoMemory
;
624 if (getPlatform()->getBootROMType()) {
626 while (cnt
< _ofPartitionSize
) {
627 // Break if there is no name.
628 if (_ofImage
[cnt
] == '\0') break;
630 // Find the length of the name.
631 propName
= _ofImage
+ cnt
;
632 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
634 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
637 // Break if the name goes past the end of the partition.
638 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
639 cnt
+= propNameLength
+ 1;
641 propData
= _ofImage
+ cnt
;
642 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
644 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
647 // Break if the data goes past the end of the partition.
648 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
649 cnt
+= propDataLength
+ 1;
651 if (convertPropToObject(propName
, propNameLength
,
652 propData
, propDataLength
,
653 &propSymbol
, &propObject
)) {
654 _ofDict
->setObject(propSymbol
, propObject
);
655 propSymbol
->release();
656 propObject
->release();
660 // Create the boot-args property if it is not in the dictionary.
661 if (_ofDict
->getObject("boot-args") == 0) {
662 propObject
= OSString::withCStringNoCopy("");
663 if (propObject
!= 0) {
664 _ofDict
->setObject("boot-args", propObject
);
665 propObject
->release();
669 // Create the 'aapl,panic-info' property if needed.
671 propDataLength
= *(UInt32
*)_piImage
;
672 if ((propDataLength
!= 0) && (propDataLength
<= (_piPartitionSize
- 4))) {
673 propObject
= OSData::withBytes(_piImage
+ 4, propDataLength
);
674 _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
);
675 propObject
->release();
677 // Clear the length from _piImage and mark dirty.
678 *(UInt32
*)_piImage
= 0;
679 _nvramImageDirty
= true;
683 owHeader
= (OWVariablesHeader
*)_ofImage
;
684 if (!validateOWChecksum(_ofImage
)) {
687 return kIOReturnBadMedia
;
692 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
696 case kOFVariableTypeBoolean
:
697 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
700 case kOFVariableTypeNumber
:
701 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
704 case kOFVariableTypeString
:
705 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
707 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
708 propName
= IONew(UInt8
, propDataLength
+ 1);
710 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
711 propName
[propDataLength
] = '\0';
712 propObject
= OSString::withCString((const char *)propName
);
713 IODelete(propName
, UInt8
, propDataLength
+ 1);
718 if (propObject
== 0) break;
720 _ofDict
->setObject(propSymbol
, propObject
);
721 propSymbol
->release();
722 propObject
->release();
725 // Create the boot-args property.
726 propSymbol
= OSSymbol::withCString("boot-command");
727 if (propSymbol
!= 0) {
728 propObject
= _ofDict
->getObject(propSymbol
);
729 if (propObject
!= 0) {
730 updateOWBootArgs(propSymbol
, propObject
);
732 propSymbol
->release();
736 return kIOReturnSuccess
;
739 IOReturn
IODTNVRAM::syncOFVariables(void)
742 UInt32 cnt
, length
, maxLength
;
743 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
744 UInt8
*buffer
, *tmpBuffer
;
745 const UInt8
*tmpData
;
746 const OSSymbol
*tmpSymbol
;
748 OSBoolean
*tmpBoolean
;
751 OSCollectionIterator
*iter
;
752 OWVariablesHeader
*owHeader
, *owHeaderOld
;
754 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
756 if (!_ofImageDirty
) return kIOReturnSuccess
;
758 if (getPlatform()->getBootROMType()) {
759 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
760 if (buffer
== 0) return kIOReturnNoMemory
;
761 bzero(buffer
, _ofPartitionSize
);
764 maxLength
= _ofPartitionSize
;
766 iter
= OSCollectionIterator::withCollection(_ofDict
);
767 if (iter
== 0) ok
= false;
770 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
771 if (tmpSymbol
== 0) break;
773 // Don't save 'aapl,panic-info'.
774 if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue;
776 tmpObject
= _ofDict
->getObject(tmpSymbol
);
779 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
788 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
791 IODelete(buffer
, UInt8
, _ofPartitionSize
);
793 if (!ok
) return kIOReturnBadArgument
;
795 buffer
= IONew(UInt8
, _ofPartitionSize
);
796 if (buffer
== 0) return kIOReturnNoMemory
;
797 bzero(buffer
, _ofPartitionSize
);
799 owHeader
= (OWVariablesHeader
*)buffer
;
800 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
802 owHeader
->owMagic
= owHeaderOld
->owMagic
;
803 owHeader
->owVersion
= owHeaderOld
->owVersion
;
804 owHeader
->owPages
= owHeaderOld
->owPages
;
806 curOffset
= _ofPartitionSize
;
811 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
814 tmpObject
= _ofDict
->getObject(tmpSymbol
);
817 case kOFVariableTypeBoolean
:
818 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
819 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
822 case kOFVariableTypeNumber
:
823 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
824 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
827 case kOFVariableTypeString
:
828 tmpString
= OSDynamicCast(OSString
, tmpObject
);
829 tmpData
= (const UInt8
*)tmpString
->getCStringNoCopy();
830 tmpDataLength
= tmpString
->getLength();
832 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
837 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
838 curOffset
-= tmpDataLength
;
839 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
840 if (tmpDataLength
!= 0)
841 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
847 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
848 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
849 owHeader
->owNext
= 0;
851 owHeader
->owChecksum
= 0;
852 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
854 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
857 IODelete(buffer
, UInt8
, _ofPartitionSize
);
859 if (!ok
) return kIOReturnBadArgument
;
862 _ofImageDirty
= false;
863 _nvramImageDirty
= true;
865 return kIOReturnSuccess
;
869 const char *variableName
;
872 SInt32 variableOffset
;
874 typedef struct OFVariable OFVariable
;
877 kOWVariableOffsetNumber
= 8,
878 kOWVariableOffsetString
= 17
881 OFVariable gOFVariables
[] = {
882 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
883 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
884 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
885 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
886 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
887 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
888 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
889 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
890 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
891 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
892 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
893 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
894 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
895 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
896 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
897 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
898 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
899 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
900 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
901 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
902 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
903 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
904 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
905 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
906 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
907 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
908 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
909 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
910 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
911 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
912 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
913 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
914 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
915 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
916 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
917 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
918 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
919 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
920 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
921 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
922 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
923 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
924 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
925 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
926 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
927 {"boot-image", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
928 {"com.apple.System.fp-state", kOFVariableTypeData
, kOFVariablePermKernelOnly
, -1},
929 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
932 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
936 ofVar
= gOFVariables
;
938 if ((ofVar
->variableName
== 0) ||
939 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
943 return ofVar
->variableType
;
946 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
950 ofVar
= gOFVariables
;
952 if ((ofVar
->variableName
== 0) ||
953 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
957 return ofVar
->variablePerm
;
960 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
961 UInt32
*propType
, UInt32
*propOffset
)
965 ofVar
= gOFVariables
;
967 if (ofVar
->variableName
== 0) return false;
969 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
974 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
975 *propType
= ofVar
->variableType
;
978 case kOFVariableTypeBoolean
:
979 *propOffset
= 1 << (31 - variableNumber
);
982 case kOFVariableTypeNumber
:
983 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
986 case kOFVariableTypeString
:
987 *propOffset
= variableNumber
- kOWVariableOffsetString
;
994 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
995 UInt8
*propData
, UInt32 propDataLength
,
996 const OSSymbol
**propSymbol
,
997 OSObject
**propObject
)
1000 const OSSymbol
*tmpSymbol
;
1001 OSObject
*tmpObject
;
1002 OSNumber
*tmpNumber
;
1003 OSString
*tmpString
;
1005 // Create the symbol.
1006 propName
[propNameLength
] = '\0';
1007 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
1008 propName
[propNameLength
] = '=';
1009 if (tmpSymbol
== 0) {
1013 propType
= getOFVariableType(tmpSymbol
);
1015 // Create the object.
1018 case kOFVariableTypeBoolean
:
1019 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
1020 tmpObject
= kOSBooleanTrue
;
1021 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
1022 tmpObject
= kOSBooleanFalse
;
1026 case kOFVariableTypeNumber
:
1027 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
1028 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
1031 case kOFVariableTypeString
:
1032 tmpString
= OSString::withCString((const char *)propData
);
1033 if (tmpString
!= 0) tmpObject
= tmpString
;
1036 case kOFVariableTypeData
:
1037 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
1041 if (tmpObject
== 0) {
1042 tmpSymbol
->release();
1046 *propSymbol
= tmpSymbol
;
1047 *propObject
= tmpObject
;
1052 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
1053 const OSSymbol
*propSymbol
, OSObject
*propObject
)
1055 const UInt8
*propName
;
1056 UInt32 propNameLength
, propDataLength
;
1057 UInt32 propType
, tmpValue
;
1058 OSBoolean
*tmpBoolean
= 0;
1059 OSNumber
*tmpNumber
= 0;
1060 OSString
*tmpString
= 0;
1061 OSData
*tmpData
= 0;
1063 propName
= (const UInt8
*)propSymbol
->getCStringNoCopy();
1064 propNameLength
= propSymbol
->getLength();
1065 propType
= getOFVariableType(propSymbol
);
1067 // Get the size of the data.
1068 propDataLength
= 0xFFFFFFFF;
1070 case kOFVariableTypeBoolean
:
1071 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
1072 if (tmpBoolean
!= 0) propDataLength
= 5;
1075 case kOFVariableTypeNumber
:
1076 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
1077 if (tmpNumber
!= 0) propDataLength
= 10;
1080 case kOFVariableTypeString
:
1081 tmpString
= OSDynamicCast(OSString
, propObject
);
1082 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
1085 case kOFVariableTypeData
:
1086 tmpData
= OSDynamicCast(OSData
, propObject
);
1088 tmpData
= escapeDataToData(tmpData
);
1089 propDataLength
= tmpData
->getLength();
1094 // Make sure the propertySize is known and will fit.
1095 if (propDataLength
== 0xFFFFFFFF) return false;
1096 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
1098 // Copy the property name equal sign.
1099 buffer
+= snprintf((char *)buffer
, *length
, "%s=", propName
);
1102 case kOFVariableTypeBoolean
:
1103 if (tmpBoolean
->getValue()) {
1104 strlcpy((char *)buffer
, "true", *length
- propNameLength
);
1106 strlcpy((char *)buffer
, "false", *length
- propNameLength
);
1110 case kOFVariableTypeNumber
:
1111 tmpValue
= tmpNumber
->unsigned32BitValue();
1112 if (tmpValue
== 0xFFFFFFFF) {
1113 strlcpy((char *)buffer
, "-1", *length
- propNameLength
);
1114 } else if (tmpValue
< 1000) {
1115 snprintf((char *)buffer
, *length
- propNameLength
, "%ld", tmpValue
);
1117 snprintf((char *)buffer
, *length
- propNameLength
, "0x%lx", tmpValue
);
1121 case kOFVariableTypeString
:
1122 strlcpy((char *)buffer
, tmpString
->getCStringNoCopy(), *length
- propNameLength
);
1125 case kOFVariableTypeData
:
1126 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
1131 propDataLength
= strlen((const char *)buffer
);
1133 *length
= propNameLength
+ propDataLength
+ 2;
1139 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
1141 UInt32 cnt
, checksum
= 0;
1142 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1144 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1145 checksum
+= tmpBuffer
[cnt
];
1147 return checksum
% 0x0000FFFF;
1150 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
1152 UInt32 cnt
, checksum
, sum
= 0;
1153 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1155 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1156 sum
+= tmpBuffer
[cnt
];
1158 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
1159 if (checksum
== 0x10000) checksum
--;
1160 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
1162 return checksum
== 0;
1165 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
1167 bool wasBootArgs
, bootr
= false;
1169 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
1170 const UInt8
*bootCommandData
, *bootArgsData
;
1172 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
1174 tmpString
= OSDynamicCast(OSString
, value
);
1175 if (tmpString
== 0) return;
1177 if (key
->isEqualTo("boot-command")) {
1178 wasBootArgs
= false;
1179 bootCommand
= tmpString
;
1180 } else if (key
->isEqualTo("boot-args")) {
1182 bootArgs
= tmpString
;
1183 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1184 if (bootCommand
== 0) return;
1187 bootCommandData
= (const UInt8
*)bootCommand
->getCStringNoCopy();
1188 bootCommandDataLength
= bootCommand
->getLength();
1190 if (bootCommandData
== 0) return;
1192 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1193 if ((bootCommandData
[cnt
] == 'b') &&
1194 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1196 while (bootCommandData
[cnt
] == ' ') cnt
++;
1202 _ofDict
->removeObject("boot-args");
1207 bootArgsData
= (const UInt8
*)bootArgs
->getCStringNoCopy();
1208 bootArgsDataLength
= bootArgs
->getLength();
1209 if (bootArgsData
== 0) return;
1211 tmpDataLength
= cnt
+ bootArgsDataLength
;
1212 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1213 if (tmpData
== 0) return;
1215 cnt
-= strlcpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1216 strlcat((char *)tmpData
, (const char *)bootArgsData
, cnt
);
1218 bootCommand
= OSString::withCString((const char *)tmpData
);
1219 if (bootCommand
!= 0) {
1220 _ofDict
->setObject("boot-command", bootCommand
);
1221 bootCommand
->release();
1224 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1226 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1227 if (bootArgs
!= 0) {
1228 _ofDict
->setObject("boot-args", bootArgs
);
1229 bootArgs
->release();
1235 // Private methods for Name Registry access.
1238 kMaxNVNameLength
= 4,
1239 kMaxNVDataLength
= 8
1242 #pragma options align=mac68k
1243 struct NVRAMProperty
1245 IONVRAMDescriptor header
;
1247 UInt8 name
[ kMaxNVNameLength
];
1249 UInt8 data
[ kMaxNVDataLength
];
1251 #pragma options align=reset
1253 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1258 nvEnd
= *((UInt16
*)_nrImage
);
1259 if(getPlatform()->getBootROMType()) {
1260 // on NewWorld, offset to partition start
1263 // on old world, absolute
1264 nvEnd
-= _nrPartitionOffset
;
1266 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1270 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1271 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1275 offset
+= sizeof(NVRAMProperty
);
1278 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1286 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1287 const OSSymbol
**name
,
1290 IONVRAMDescriptor hdr
;
1291 NVRAMProperty
*prop
;
1295 char nameBuf
[kMaxNVNameLength
+ 1];
1297 if (_nrImage
== 0) return kIOReturnUnsupported
;
1298 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1300 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1301 if (err
!= kIOReturnSuccess
) return err
;
1303 if (searchNVRAMProperty(&hdr
, &offset
)) {
1304 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1306 length
= prop
->nameLength
;
1307 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1308 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1309 nameBuf
[length
] = 0;
1310 *name
= OSSymbol::withCString(nameBuf
);
1312 length
= prop
->dataLength
;
1313 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1314 *value
= OSData::withBytes(prop
->data
, length
);
1316 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1317 else return kIOReturnNoMemory
;
1320 return kIOReturnNoResources
;
1323 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1324 const OSSymbol
*name
,
1327 IONVRAMDescriptor hdr
;
1328 NVRAMProperty
*prop
;
1329 IOByteCount nameLength
;
1330 IOByteCount dataLength
;
1336 if (_nrImage
== 0) return kIOReturnUnsupported
;
1337 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1339 nameLength
= name
->getLength();
1340 dataLength
= value
->getLength();
1341 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1342 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1344 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1345 if (err
!= kIOReturnSuccess
) return err
;
1347 exists
= searchNVRAMProperty(&hdr
, &offset
);
1348 if (offset
== 0) return kIOReturnNoMemory
;
1350 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1351 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1353 prop
->nameLength
= nameLength
;
1354 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1355 prop
->dataLength
= dataLength
;
1356 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1359 nvLength
= offset
+ sizeof(NVRAMProperty
);
1360 if (getPlatform()->getBootROMType())
1363 nvLength
+= _nrPartitionOffset
;
1364 *((UInt16
*)_nrImage
) = nvLength
;
1367 _nvramImageDirty
= true;
1372 OSData
*IODTNVRAM::unescapeBytesToData(const UInt8
*bytes
, UInt32 length
)
1375 UInt32 totalLength
= 0;
1380 // Calculate the actual length of the data.
1383 for (cnt
= 0; cnt
< length
;) {
1384 byte
= bytes
[cnt
++];
1386 byte
= bytes
[cnt
++];
1394 totalLength
+= cnt2
;
1398 // Create an empty OSData of the correct size.
1399 data
= OSData::withCapacity(totalLength
);
1401 for (cnt
= 0; cnt
< length
;) {
1402 byte
= bytes
[cnt
++];
1404 byte
= bytes
[cnt
++];
1406 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1409 data
->appendByte(byte
, cnt2
);
1417 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1420 const UInt8
* startPtr
;
1421 const UInt8
* endPtr
;
1422 const UInt8
* wherePtr
;
1426 wherePtr
= (const UInt8
*) value
->getBytesNoCopy();
1427 endPtr
= wherePtr
+ value
->getLength();
1429 result
= OSData::withCapacity(endPtr
- wherePtr
);
1433 while (wherePtr
< endPtr
) {
1434 startPtr
= wherePtr
;
1436 if ((byte
== 0x00) || (byte
== 0xFF)) {
1438 ((wherePtr
- startPtr
) < 0x80) && (wherePtr
< endPtr
) && (byte
== *wherePtr
);
1440 ok
&= result
->appendByte(0xff, 1);
1441 byte
= (byte
& 0x80) | (wherePtr
- startPtr
);
1443 ok
&= result
->appendByte(byte
, 1);
1445 ok
&= result
->appendByte(0, 1);
1455 static bool IsApplePropertyName(const char * propName
)
1458 while ((c
= *propName
++)) {
1459 if ((c
>= 'A') && (c
<= 'Z'))
1466 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1467 const OSSymbol
**name
,
1470 IOReturn err
= kIOReturnNoResources
;
1472 const UInt8
*startPtr
;
1473 const UInt8
*endPtr
;
1474 const UInt8
*wherePtr
;
1475 const UInt8
*nvPath
= 0;
1476 const char *nvName
= 0;
1477 const char *resultName
= 0;
1478 const UInt8
*resultValue
= 0;
1479 UInt32 resultValueLen
= 0;
1482 if (_ofDict
== 0) return err
;
1483 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1484 if (data
== 0) return err
;
1486 startPtr
= (const UInt8
*) data
->getBytesNoCopy();
1487 endPtr
= startPtr
+ data
->getLength();
1489 wherePtr
= startPtr
;
1490 while (wherePtr
< endPtr
) {
1491 byte
= *(wherePtr
++);
1497 else if (nvName
== 0)
1498 nvName
= (const char *) startPtr
;
1500 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1502 compareEntry
->release();
1503 if (entry
== compareEntry
) {
1504 bool appleProp
= IsApplePropertyName(nvName
);
1505 if (!appleProp
|| !resultName
) {
1506 resultName
= nvName
;
1507 resultValue
= startPtr
;
1508 resultValueLen
= wherePtr
- startPtr
- 1;
1516 startPtr
= wherePtr
;
1519 *name
= OSSymbol::withCString(resultName
);
1520 *value
= unescapeBytesToData(resultValue
, resultValueLen
);
1521 if ((*name
!= 0) && (*value
!= 0))
1522 err
= kIOReturnSuccess
;
1524 err
= kIOReturnNoMemory
;
1529 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1530 const OSSymbol
*propName
,
1535 const UInt8
*startPtr
;
1536 const UInt8
*propStart
;
1537 const UInt8
*endPtr
;
1538 const UInt8
*wherePtr
;
1539 const UInt8
*nvPath
= 0;
1540 const char *nvName
= 0;
1545 bool settingAppleProp
;
1547 if (_ofDict
== 0) return kIOReturnNoResources
;
1549 settingAppleProp
= IsApplePropertyName(propName
->getCStringNoCopy());
1551 // copy over existing properties for other entries
1553 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1555 startPtr
= (const UInt8
*) oldData
->getBytesNoCopy();
1556 endPtr
= startPtr
+ oldData
->getLength();
1558 propStart
= startPtr
;
1559 wherePtr
= startPtr
;
1560 while (wherePtr
< endPtr
) {
1561 byte
= *(wherePtr
++);
1566 else if (nvName
== 0)
1567 nvName
= (const char *) startPtr
;
1569 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1571 compareEntry
->release();
1572 if (entry
== compareEntry
) {
1573 if ((settingAppleProp
&& propName
->isEqualTo(nvName
))
1574 || (!settingAppleProp
&& !IsApplePropertyName(nvName
))) {
1575 // delete old property (nvPath -> wherePtr)
1576 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1578 ok
&= data
->appendBytes(wherePtr
, endPtr
- wherePtr
);
1586 startPtr
= wherePtr
;
1590 // make the new property
1594 data
= OSData::withData(oldData
);
1596 data
= OSData::withCapacity(16);
1598 return kIOReturnNoMemory
;
1601 if (value
&& value
->getLength()) {
1602 // get entries in path
1603 OSArray
*array
= OSArray::withCapacity(5);
1606 return kIOReturnNoMemory
;
1609 array
->setObject(entry
);
1610 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1613 for (int i
= array
->getCount() - 3;
1614 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1617 name
= entry
->getName(gIODTPlane
);
1618 comp
= entry
->getLocation(gIODTPlane
);
1619 if( comp
&& (0 == strncmp("pci", name
, sizeof("pci")))
1620 && (0 == strncmp("80000000", comp
, sizeof("80000000")))) {
1622 comp
= "/pci@80000000";
1625 ok
&= data
->appendBytes("/@", 2);
1629 ok
&= data
->appendByte('/', 1);
1633 ok
&= data
->appendBytes(comp
, strlen(comp
));
1635 ok
&= data
->appendByte(0, 1);
1639 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1641 // append escaped data
1642 oldData
= escapeDataToData(value
);
1643 ok
&= (oldData
!= 0);
1645 ok
&= data
->appendBytes(oldData
);
1648 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1650 _ofImageDirty
= true;
1654 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;