2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IONVRAM.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOUserClient.h>
35 #include <IOKit/IOKitKeys.h>
37 #define super IOService
39 #define kIONVRAMPrivilege kIOClientPrivilegeAdministrator
40 //#define kIONVRAMPrivilege kIOClientPrivilegeLocalUser
43 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
);
45 bool IODTNVRAM::init(IORegistryEntry
*old
, const IORegistryPlane
*plane
)
49 if (!super::init(old
, plane
)) return false;
51 dict
= OSDictionary::withCapacity(1);
52 if (dict
== 0) return false;
53 setPropertyTable(dict
);
55 _nvramImage
= IONew(UInt8
, kIODTNVRAMImageSize
);
56 if (_nvramImage
== 0) return false;
58 _nvramPartitionOffsets
= OSDictionary::withCapacity(1);
59 if (_nvramPartitionOffsets
== 0) return false;
61 _nvramPartitionLengths
= OSDictionary::withCapacity(1);
62 if (_nvramPartitionLengths
== 0) return false;
64 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
65 if (_registryPropertiesKey
== 0) return false;
70 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
73 UInt32 partitionOffset
, partitionLength
;
74 UInt32 freePartitionOffset
, freePartitionSize
;
75 UInt32 currentLength
, currentOffset
= 0;
76 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
78 if (_nvramController
!= 0) return;
80 _nvramController
= nvram
;
82 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
84 // Find the offsets for the OF, XPRAM, NameRegistry and PanicInfo partitions.
85 _ofPartitionOffset
= 0xFFFFFFFF;
86 _xpramPartitionOffset
= 0xFFFFFFFF;
87 _nrPartitionOffset
= 0xFFFFFFFF;
88 _piPartitionOffset
= 0xFFFFFFFF;
89 freePartitionOffset
= 0xFFFFFFFF;
90 freePartitionSize
= 0;
91 if (getPlatform()->getBootROMType()) {
92 // Look through the partitions to find the OF, MacOS partitions.
93 while (currentOffset
< kIODTNVRAMImageSize
) {
94 currentLength
= ((UInt16
*)(_nvramImage
+ currentOffset
))[1] * 16;
96 partitionOffset
= currentOffset
+ 16;
97 partitionLength
= currentLength
- 16;
99 if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
100 kIODTNVRAMOFPartitionName
, 12) == 0) {
101 _ofPartitionOffset
= partitionOffset
;
102 _ofPartitionSize
= partitionLength
;
103 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
104 kIODTNVRAMXPRAMPartitionName
, 12) == 0) {
105 _xpramPartitionOffset
= partitionOffset
;
106 _xpramPartitionSize
= kIODTNVRAMXPRAMSize
;
107 _nrPartitionOffset
= _xpramPartitionOffset
+ _xpramPartitionSize
;
108 _nrPartitionSize
= partitionLength
- _xpramPartitionSize
;
109 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
110 kIODTNVRAMPanicInfoPartitonName
, 12) == 0) {
111 _piPartitionOffset
= partitionOffset
;
112 _piPartitionSize
= partitionLength
;
113 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
114 kIODTNVRAMFreePartitionName
, 12) == 0) {
115 freePartitionOffset
= currentOffset
;
116 freePartitionSize
= currentLength
;
118 // Construct the partition ID from the signature and name.
119 sprintf(partitionID
, "0x%02x,",
120 *(UInt8
*)(_nvramImage
+ currentOffset
));
121 strncpy(partitionID
+ 5,
122 (const char *)(_nvramImage
+ currentOffset
+ 4), 12);
123 partitionID
[17] = '\0';
125 partitionOffsetNumber
= OSNumber::withNumber(partitionOffset
, 32);
126 partitionLengthNumber
= OSNumber::withNumber(partitionLength
, 32);
128 // Save the partition offset and length
129 _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
);
130 _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
);
132 partitionOffsetNumber
->release();
133 partitionLengthNumber
->release();
135 currentOffset
+= currentLength
;
138 // Use the fixed address for old world machines.
139 _ofPartitionOffset
= 0x1800;
140 _ofPartitionSize
= 0x0800;
141 _xpramPartitionOffset
= 0x1300;
142 _xpramPartitionSize
= 0x0100;
143 _nrPartitionOffset
= 0x1400;
144 _nrPartitionSize
= 0x0400;
147 if (_ofPartitionOffset
!= 0xFFFFFFFF)
148 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
149 if (_xpramPartitionOffset
!= 0xFFFFFFFF)
150 _xpramImage
= _nvramImage
+ _xpramPartitionOffset
;
151 if (_nrPartitionOffset
!= 0xFFFFFFFF)
152 _nrImage
= _nvramImage
+ _nrPartitionOffset
;
154 if (_piPartitionOffset
== 0xFFFFFFFF) {
155 if (freePartitionSize
> 0x20) {
156 // Set the signature to 0xa1.
157 _nvramImage
[freePartitionOffset
] = 0xa1;
158 // Set the checksum to 0.
159 _nvramImage
[freePartitionOffset
+ 1] = 0;
160 // Set the name for the Panic Info partition.
161 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
162 kIODTNVRAMPanicInfoPartitonName
, 12);
164 // Calculate the partition offset and size.
165 _piPartitionOffset
= freePartitionOffset
+ 0x10;
166 _piPartitionSize
= 0x800;
167 if (_piPartitionSize
+ 0x20 > freePartitionSize
)
168 _piPartitionSize
= freePartitionSize
- 0x20;
170 _piImage
= _nvramImage
+ _piPartitionOffset
;
172 // Zero the new partition.
173 bzero(_piImage
, _piPartitionSize
);
175 // Set the partition size.
176 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
177 (_piPartitionSize
/ 0x10) + 1;
179 // Set the partition checksum.
180 _nvramImage
[freePartitionOffset
+ 1] =
181 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
183 // Calculate the free partition offset and size.
184 freePartitionOffset
+= _piPartitionSize
+ 0x10;
185 freePartitionSize
-= _piPartitionSize
+ 0x10;
187 // Set the signature to 0x7f.
188 _nvramImage
[freePartitionOffset
] = 0x7f;
189 // Set the checksum to 0.
190 _nvramImage
[freePartitionOffset
+ 1] = 0;
191 // Set the name for the free partition.
192 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
193 kIODTNVRAMFreePartitionName
, 12);
194 // Set the partition size.
195 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
196 freePartitionSize
/ 0x10;
197 // Set the partition checksum.
198 _nvramImage
[freePartitionOffset
+ 1] =
199 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
201 // Set the nvram image as dirty.
202 _nvramImageDirty
= true;
205 _piImage
= _nvramImage
+ _piPartitionOffset
;
211 void IODTNVRAM::sync(void)
213 if (!_nvramImageDirty
&& !_ofImageDirty
) return;
215 // Don't try to sync OF Variables if the system has already paniced.
216 if (!_systemPaniced
) syncOFVariables();
218 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
219 _nvramController
->sync();
221 _nvramImageDirty
= false;
224 bool IODTNVRAM::serializeProperties(OSSerialize
*s
) const
229 OSDictionary
*dict
, *tmpDict
= 0;
230 OSCollectionIterator
*iter
= 0;
232 if (_ofDict
== 0) return false;
234 // Verify permissions.
235 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
236 if (result
!= kIOReturnSuccess
) {
237 tmpDict
= OSDictionary::withCapacity(1);
238 if (tmpDict
== 0) return false;
240 iter
= OSCollectionIterator::withCollection(_ofDict
);
241 if (iter
== 0) return false;
244 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
247 variablePerm
= getOFVariablePerm(key
);
248 if (variablePerm
!= kOFVariablePermRootOnly
) {
249 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
257 result
= dict
->serialize(s
);
259 if (tmpDict
!= 0) tmpDict
->release();
260 if (iter
!= 0) iter
->release();
265 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
270 if (_ofDict
== 0) return 0;
272 // Verify permissions.
273 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
274 if (result
!= kIOReturnSuccess
) {
275 variablePerm
= getOFVariablePerm(aKey
);
276 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
279 return _ofDict
->getObject(aKey
);
282 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
284 const OSSymbol
*keySymbol
;
285 OSObject
*theObject
= 0;
287 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
288 if (keySymbol
!= 0) {
289 theObject
= getProperty(keySymbol
);
290 keySymbol
->release();
296 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
299 UInt32 propType
, propPerm
;
301 OSObject
*propObject
= 0;
303 if (_ofDict
== 0) return false;
305 // Verify permissions.
306 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
307 if (result
!= kIOReturnSuccess
) {
308 propPerm
= getOFVariablePerm(aKey
);
309 if (propPerm
!= kOFVariablePermUserWrite
) return false;
312 // Don't allow creation of new properties on old world machines.
313 if (getPlatform()->getBootROMType() == 0) {
314 if (_ofDict
->getObject(aKey
) == 0) return false;
317 // Don't allow change of 'aapl,panic-info'.
318 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return false;
320 // Make sure the object is of the correct type.
321 propType
= getOFVariableType(aKey
);
323 case kOFVariableTypeBoolean
:
324 propObject
= OSDynamicCast(OSBoolean
, anObject
);
327 case kOFVariableTypeNumber
:
328 propObject
= OSDynamicCast(OSNumber
, anObject
);
331 case kOFVariableTypeString
:
332 propObject
= OSDynamicCast(OSString
, anObject
);
335 case kOFVariableTypeData
:
336 propObject
= OSDynamicCast(OSData
, anObject
);
337 if (propObject
== 0) {
338 tmpString
= OSDynamicCast(OSString
, anObject
);
339 if (tmpString
!= 0) {
340 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
341 tmpString
->getLength());
347 if (propObject
== 0) return false;
349 result
= _ofDict
->setObject(aKey
, propObject
);
352 if (getPlatform()->getBootROMType() == 0) {
353 updateOWBootArgs(aKey
, propObject
);
356 _ofImageDirty
= true;
362 void IODTNVRAM::removeProperty(const OSSymbol
*aKey
)
367 if (_ofDict
== 0) return;
369 // Verify permissions.
370 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
371 if (result
!= kIOReturnSuccess
) {
372 propPerm
= getOFVariablePerm(aKey
);
373 if (propPerm
!= kOFVariablePermUserWrite
) return;
376 // Don't allow removal of properties on old world machines.
377 if (getPlatform()->getBootROMType() == 0) return;
379 // Don't allow change of 'aapl,panic-info'.
380 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return;
382 // If the object exists, remove it from the dictionary.
383 result
= _ofDict
->getObject(aKey
) != 0;
385 _ofDict
->removeObject(aKey
);
387 _ofImageDirty
= true;
391 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
396 const OSString
*tmpStr
;
398 OSCollectionIterator
*iter
;
400 dict
= OSDynamicCast(OSDictionary
, properties
);
401 if (dict
== 0) return kIOReturnBadArgument
;
403 iter
= OSCollectionIterator::withCollection(dict
);
404 if (iter
== 0) return kIOReturnBadArgument
;
407 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
410 object
= dict
->getObject(key
);
411 if (object
== 0) continue;
413 if (key
->isEqualTo(kIONVRAMDeletePropertyKey
)) {
414 tmpStr
= OSDynamicCast(OSString
, object
);
416 key
= OSSymbol::withString(tmpStr
);
424 result
= setProperty(key
, object
);
430 if (result
) return kIOReturnSuccess
;
431 else return kIOReturnError
;
434 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
437 if (_xpramImage
== 0) return kIOReturnUnsupported
;
439 if ((buffer
== 0) || (length
== 0) ||
440 (offset
+ length
> kIODTNVRAMXPRAMSize
))
441 return kIOReturnBadArgument
;
443 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
445 return kIOReturnSuccess
;
448 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
451 if (_xpramImage
== 0) return kIOReturnUnsupported
;
453 if ((buffer
== 0) || (length
== 0) ||
454 (offset
+ length
> kIODTNVRAMXPRAMSize
))
455 return kIOReturnBadArgument
;
457 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
459 _nvramImageDirty
= true;
461 return kIOReturnSuccess
;
464 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
465 const OSSymbol
**name
,
470 if (getPlatform()->getBootROMType())
471 err
= readNVRAMPropertyType1(entry
, name
, value
);
473 err
= readNVRAMPropertyType0(entry
, name
, value
);
478 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
479 const OSSymbol
*name
,
484 if (getPlatform()->getBootROMType())
485 err
= writeNVRAMPropertyType1(entry
, name
, value
);
487 err
= writeNVRAMPropertyType0(entry
, name
, value
);
492 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
494 return _nvramPartitionLengths
;
497 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
498 IOByteCount offset
, UInt8
*buffer
,
501 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
502 UInt32 partitionOffset
, partitionLength
;
504 partitionOffsetNumber
=
505 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
506 partitionLengthNumber
=
507 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
509 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
510 return kIOReturnNotFound
;
512 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
513 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
515 if ((buffer
== 0) || (length
== 0) ||
516 (offset
+ length
> partitionLength
))
517 return kIOReturnBadArgument
;
519 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
521 return kIOReturnSuccess
;
524 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
525 IOByteCount offset
, UInt8
*buffer
,
528 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
529 UInt32 partitionOffset
, partitionLength
;
531 partitionOffsetNumber
=
532 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
533 partitionLengthNumber
=
534 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
536 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
537 return kIOReturnNotFound
;
539 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
540 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
542 if ((buffer
== 0) || (length
== 0) ||
543 (offset
+ length
> partitionLength
))
544 return kIOReturnBadArgument
;
546 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
548 _nvramImageDirty
= true;
550 return kIOReturnSuccess
;
553 UInt32
IODTNVRAM::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
555 if ((_piImage
== 0) || (length
<= 0)) return 0;
557 if (length
> (_piPartitionSize
- 4))
558 length
= _piPartitionSize
- 4;
560 // Save the Panic Info.
561 bcopy(buffer
, _piImage
+ 4, length
);
563 // Save the Panic Info length.
564 *(UInt32
*)_piImage
= length
;
566 _nvramImageDirty
= true;
568 _systemPaniced
= true;
575 UInt8
IODTNVRAM::calculatePartitionChecksum(UInt8
*partitionHeader
)
577 UInt8 cnt
, isum
, csum
= 0;
579 for (cnt
= 0; cnt
< 0x10; cnt
++) {
580 isum
= csum
+ partitionHeader
[cnt
];
581 if (isum
< csum
) isum
++;
588 struct OWVariablesHeader
{
603 typedef struct OWVariablesHeader OWVariablesHeader
;
605 IOReturn
IODTNVRAM::initOFVariables(void)
607 UInt32 cnt
, propOffset
, propType
;
608 UInt8
*propName
, *propData
;
609 UInt32 propNameLength
, propDataLength
;
610 const OSSymbol
*propSymbol
;
611 OSObject
*propObject
;
612 OWVariablesHeader
*owHeader
;
614 if (_ofImage
== 0) return kIOReturnNotReady
;
616 _ofDict
= OSDictionary::withCapacity(1);
617 if (_ofDict
== 0) return kIOReturnNoMemory
;
619 if (getPlatform()->getBootROMType()) {
621 while (cnt
< _ofPartitionSize
) {
622 // Break if there is no name.
623 if (_ofImage
[cnt
] == '\0') break;
625 // Find the length of the name.
626 propName
= _ofImage
+ cnt
;
627 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
629 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
632 // Break if the name goes past the end of the partition.
633 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
634 cnt
+= propNameLength
+ 1;
636 propData
= _ofImage
+ cnt
;
637 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
639 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
642 // Break if the data goes past the end of the partition.
643 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
644 cnt
+= propDataLength
+ 1;
646 if (convertPropToObject(propName
, propNameLength
,
647 propData
, propDataLength
,
648 &propSymbol
, &propObject
)) {
649 _ofDict
->setObject(propSymbol
, propObject
);
650 propSymbol
->release();
651 propObject
->release();
655 // Create the boot-args property if it is not in the dictionary.
656 if (_ofDict
->getObject("boot-args") == 0) {
657 propObject
= OSString::withCStringNoCopy("");
658 if (propObject
!= 0) {
659 _ofDict
->setObject("boot-args", propObject
);
660 propObject
->release();
664 // Create the 'aapl,panic-info' property if needed.
666 propDataLength
= *(UInt32
*)_piImage
;
667 if ((propDataLength
!= 0) && (propDataLength
< (_piPartitionSize
- 4))) {
668 propObject
= OSData::withBytes(_piImage
+ 4, propDataLength
);
669 _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
);
670 propObject
->release();
672 // Clear the length from _piImage and mark dirty.
673 *(UInt32
*)_piImage
= 0;
674 _nvramImageDirty
= true;
678 owHeader
= (OWVariablesHeader
*)_ofImage
;
679 if (!validateOWChecksum(_ofImage
)) {
682 return kIOReturnBadMedia
;
687 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
691 case kOFVariableTypeBoolean
:
692 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
695 case kOFVariableTypeNumber
:
696 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
699 case kOFVariableTypeString
:
700 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
702 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
703 propName
= IONew(UInt8
, propDataLength
+ 1);
705 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
706 propName
[propDataLength
] = '\0';
707 propObject
= OSString::withCString((const char *)propName
);
708 IODelete(propName
, UInt8
, propDataLength
+ 1);
713 if (propObject
== 0) break;
715 _ofDict
->setObject(propSymbol
, propObject
);
716 propSymbol
->release();
717 propObject
->release();
720 // Create the boot-args property.
721 propSymbol
= OSSymbol::withCString("boot-command");
722 if (propSymbol
!= 0) {
723 propObject
= _ofDict
->getObject(propSymbol
);
724 if (propObject
!= 0) {
725 updateOWBootArgs(propSymbol
, propObject
);
727 propSymbol
->release();
731 return kIOReturnSuccess
;
734 IOReturn
IODTNVRAM::syncOFVariables(void)
737 UInt32 cnt
, length
, maxLength
;
738 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
739 UInt8
*buffer
, *tmpBuffer
;
740 const UInt8
*tmpData
;
741 const OSSymbol
*tmpSymbol
;
743 OSBoolean
*tmpBoolean
;
746 OSCollectionIterator
*iter
;
747 OWVariablesHeader
*owHeader
, *owHeaderOld
;
749 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
751 if (!_ofImageDirty
) return kIOReturnSuccess
;
753 if (getPlatform()->getBootROMType()) {
754 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
755 if (buffer
== 0) return kIOReturnNoMemory
;
756 bzero(buffer
, _ofPartitionSize
);
759 maxLength
= _ofPartitionSize
;
761 iter
= OSCollectionIterator::withCollection(_ofDict
);
762 if (iter
== 0) ok
= false;
765 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
766 if (tmpSymbol
== 0) break;
768 // Don't save 'aapl,panic-info'.
769 if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue;
771 tmpObject
= _ofDict
->getObject(tmpSymbol
);
774 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
783 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
786 IODelete(buffer
, UInt8
, _ofPartitionSize
);
788 if (!ok
) return kIOReturnBadArgument
;
790 buffer
= IONew(UInt8
, _ofPartitionSize
);
791 if (buffer
== 0) return kIOReturnNoMemory
;
792 bzero(buffer
, _ofPartitionSize
);
794 owHeader
= (OWVariablesHeader
*)buffer
;
795 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
797 owHeader
->owMagic
= owHeaderOld
->owMagic
;
798 owHeader
->owVersion
= owHeaderOld
->owVersion
;
799 owHeader
->owPages
= owHeaderOld
->owPages
;
801 curOffset
= _ofPartitionSize
;
806 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
809 tmpObject
= _ofDict
->getObject(tmpSymbol
);
812 case kOFVariableTypeBoolean
:
813 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
814 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
817 case kOFVariableTypeNumber
:
818 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
819 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
822 case kOFVariableTypeString
:
823 tmpString
= OSDynamicCast(OSString
, tmpObject
);
824 tmpData
= (const UInt8
*)tmpString
->getCStringNoCopy();
825 tmpDataLength
= tmpString
->getLength();
827 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
832 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
833 curOffset
-= tmpDataLength
;
834 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
835 if (tmpDataLength
!= 0)
836 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
842 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
843 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
844 owHeader
->owNext
= 0;
846 owHeader
->owChecksum
= 0;
847 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
849 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
852 IODelete(buffer
, UInt8
, _ofPartitionSize
);
854 if (!ok
) return kIOReturnBadArgument
;
857 _ofImageDirty
= false;
858 _nvramImageDirty
= true;
860 return kIOReturnSuccess
;
864 const char *variableName
;
867 SInt32 variableOffset
;
869 typedef struct OFVariable OFVariable
;
872 kOWVariableOffsetNumber
= 8,
873 kOWVariableOffsetString
= 17
876 OFVariable gOFVariables
[] = {
877 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
878 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
879 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
880 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
881 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
882 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
883 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
884 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
885 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
886 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
887 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
888 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
889 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
890 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
891 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
892 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
893 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
894 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
895 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
896 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
897 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
898 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
899 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
900 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
901 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
902 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
903 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
904 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
905 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
906 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
907 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
908 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
909 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
910 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
911 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
912 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
913 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
914 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
915 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
916 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
917 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
918 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
919 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
920 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
921 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
922 {"boot-image", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
923 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
926 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
930 ofVar
= gOFVariables
;
932 if ((ofVar
->variableName
== 0) ||
933 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
937 return ofVar
->variableType
;
940 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
944 ofVar
= gOFVariables
;
946 if ((ofVar
->variableName
== 0) ||
947 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
951 return ofVar
->variablePerm
;
954 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
955 UInt32
*propType
, UInt32
*propOffset
)
959 ofVar
= gOFVariables
;
961 if (ofVar
->variableName
== 0) return false;
963 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
968 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
969 *propType
= ofVar
->variableType
;
972 case kOFVariableTypeBoolean
:
973 *propOffset
= 1 << (31 - variableNumber
);
976 case kOFVariableTypeNumber
:
977 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
980 case kOFVariableTypeString
:
981 *propOffset
= variableNumber
- kOWVariableOffsetString
;
988 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
989 UInt8
*propData
, UInt32 propDataLength
,
990 const OSSymbol
**propSymbol
,
991 OSObject
**propObject
)
994 const OSSymbol
*tmpSymbol
;
999 // Create the symbol.
1000 propName
[propNameLength
] = '\0';
1001 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
1002 propName
[propNameLength
] = '=';
1003 if (tmpSymbol
== 0) {
1007 propType
= getOFVariableType(tmpSymbol
);
1009 // Create the object.
1012 case kOFVariableTypeBoolean
:
1013 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
1014 tmpObject
= kOSBooleanTrue
;
1015 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
1016 tmpObject
= kOSBooleanFalse
;
1020 case kOFVariableTypeNumber
:
1021 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
1022 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
1025 case kOFVariableTypeString
:
1026 tmpString
= OSString::withCString((const char *)propData
);
1027 if (tmpString
!= 0) tmpObject
= tmpString
;
1030 case kOFVariableTypeData
:
1031 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
1035 if (tmpObject
== 0) {
1036 tmpSymbol
->release();
1040 *propSymbol
= tmpSymbol
;
1041 *propObject
= tmpObject
;
1046 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
1047 const OSSymbol
*propSymbol
, OSObject
*propObject
)
1049 const UInt8
*propName
;
1050 UInt32 propNameLength
, propDataLength
;
1051 UInt32 propType
, tmpValue
;
1052 OSBoolean
*tmpBoolean
= 0;
1053 OSNumber
*tmpNumber
= 0;
1054 OSString
*tmpString
= 0;
1055 OSData
*tmpData
= 0;
1057 propName
= (const UInt8
*)propSymbol
->getCStringNoCopy();
1058 propNameLength
= propSymbol
->getLength();
1059 propType
= getOFVariableType(propSymbol
);
1061 // Get the size of the data.
1062 propDataLength
= 0xFFFFFFFF;
1064 case kOFVariableTypeBoolean
:
1065 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
1066 if (tmpBoolean
!= 0) propDataLength
= 5;
1069 case kOFVariableTypeNumber
:
1070 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
1071 if (tmpNumber
!= 0) propDataLength
= 10;
1074 case kOFVariableTypeString
:
1075 tmpString
= OSDynamicCast(OSString
, propObject
);
1076 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
1079 case kOFVariableTypeData
:
1080 tmpData
= OSDynamicCast(OSData
, propObject
);
1082 tmpData
= escapeDataToData(tmpData
);
1083 propDataLength
= tmpData
->getLength();
1088 // Make sure the propertySize is known and will fit.
1089 if (propDataLength
== 0xFFFFFFFF) return false;
1090 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
1092 // Copy the property name equal sign.
1093 sprintf((char *)buffer
, "%s=", propName
);
1094 buffer
+= propNameLength
+ 1;
1097 case kOFVariableTypeBoolean
:
1098 if (tmpBoolean
->getValue()) {
1099 strcpy((char *)buffer
, "true");
1101 strcpy((char *)buffer
, "false");
1105 case kOFVariableTypeNumber
:
1106 tmpValue
= tmpNumber
->unsigned32BitValue();
1107 if (tmpValue
== 0xFFFFFFFF) {
1108 strcpy((char *)buffer
, "-1");
1109 } else if (tmpValue
< 1000) {
1110 sprintf((char *)buffer
, "%ld", tmpValue
);
1112 sprintf((char *)buffer
, "0x%lx", tmpValue
);
1116 case kOFVariableTypeString
:
1117 strcpy((char *)buffer
, tmpString
->getCStringNoCopy());
1120 case kOFVariableTypeData
:
1121 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
1126 propDataLength
= strlen((const char *)buffer
);
1128 *length
= propNameLength
+ propDataLength
+ 2;
1134 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
1136 UInt32 cnt
, checksum
= 0;
1137 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1139 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1140 checksum
+= tmpBuffer
[cnt
];
1142 return checksum
% 0x0000FFFF;
1145 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
1147 UInt32 cnt
, checksum
, sum
= 0;
1148 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1150 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1151 sum
+= tmpBuffer
[cnt
];
1153 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
1154 if (checksum
== 0x10000) checksum
--;
1155 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
1157 return checksum
== 0;
1160 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
1162 bool wasBootArgs
, bootr
= false;
1164 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
1165 const UInt8
*bootCommandData
, *bootArgsData
;
1167 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
1169 tmpString
= OSDynamicCast(OSString
, value
);
1170 if (tmpString
== 0) return;
1172 if (key
->isEqualTo("boot-command")) {
1173 wasBootArgs
= false;
1174 bootCommand
= tmpString
;
1175 } else if (key
->isEqualTo("boot-args")) {
1177 bootArgs
= tmpString
;
1178 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1179 if (bootCommand
== 0) return;
1182 bootCommandData
= (const UInt8
*)bootCommand
->getCStringNoCopy();
1183 bootCommandDataLength
= bootCommand
->getLength();
1185 if (bootCommandData
== 0) return;
1187 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1188 if ((bootCommandData
[cnt
] == 'b') &&
1189 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1191 while (bootCommandData
[cnt
] == ' ') cnt
++;
1197 _ofDict
->removeObject("boot-args");
1202 bootArgsData
= (const UInt8
*)bootArgs
->getCStringNoCopy();
1203 bootArgsDataLength
= bootArgs
->getLength();
1204 if (bootArgsData
== 0) return;
1206 tmpDataLength
= cnt
+ bootArgsDataLength
;
1207 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1208 if (tmpData
== 0) return;
1210 strncpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1211 tmpData
[cnt
] = '\0';
1212 strcat((char *)tmpData
, (const char *)bootArgsData
);
1214 bootCommand
= OSString::withCString((const char *)tmpData
);
1215 if (bootCommand
!= 0) {
1216 _ofDict
->setObject("boot-command", bootCommand
);
1217 bootCommand
->release();
1220 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1222 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1223 if (bootArgs
!= 0) {
1224 _ofDict
->setObject("boot-args", bootArgs
);
1225 bootArgs
->release();
1231 // Private methods for Name Registry access.
1234 kMaxNVNameLength
= 4,
1235 kMaxNVDataLength
= 8
1238 #pragma options align=mac68k
1239 struct NVRAMProperty
1241 IONVRAMDescriptor header
;
1243 UInt8 name
[ kMaxNVNameLength
];
1245 UInt8 data
[ kMaxNVDataLength
];
1247 #pragma options align=reset
1249 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1254 nvEnd
= *((UInt16
*)_nrImage
);
1255 if(getPlatform()->getBootROMType()) {
1256 // on NewWorld, offset to partition start
1259 // on old world, absolute
1260 nvEnd
-= _nrPartitionOffset
;
1262 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1266 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1267 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1271 offset
+= sizeof(NVRAMProperty
);
1274 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1282 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1283 const OSSymbol
**name
,
1286 IONVRAMDescriptor hdr
;
1287 NVRAMProperty
*prop
;
1291 char nameBuf
[kMaxNVNameLength
+ 1];
1293 if (_nrImage
== 0) return kIOReturnUnsupported
;
1294 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1296 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1297 if (err
!= kIOReturnSuccess
) return err
;
1299 if (searchNVRAMProperty(&hdr
, &offset
)) {
1300 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1302 length
= prop
->nameLength
;
1303 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1304 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1305 nameBuf
[length
] = 0;
1306 *name
= OSSymbol::withCString(nameBuf
);
1308 length
= prop
->dataLength
;
1309 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1310 *value
= OSData::withBytes(prop
->data
, length
);
1312 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1313 else return kIOReturnNoMemory
;
1316 return kIOReturnNoResources
;
1319 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1320 const OSSymbol
*name
,
1323 IONVRAMDescriptor hdr
;
1324 NVRAMProperty
*prop
;
1325 IOByteCount nameLength
;
1326 IOByteCount dataLength
;
1332 if (_nrImage
== 0) return kIOReturnUnsupported
;
1333 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1335 nameLength
= name
->getLength();
1336 dataLength
= value
->getLength();
1337 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1338 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1340 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1341 if (err
!= kIOReturnSuccess
) return err
;
1343 exists
= searchNVRAMProperty(&hdr
, &offset
);
1344 if (offset
== 0) return kIOReturnNoMemory
;
1346 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1347 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1349 prop
->nameLength
= nameLength
;
1350 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1351 prop
->dataLength
= dataLength
;
1352 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1355 nvLength
= offset
+ sizeof(NVRAMProperty
);
1356 if (getPlatform()->getBootROMType())
1359 nvLength
+= _nrPartitionOffset
;
1360 *((UInt16
*)_nrImage
) = nvLength
;
1363 _nvramImageDirty
= true;
1368 OSData
*IODTNVRAM::unescapeBytesToData(const UInt8
*bytes
, UInt32 length
)
1371 UInt32 totalLength
= 0;
1376 // Calculate the actual length of the data.
1379 for (cnt
= 0; cnt
< length
;) {
1380 byte
= bytes
[cnt
++];
1382 byte
= bytes
[cnt
++];
1390 totalLength
+= cnt2
;
1394 // Create an empty OSData of the correct size.
1395 data
= OSData::withCapacity(totalLength
);
1397 for (cnt
= 0; cnt
< length
;) {
1398 byte
= bytes
[cnt
++];
1400 byte
= bytes
[cnt
++];
1402 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1405 data
->appendByte(byte
, cnt2
);
1413 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1416 const UInt8
* startPtr
;
1417 const UInt8
* endPtr
;
1418 const UInt8
* wherePtr
;
1422 wherePtr
= (const UInt8
*) value
->getBytesNoCopy();
1423 endPtr
= wherePtr
+ value
->getLength();
1425 result
= OSData::withCapacity(endPtr
- wherePtr
);
1429 while (wherePtr
< endPtr
) {
1430 startPtr
= wherePtr
;
1432 if ((byte
== 0x00) || (byte
== 0xFF)) {
1434 ((wherePtr
- startPtr
) < 0x80) && (wherePtr
< endPtr
) && (byte
== *wherePtr
);
1436 ok
&= result
->appendByte(0xff, 1);
1437 byte
= (byte
& 0x80) | (wherePtr
- startPtr
);
1439 ok
&= result
->appendByte(byte
, 1);
1441 ok
&= result
->appendByte(0, 1);
1451 static bool IsApplePropertyName(const char * propName
)
1454 while ((c
= *propName
++)) {
1455 if ((c
>= 'A') && (c
<= 'Z'))
1462 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1463 const OSSymbol
**name
,
1466 IOReturn err
= kIOReturnNoResources
;
1468 const UInt8
*startPtr
;
1469 const UInt8
*endPtr
;
1470 const UInt8
*wherePtr
;
1471 const UInt8
*nvPath
= 0;
1472 const char *nvName
= 0;
1473 const char *resultName
= 0;
1474 const UInt8
*resultValue
= 0;
1475 UInt32 resultValueLen
= 0;
1478 if (_ofDict
== 0) return err
;
1479 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1480 if (data
== 0) return err
;
1482 startPtr
= (const UInt8
*) data
->getBytesNoCopy();
1483 endPtr
= startPtr
+ data
->getLength();
1485 wherePtr
= startPtr
;
1486 while (wherePtr
< endPtr
) {
1487 byte
= *(wherePtr
++);
1493 else if (nvName
== 0)
1494 nvName
= (const char *) startPtr
;
1496 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1498 compareEntry
->release();
1499 if (entry
== compareEntry
) {
1500 bool appleProp
= IsApplePropertyName(nvName
);
1501 if (!appleProp
|| !resultName
) {
1502 resultName
= nvName
;
1503 resultValue
= startPtr
;
1504 resultValueLen
= wherePtr
- startPtr
- 1;
1512 startPtr
= wherePtr
;
1515 *name
= OSSymbol::withCString(resultName
);
1516 *value
= unescapeBytesToData(resultValue
, resultValueLen
);
1517 if ((*name
!= 0) && (*value
!= 0))
1518 err
= kIOReturnSuccess
;
1520 err
= kIOReturnNoMemory
;
1525 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1526 const OSSymbol
*propName
,
1531 const UInt8
*startPtr
;
1532 const UInt8
*propStart
;
1533 const UInt8
*endPtr
;
1534 const UInt8
*wherePtr
;
1535 const UInt8
*nvPath
= 0;
1536 const char *nvName
= 0;
1541 bool settingAppleProp
;
1543 if (_ofDict
== 0) return kIOReturnNoResources
;
1545 settingAppleProp
= IsApplePropertyName(propName
->getCStringNoCopy());
1547 // copy over existing properties for other entries
1549 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1551 startPtr
= (const UInt8
*) oldData
->getBytesNoCopy();
1552 endPtr
= startPtr
+ oldData
->getLength();
1554 propStart
= startPtr
;
1555 wherePtr
= startPtr
;
1556 while (wherePtr
< endPtr
) {
1557 byte
= *(wherePtr
++);
1562 else if (nvName
== 0)
1563 nvName
= (const char *) startPtr
;
1565 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1567 compareEntry
->release();
1568 if (entry
== compareEntry
) {
1569 if ((settingAppleProp
&& propName
->isEqualTo(nvName
))
1570 || (!settingAppleProp
&& !IsApplePropertyName(nvName
))) {
1571 // delete old property (nvPath -> wherePtr)
1572 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1574 ok
&= data
->appendBytes(wherePtr
, endPtr
- wherePtr
);
1582 startPtr
= wherePtr
;
1586 // make the new property
1590 data
= OSData::withData(oldData
);
1592 data
= OSData::withCapacity(16);
1594 return kIOReturnNoMemory
;
1597 if (value
&& value
->getLength()) {
1598 // get entries in path
1599 OSArray
*array
= OSArray::withCapacity(5);
1602 return kIOReturnNoMemory
;
1605 array
->setObject(entry
);
1606 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1609 for (int i
= array
->getCount() - 3;
1610 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1613 name
= entry
->getName(gIODTPlane
);
1614 comp
= entry
->getLocation(gIODTPlane
);
1615 if( comp
&& (0 == strcmp("pci", name
))
1616 && (0 == strcmp("80000000", comp
))) {
1618 comp
= "/pci@80000000";
1621 ok
&= data
->appendBytes("/@", 2);
1625 ok
&= data
->appendByte('/', 1);
1629 ok
&= data
->appendBytes(comp
, strlen(comp
));
1631 ok
&= data
->appendByte(0, 1);
1635 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1637 // append escaped data
1638 oldData
= escapeDataToData(value
);
1639 ok
&= (oldData
!= 0);
1641 ok
&= data
->appendBytes(oldData
);
1644 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1646 _ofImageDirty
= true;
1650 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;