2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #include <IOKit/IOLib.h>
27 #include <IOKit/IONVRAM.h>
28 #include <IOKit/IOPlatformExpert.h>
29 #include <IOKit/IOUserClient.h>
30 #include <IOKit/IOKitKeys.h>
32 #define super IOService
34 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
);
36 bool IODTNVRAM::init(IORegistryEntry
*old
, const IORegistryPlane
*plane
)
40 if (!super::init(old
, plane
)) return false;
42 dict
= OSDictionary::withCapacity(1);
43 if (dict
== 0) return false;
44 setPropertyTable(dict
);
46 _nvramImage
= IONew(UInt8
, kIODTNVRAMImageSize
);
47 if (_nvramImage
== 0) return false;
49 _nvramPartitionOffsets
= OSDictionary::withCapacity(1);
50 if (_nvramPartitionOffsets
== 0) return false;
52 _nvramPartitionLengths
= OSDictionary::withCapacity(1);
53 if (_nvramPartitionLengths
== 0) return false;
55 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
56 if (_registryPropertiesKey
== 0) return false;
61 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
64 UInt32 partitionOffset
, partitionLength
;
65 UInt32 freePartitionOffset
, freePartitionSize
;
66 UInt32 currentLength
, currentOffset
= 0;
67 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
69 if (_nvramController
!= 0) return;
71 _nvramController
= nvram
;
73 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
75 // Find the offsets for the OF, XPRAM, NameRegistry and PanicInfo partitions.
76 _ofPartitionOffset
= 0xFFFFFFFF;
77 _xpramPartitionOffset
= 0xFFFFFFFF;
78 _nrPartitionOffset
= 0xFFFFFFFF;
79 _piPartitionOffset
= 0xFFFFFFFF;
80 freePartitionOffset
= 0xFFFFFFFF;
81 freePartitionSize
= 0;
82 if (getPlatform()->getBootROMType()) {
83 // Look through the partitions to find the OF, MacOS partitions.
84 while (currentOffset
< kIODTNVRAMImageSize
) {
85 currentLength
= ((UInt16
*)(_nvramImage
+ currentOffset
))[1] * 16;
87 partitionOffset
= currentOffset
+ 16;
88 partitionLength
= currentLength
- 16;
90 if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
91 kIODTNVRAMOFPartitionName
, 12) == 0) {
92 _ofPartitionOffset
= partitionOffset
;
93 _ofPartitionSize
= partitionLength
;
94 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
95 kIODTNVRAMXPRAMPartitionName
, 12) == 0) {
96 _xpramPartitionOffset
= partitionOffset
;
97 _xpramPartitionSize
= kIODTNVRAMXPRAMSize
;
98 _nrPartitionOffset
= _xpramPartitionOffset
+ _xpramPartitionSize
;
99 _nrPartitionSize
= partitionLength
- _xpramPartitionSize
;
100 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
101 kIODTNVRAMPanicInfoPartitonName
, 12) == 0) {
102 _piPartitionOffset
= partitionOffset
;
103 _piPartitionSize
= partitionLength
;
104 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
105 kIODTNVRAMFreePartitionName
, 12) == 0) {
106 freePartitionOffset
= currentOffset
;
107 freePartitionSize
= currentLength
;
109 // Construct the partition ID from the signature and name.
110 sprintf(partitionID
, "0x%02x,",
111 *(UInt8
*)(_nvramImage
+ currentOffset
));
112 strncpy(partitionID
+ 5,
113 (const char *)(_nvramImage
+ currentOffset
+ 4), 12);
114 partitionID
[17] = '\0';
116 partitionOffsetNumber
= OSNumber::withNumber(partitionOffset
, 32);
117 partitionLengthNumber
= OSNumber::withNumber(partitionLength
, 32);
119 // Save the partition offset and length
120 _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
);
121 _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
);
123 partitionOffsetNumber
->release();
124 partitionLengthNumber
->release();
126 currentOffset
+= currentLength
;
129 // Use the fixed address for old world machines.
130 _ofPartitionOffset
= 0x1800;
131 _ofPartitionSize
= 0x0800;
132 _xpramPartitionOffset
= 0x1300;
133 _xpramPartitionSize
= 0x0100;
134 _nrPartitionOffset
= 0x1400;
135 _nrPartitionSize
= 0x0400;
138 if (_ofPartitionOffset
!= 0xFFFFFFFF)
139 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
140 if (_xpramPartitionOffset
!= 0xFFFFFFFF)
141 _xpramImage
= _nvramImage
+ _xpramPartitionOffset
;
142 if (_nrPartitionOffset
!= 0xFFFFFFFF)
143 _nrImage
= _nvramImage
+ _nrPartitionOffset
;
145 if (_piPartitionOffset
== 0xFFFFFFFF) {
146 if (freePartitionSize
> 0x20) {
147 // Set the signature to 0xa1.
148 _nvramImage
[freePartitionOffset
] = 0xa1;
149 // Set the checksum to 0.
150 _nvramImage
[freePartitionOffset
+ 1] = 0;
151 // Set the name for the Panic Info partition.
152 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
153 kIODTNVRAMPanicInfoPartitonName
, 12);
155 // Calculate the partition offset and size.
156 _piPartitionOffset
= freePartitionOffset
+ 0x10;
157 _piPartitionSize
= 0x800;
158 if (_piPartitionSize
+ 0x20 > freePartitionSize
)
159 _piPartitionSize
= freePartitionSize
- 0x20;
161 _piImage
= _nvramImage
+ _piPartitionOffset
;
163 // Zero the new partition.
164 bzero(_piImage
, _piPartitionSize
);
166 // Set the partition size.
167 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
168 (_piPartitionSize
/ 0x10) + 1;
170 // Set the partition checksum.
171 _nvramImage
[freePartitionOffset
+ 1] =
172 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
174 // Calculate the free partition offset and size.
175 freePartitionOffset
+= _piPartitionSize
+ 0x10;
176 freePartitionSize
-= _piPartitionSize
+ 0x10;
178 // Set the signature to 0x7f.
179 _nvramImage
[freePartitionOffset
] = 0x7f;
180 // Set the checksum to 0.
181 _nvramImage
[freePartitionOffset
+ 1] = 0;
182 // Set the name for the free partition.
183 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
184 kIODTNVRAMFreePartitionName
, 12);
185 // Set the partition size.
186 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
187 freePartitionSize
/ 0x10;
188 // Set the partition checksum.
189 _nvramImage
[freePartitionOffset
+ 1] =
190 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
192 // Set the nvram image as dirty.
193 _nvramImageDirty
= true;
196 _piImage
= _nvramImage
+ _piPartitionOffset
;
202 void IODTNVRAM::sync(void)
204 if (!_nvramImageDirty
&& !_ofImageDirty
) return;
206 // Don't try to sync OF Variables if the system has already paniced.
207 if (!_systemPaniced
) syncOFVariables();
209 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
210 _nvramController
->sync();
212 _nvramImageDirty
= false;
215 bool IODTNVRAM::serializeProperties(OSSerialize
*serialize
) const
220 OSDictionary
*dict
, *tmpDict
= 0;
221 OSCollectionIterator
*iter
= 0;
223 if (_ofDict
== 0) return false;
225 // Verify permissions.
226 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
227 if (result
!= kIOReturnSuccess
) {
228 tmpDict
= OSDictionary::withCapacity(1);
229 if (tmpDict
== 0) return false;
231 iter
= OSCollectionIterator::withCollection(_ofDict
);
232 if (iter
== 0) return false;
235 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
238 variablePerm
= getOFVariablePerm(key
);
239 if (variablePerm
!= kOFVariablePermRootOnly
) {
240 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
248 result
= dict
->serialize(serialize
);
250 if (tmpDict
!= 0) tmpDict
->release();
251 if (iter
!= 0) iter
->release();
256 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
261 if (_ofDict
== 0) return 0;
263 // Verify permissions.
264 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
265 if (result
!= kIOReturnSuccess
) {
266 variablePerm
= getOFVariablePerm(aKey
);
267 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
270 return _ofDict
->getObject(aKey
);
273 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
275 const OSSymbol
*keySymbol
;
276 OSObject
*theObject
= 0;
278 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
279 if (keySymbol
!= 0) {
280 theObject
= getProperty(keySymbol
);
281 keySymbol
->release();
287 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
290 UInt32 propType
, propPerm
;
292 OSObject
*propObject
= 0;
294 if (_ofDict
== 0) return false;
296 // Verify permissions.
297 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
298 if (result
!= kIOReturnSuccess
) {
299 propPerm
= getOFVariablePerm(aKey
);
300 if (propPerm
!= kOFVariablePermUserWrite
) return false;
303 // Don't allow creation of new properties on old world machines.
304 if (getPlatform()->getBootROMType() == 0) {
305 if (_ofDict
->getObject(aKey
) == 0) return false;
308 // Don't allow change of 'aapl,panic-info'.
309 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return false;
311 // Make sure the object is of the correct type.
312 propType
= getOFVariableType(aKey
);
314 case kOFVariableTypeBoolean
:
315 propObject
= OSDynamicCast(OSBoolean
, anObject
);
318 case kOFVariableTypeNumber
:
319 propObject
= OSDynamicCast(OSNumber
, anObject
);
322 case kOFVariableTypeString
:
323 propObject
= OSDynamicCast(OSString
, anObject
);
326 case kOFVariableTypeData
:
327 propObject
= OSDynamicCast(OSData
, anObject
);
328 if (propObject
== 0) {
329 tmpString
= OSDynamicCast(OSString
, anObject
);
330 if (tmpString
!= 0) {
331 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
332 tmpString
->getLength());
338 if (propObject
== 0) return false;
340 result
= _ofDict
->setObject(aKey
, propObject
);
343 if (getPlatform()->getBootROMType() == 0) {
344 updateOWBootArgs(aKey
, propObject
);
347 _ofImageDirty
= true;
353 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
359 OSCollectionIterator
*iter
;
361 dict
= OSDynamicCast(OSDictionary
, properties
);
362 if (dict
== 0) return kIOReturnBadArgument
;
364 iter
= OSCollectionIterator::withCollection(dict
);
365 if (iter
== 0) return kIOReturnBadArgument
;
368 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
371 object
= dict
->getObject(key
);
372 if (object
== 0) continue;
374 result
= setProperty(key
, object
);
379 if (result
) return kIOReturnSuccess
;
380 else return kIOReturnError
;
383 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
386 if (_xpramImage
== 0) return kIOReturnUnsupported
;
388 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
389 (offset
+ length
> kIODTNVRAMXPRAMSize
))
390 return kIOReturnBadArgument
;
392 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
394 return kIOReturnSuccess
;
397 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
400 if (_xpramImage
== 0) return kIOReturnUnsupported
;
402 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
403 (offset
+ length
> kIODTNVRAMXPRAMSize
))
404 return kIOReturnBadArgument
;
406 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
408 _nvramImageDirty
= true;
410 return kIOReturnSuccess
;
413 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
414 const OSSymbol
**name
,
419 if (getPlatform()->getBootROMType())
420 err
= readNVRAMPropertyType1(entry
, name
, value
);
422 err
= readNVRAMPropertyType0(entry
, name
, value
);
427 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
428 const OSSymbol
*name
,
433 if (getPlatform()->getBootROMType())
434 err
= writeNVRAMPropertyType1(entry
, name
, value
);
436 err
= writeNVRAMPropertyType0(entry
, name
, value
);
441 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
443 return _nvramPartitionLengths
;
446 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
447 IOByteCount offset
, UInt8
*buffer
,
450 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
451 UInt32 partitionOffset
, partitionLength
;
453 partitionOffsetNumber
=
454 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
455 partitionLengthNumber
=
456 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
458 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
459 return kIOReturnNotFound
;
461 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
462 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
464 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
465 (offset
+ length
> partitionLength
))
466 return kIOReturnBadArgument
;
468 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
470 return kIOReturnSuccess
;
473 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
474 IOByteCount offset
, UInt8
*buffer
,
477 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
478 UInt32 partitionOffset
, partitionLength
;
480 partitionOffsetNumber
=
481 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
482 partitionLengthNumber
=
483 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
485 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
486 return kIOReturnNotFound
;
488 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
489 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
491 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
492 (offset
+ length
> partitionLength
))
493 return kIOReturnBadArgument
;
495 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
497 _nvramImageDirty
= true;
499 return kIOReturnSuccess
;
502 UInt32
IODTNVRAM::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
504 if ((_piImage
== 0) || (length
<= 0)) return 0;
506 if (length
> (_piPartitionSize
- 4))
507 length
= _piPartitionSize
- 4;
509 // Save the Panic Info.
510 bcopy(buffer
, _piImage
+ 4, length
);
512 // Save the Panic Info length.
513 *(UInt32
*)_piImage
= length
;
515 _nvramImageDirty
= true;
517 _systemPaniced
= true;
524 UInt8
IODTNVRAM::calculatePartitionChecksum(UInt8
*partitionHeader
)
526 UInt8 cnt
, isum
, csum
= 0;
528 for (cnt
= 0; cnt
< 0x10; cnt
++) {
529 isum
= csum
+ partitionHeader
[cnt
];
530 if (isum
< csum
) isum
++;
537 struct OWVariablesHeader
{
552 typedef struct OWVariablesHeader OWVariablesHeader
;
554 IOReturn
IODTNVRAM::initOFVariables(void)
556 UInt32 cnt
, propOffset
, propType
;
557 UInt8
*propName
, *propData
;
558 UInt32 propNameLength
, propDataLength
;
559 const OSSymbol
*propSymbol
;
560 OSObject
*propObject
;
561 OWVariablesHeader
*owHeader
;
563 if (_ofImage
== 0) return kIOReturnNotReady
;
565 _ofDict
= OSDictionary::withCapacity(1);
566 if (_ofDict
== 0) return kIOReturnNoMemory
;
568 if (getPlatform()->getBootROMType()) {
570 while (cnt
< _ofPartitionSize
) {
571 // Break if there is no name.
572 if (_ofImage
[cnt
] == '\0') break;
574 // Find the length of the name.
575 propName
= _ofImage
+ cnt
;
576 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
578 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
581 // Break if the name goes past the end of the partition.
582 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
583 cnt
+= propNameLength
+ 1;
585 propData
= _ofImage
+ cnt
;
586 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
588 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
591 // Break if the data goes past the end of the partition.
592 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
593 cnt
+= propDataLength
+ 1;
595 if (convertPropToObject(propName
, propNameLength
,
596 propData
, propDataLength
,
597 &propSymbol
, &propObject
)) {
598 _ofDict
->setObject(propSymbol
, propObject
);
599 propSymbol
->release();
600 propObject
->release();
604 // Create the boot-args property if it is not in the dictionary.
605 if (_ofDict
->getObject("boot-args") == 0) {
606 propObject
= OSString::withCStringNoCopy("");
607 if (propObject
!= 0) {
608 _ofDict
->setObject("boot-args", propObject
);
609 propObject
->release();
613 // Create the 'aapl,panic-info' property if needed.
615 propDataLength
= *(UInt32
*)_piImage
;
616 if ((propDataLength
!= 0) && (propDataLength
< (_piPartitionSize
- 4))) {
617 propObject
= OSData::withBytes(_piImage
+ 4, propDataLength
);
618 _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
);
619 propObject
->release();
621 // Clear the length from _piImage and mark dirty.
622 *(UInt32
*)_piImage
= 0;
623 _nvramImageDirty
= true;
627 owHeader
= (OWVariablesHeader
*)_ofImage
;
628 if (!validateOWChecksum(_ofImage
)) {
631 return kIOReturnBadMedia
;
636 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
640 case kOFVariableTypeBoolean
:
641 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
644 case kOFVariableTypeNumber
:
645 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
648 case kOFVariableTypeString
:
649 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
651 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
652 propName
= IONew(UInt8
, propDataLength
+ 1);
654 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
655 propName
[propDataLength
] = '\0';
656 propObject
= OSString::withCString((const char *)propName
);
657 IODelete(propName
, UInt8
, propDataLength
+ 1);
662 if (propObject
== 0) break;
664 _ofDict
->setObject(propSymbol
, propObject
);
665 propSymbol
->release();
666 propObject
->release();
669 // Create the boot-args property.
670 propSymbol
= OSSymbol::withCString("boot-command");
671 if (propSymbol
!= 0) {
672 propObject
= _ofDict
->getObject(propSymbol
);
673 if (propObject
!= 0) {
674 updateOWBootArgs(propSymbol
, propObject
);
676 propSymbol
->release();
680 return kIOReturnSuccess
;
683 IOReturn
IODTNVRAM::syncOFVariables(void)
686 UInt32 cnt
, length
, maxLength
;
687 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
688 UInt8
*buffer
, *tmpBuffer
, *tmpData
;
689 const OSSymbol
*tmpSymbol
;
691 OSBoolean
*tmpBoolean
;
694 OSCollectionIterator
*iter
;
695 OWVariablesHeader
*owHeader
, *owHeaderOld
;
697 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
699 if (!_ofImageDirty
) return kIOReturnSuccess
;
701 if (getPlatform()->getBootROMType()) {
702 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
703 if (buffer
== 0) return kIOReturnNoMemory
;
704 bzero(buffer
, _ofPartitionSize
);
707 maxLength
= _ofPartitionSize
;
709 iter
= OSCollectionIterator::withCollection(_ofDict
);
710 if (iter
== 0) ok
= false;
713 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
714 if (tmpSymbol
== 0) break;
716 // Don't save 'aapl,panic-info'.
717 if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue;
719 tmpObject
= _ofDict
->getObject(tmpSymbol
);
722 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
731 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
734 IODelete(buffer
, UInt8
, _ofPartitionSize
);
736 if (!ok
) return kIOReturnBadArgument
;
738 buffer
= IONew(UInt8
, _ofPartitionSize
);
739 if (buffer
== 0) return kIOReturnNoMemory
;
740 bzero(buffer
, _ofPartitionSize
);
742 owHeader
= (OWVariablesHeader
*)buffer
;
743 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
745 owHeader
->owMagic
= owHeaderOld
->owMagic
;
746 owHeader
->owVersion
= owHeaderOld
->owVersion
;
747 owHeader
->owPages
= owHeaderOld
->owPages
;
749 curOffset
= _ofPartitionSize
;
754 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
757 tmpObject
= _ofDict
->getObject(tmpSymbol
);
760 case kOFVariableTypeBoolean
:
761 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
762 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
765 case kOFVariableTypeNumber
:
766 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
767 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
770 case kOFVariableTypeString
:
771 tmpString
= OSDynamicCast(OSString
, tmpObject
);
772 tmpData
= (UInt8
*) tmpString
->getCStringNoCopy();
773 tmpDataLength
= tmpString
->getLength();
775 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
780 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
781 curOffset
-= tmpDataLength
;
782 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
783 if (tmpDataLength
!= 0)
784 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
790 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
791 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
792 owHeader
->owNext
= 0;
794 owHeader
->owChecksum
= 0;
795 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
797 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
800 IODelete(buffer
, UInt8
, _ofPartitionSize
);
802 if (!ok
) return kIOReturnBadArgument
;
805 _ofImageDirty
= false;
806 _nvramImageDirty
= true;
808 return kIOReturnSuccess
;
815 SInt32 variableOffset
;
817 typedef struct OFVariable OFVariable
;
820 kOWVariableOffsetNumber
= 8,
821 kOWVariableOffsetString
= 17
824 OFVariable gOFVariables
[] = {
825 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
826 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
827 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
828 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
829 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
830 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
831 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
832 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
833 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
834 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
835 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
836 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
837 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
838 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
839 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
840 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
841 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
842 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
843 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
844 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
845 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
846 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
847 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
848 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
849 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
850 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
851 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
852 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
853 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
854 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
855 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
856 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
857 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
858 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
859 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
860 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
861 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
862 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
863 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
864 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
865 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
866 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
867 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
868 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
869 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
870 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
873 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
877 ofVar
= gOFVariables
;
879 if ((ofVar
->variableName
== 0) ||
880 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
884 return ofVar
->variableType
;
887 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
891 ofVar
= gOFVariables
;
893 if ((ofVar
->variableName
== 0) ||
894 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
898 return ofVar
->variablePerm
;
901 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
902 UInt32
*propType
, UInt32
*propOffset
)
906 ofVar
= gOFVariables
;
908 if (ofVar
->variableName
== 0) return false;
910 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
915 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
916 *propType
= ofVar
->variableType
;
919 case kOFVariableTypeBoolean
:
920 *propOffset
= 1 << (31 - variableNumber
);
923 case kOFVariableTypeNumber
:
924 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
927 case kOFVariableTypeString
:
928 *propOffset
= variableNumber
- kOWVariableOffsetString
;
935 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
936 UInt8
*propData
, UInt32 propDataLength
,
937 const OSSymbol
**propSymbol
,
938 OSObject
**propObject
)
941 const OSSymbol
*tmpSymbol
;
946 // Create the symbol.
947 propName
[propNameLength
] = '\0';
948 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
949 propName
[propNameLength
] = '=';
950 if (tmpSymbol
== 0) {
954 propType
= getOFVariableType(tmpSymbol
);
956 // Create the object.
959 case kOFVariableTypeBoolean
:
960 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
961 tmpObject
= kOSBooleanTrue
;
962 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
963 tmpObject
= kOSBooleanFalse
;
967 case kOFVariableTypeNumber
:
968 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
969 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
972 case kOFVariableTypeString
:
973 tmpString
= OSString::withCString((const char *)propData
);
974 if (tmpString
!= 0) tmpObject
= tmpString
;
977 case kOFVariableTypeData
:
978 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
982 if (tmpObject
== 0) {
983 tmpSymbol
->release();
987 *propSymbol
= tmpSymbol
;
988 *propObject
= tmpObject
;
993 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
994 const OSSymbol
*propSymbol
, OSObject
*propObject
)
997 UInt32 propNameLength
, propDataLength
;
998 UInt32 propType
, tmpValue
;
999 OSBoolean
*tmpBoolean
= 0;
1000 OSNumber
*tmpNumber
= 0;
1001 OSString
*tmpString
= 0;
1002 OSData
*tmpData
= 0;
1004 propName
= (UInt8
*)propSymbol
->getCStringNoCopy();
1005 propNameLength
= propSymbol
->getLength();
1006 propType
= getOFVariableType(propSymbol
);
1008 // Get the size of the data.
1009 propDataLength
= 0xFFFFFFFF;
1011 case kOFVariableTypeBoolean
:
1012 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
1013 if (tmpBoolean
!= 0) propDataLength
= 5;
1016 case kOFVariableTypeNumber
:
1017 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
1018 if (tmpNumber
!= 0) propDataLength
= 10;
1021 case kOFVariableTypeString
:
1022 tmpString
= OSDynamicCast(OSString
, propObject
);
1023 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
1026 case kOFVariableTypeData
:
1027 tmpData
= OSDynamicCast(OSData
, propObject
);
1029 tmpData
= escapeDataToData(tmpData
);
1030 propDataLength
= tmpData
->getLength();
1035 // Make sure the propertySize is known and will fit.
1036 if (propDataLength
== 0xFFFFFFFF) return false;
1037 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
1039 // Copy the property name equal sign.
1040 sprintf((char *)buffer
, "%s=", propName
);
1041 buffer
+= propNameLength
+ 1;
1044 case kOFVariableTypeBoolean
:
1045 if (tmpBoolean
->getValue()) {
1046 strcpy((char *)buffer
, "true");
1048 strcpy((char *)buffer
, "false");
1052 case kOFVariableTypeNumber
:
1053 tmpValue
= tmpNumber
->unsigned32BitValue();
1054 if (tmpValue
== 0xFFFFFFFF) {
1055 strcpy((char *)buffer
, "-1");
1056 } else if (tmpValue
< 1000) {
1057 sprintf((char *)buffer
, "%ld", tmpValue
);
1059 sprintf((char *)buffer
, "0x%lx", tmpValue
);
1063 case kOFVariableTypeString
:
1064 strcpy((char *)buffer
, tmpString
->getCStringNoCopy());
1067 case kOFVariableTypeData
:
1068 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
1073 propDataLength
= strlen((const char *)buffer
);
1075 *length
= propNameLength
+ propDataLength
+ 2;
1081 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
1083 UInt32 cnt
, checksum
= 0;
1084 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1086 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1087 checksum
+= tmpBuffer
[cnt
];
1089 return checksum
% 0x0000FFFF;
1092 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
1094 UInt32 cnt
, checksum
, sum
= 0;
1095 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1097 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1098 sum
+= tmpBuffer
[cnt
];
1100 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
1101 if (checksum
== 0x10000) checksum
--;
1102 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
1104 return checksum
== 0;
1107 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
1109 bool wasBootArgs
, bootr
= false;
1111 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
1112 UInt8
*bootCommandData
, *bootArgsData
, *tmpData
;
1113 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
1115 tmpString
= OSDynamicCast(OSString
, value
);
1116 if (tmpString
== 0) return;
1118 if (key
->isEqualTo("boot-command")) {
1119 wasBootArgs
= false;
1120 bootCommand
= tmpString
;
1121 } else if (key
->isEqualTo("boot-args")) {
1123 bootArgs
= tmpString
;
1124 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1125 if (bootCommand
== 0) return;
1128 bootCommandData
= (UInt8
*)bootCommand
->getCStringNoCopy();
1129 bootCommandDataLength
= bootCommand
->getLength();
1131 if (bootCommandData
== 0) return;
1133 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1134 if ((bootCommandData
[cnt
] == 'b') &&
1135 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1137 while (bootCommandData
[cnt
] == ' ') cnt
++;
1143 _ofDict
->removeObject("boot-args");
1148 bootArgsData
= (UInt8
*)bootArgs
->getCStringNoCopy();
1149 bootArgsDataLength
= bootArgs
->getLength();
1150 if (bootArgsData
== 0) return;
1152 tmpDataLength
= cnt
+ bootArgsDataLength
;
1153 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1154 if (tmpData
== 0) return;
1156 strncpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1157 tmpData
[cnt
] = '\0';
1158 strcat((char *)tmpData
, (const char *)bootArgsData
);
1160 bootCommand
= OSString::withCString((const char *)tmpData
);
1161 if (bootCommand
!= 0) {
1162 _ofDict
->setObject("boot-command", bootCommand
);
1163 bootCommand
->release();
1166 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1168 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1169 if (bootArgs
!= 0) {
1170 _ofDict
->setObject("boot-args", bootArgs
);
1171 bootArgs
->release();
1177 // Private methods for Name Registry access.
1180 kMaxNVNameLength
= 4,
1181 kMaxNVDataLength
= 8
1184 #pragma options align=mac68k
1185 struct NVRAMProperty
1187 IONVRAMDescriptor header
;
1189 UInt8 name
[ kMaxNVNameLength
];
1191 UInt8 data
[ kMaxNVDataLength
];
1193 #pragma options align=reset
1195 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1200 nvEnd
= *((UInt16
*)_nrImage
);
1201 if(getPlatform()->getBootROMType()) {
1202 // on NewWorld, offset to partition start
1205 // on old world, absolute
1206 nvEnd
-= _nrPartitionOffset
;
1208 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1212 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1213 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1217 offset
+= sizeof(NVRAMProperty
);
1220 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1228 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1229 const OSSymbol
**name
,
1232 IONVRAMDescriptor hdr
;
1233 NVRAMProperty
*prop
;
1237 char nameBuf
[kMaxNVNameLength
+ 1];
1239 if (_nrImage
== 0) return kIOReturnUnsupported
;
1240 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1242 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1243 if (err
!= kIOReturnSuccess
) return err
;
1245 if (searchNVRAMProperty(&hdr
, &offset
)) {
1246 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1248 length
= prop
->nameLength
;
1249 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1250 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1251 nameBuf
[length
] = 0;
1252 *name
= OSSymbol::withCString(nameBuf
);
1254 length
= prop
->dataLength
;
1255 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1256 *value
= OSData::withBytes(prop
->data
, length
);
1258 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1259 else return kIOReturnNoMemory
;
1262 return kIOReturnNoResources
;
1265 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1266 const OSSymbol
*name
,
1269 IONVRAMDescriptor hdr
;
1270 NVRAMProperty
*prop
;
1271 IOByteCount nameLength
;
1272 IOByteCount dataLength
;
1278 if (_nrImage
== 0) return kIOReturnUnsupported
;
1279 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1281 nameLength
= name
->getLength();
1282 dataLength
= value
->getLength();
1283 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1284 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1286 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1287 if (err
!= kIOReturnSuccess
) return err
;
1289 exists
= searchNVRAMProperty(&hdr
, &offset
);
1290 if (offset
== 0) return kIOReturnNoMemory
;
1292 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1293 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1295 prop
->nameLength
= nameLength
;
1296 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1297 prop
->dataLength
= dataLength
;
1298 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1301 nvLength
= offset
+ sizeof(NVRAMProperty
);
1302 if (getPlatform()->getBootROMType())
1305 nvLength
+= _nrPartitionOffset
;
1306 *((UInt16
*)_nrImage
) = nvLength
;
1309 _nvramImageDirty
= true;
1314 OSData
*IODTNVRAM::unescapeBytesToData(UInt8
*bytes
, UInt32 length
)
1317 UInt32 totalLength
= 0;
1322 // Calculate the actual length of the data.
1325 for (cnt
= 0; cnt
< length
;) {
1326 byte
= bytes
[cnt
++];
1328 byte
= bytes
[cnt
++];
1336 totalLength
+= cnt2
;
1340 // Create an empty OSData of the correct size.
1341 data
= OSData::withCapacity(totalLength
);
1343 for (cnt
= 0; cnt
< length
;) {
1344 byte
= bytes
[cnt
++];
1346 byte
= bytes
[cnt
++];
1348 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1351 data
->appendByte(byte
, cnt2
);
1359 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1368 where
= (UInt8
*) value
->getBytesNoCopy();
1369 end
= where
+ value
->getLength();
1371 result
= OSData::withCapacity(end
- where
);
1375 while (where
< end
) {
1378 if ((byte
== 0x00) || (byte
== 0xFF)) {
1380 ((where
- start
) < 0x80) && (where
< end
) && (byte
== *where
);
1382 ok
&= result
->appendByte(0xff, 1);
1383 byte
= (byte
& 0x80) | (where
- start
);
1385 ok
&= result
->appendByte(byte
, 1);
1387 ok
&= result
->appendByte(0, 1);
1397 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1398 const OSSymbol
**name
,
1401 IOReturn err
= kIOReturnNoResources
;
1410 if (_ofDict
== 0) return err
;
1411 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1412 if (data
== 0) return err
;
1414 start
= (UInt8
*) data
->getBytesNoCopy();
1415 end
= start
+ data
->getLength();
1418 while (where
< end
) {
1425 else if (nvName
== 0)
1428 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1429 if (entry
== compareEntry
) {
1431 compareEntry
->release();
1432 *name
= OSSymbol::withCString((const char *) nvName
);
1433 *value
= unescapeBytesToData(start
, where
- start
- 1);
1434 if ((*name
!= 0) && (*value
!= 0))
1435 err
= kIOReturnSuccess
;
1437 err
= kIOReturnNoMemory
;
1441 compareEntry
->release();
1442 nvPath
= nvName
= 0;
1450 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1451 const OSSymbol
*propName
,
1467 if (_ofDict
== 0) return kIOReturnNoResources
;
1469 // copy over existing properties for other entries
1471 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1473 start
= (UInt8
*) oldData
->getBytesNoCopy();
1474 end
= start
+ oldData
->getLength();
1478 while (where
< end
) {
1484 else if (nvName
== 0)
1487 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1488 if (entry
== compareEntry
) {
1490 compareEntry
->release();
1491 // delete old property (nvPath -> where)
1492 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1494 ok
&= data
->appendBytes(where
, end
- where
);
1498 compareEntry
->release();
1499 nvPath
= nvName
= 0;
1506 // make the new property
1510 data
= OSData::withData(oldData
);
1512 data
= OSData::withCapacity(16);
1514 return kIOReturnNoMemory
;
1517 // get entries in path
1518 OSArray
*array
= OSArray::withCapacity(5);
1521 return kIOReturnNoMemory
;
1524 array
->setObject(entry
);
1525 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1528 for (int i
= array
->getCount() - 3;
1529 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1532 name
= entry
->getName(gIODTPlane
);
1533 comp
= entry
->getLocation(gIODTPlane
);
1534 if( comp
&& (0 == strcmp("pci", name
))
1535 && (0 == strcmp("80000000", comp
))) {
1537 comp
= "/pci@80000000";
1540 ok
&= data
->appendBytes("/@", 2);
1544 ok
&= data
->appendByte('/', 1);
1548 ok
&= data
->appendBytes(comp
, strlen(comp
));
1550 ok
&= data
->appendByte(0, 1);
1554 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1556 // append escaped data
1557 oldData
= escapeDataToData(value
);
1558 ok
&= (oldData
!= 0);
1560 ok
&= data
->appendBytes(oldData
);
1563 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1565 _ofImageDirty
= true;
1569 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;