2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <IOKit/IOLib.h>
25 #include <IOKit/IONVRAM.h>
26 #include <IOKit/IOPlatformExpert.h>
27 #include <IOKit/IOUserClient.h>
28 #include <IOKit/IOKitKeys.h>
30 #define super IOService
32 #define kIONVRAMPrivilege kIOClientPrivilegeAdministrator
33 //#define kIONVRAMPrivilege kIOClientPrivilegeLocalUser
36 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
);
38 bool IODTNVRAM::init(IORegistryEntry
*old
, const IORegistryPlane
*plane
)
42 if (!super::init(old
, plane
)) return false;
44 dict
= OSDictionary::withCapacity(1);
45 if (dict
== 0) return false;
46 setPropertyTable(dict
);
48 _nvramImage
= IONew(UInt8
, kIODTNVRAMImageSize
);
49 if (_nvramImage
== 0) return false;
51 _nvramPartitionOffsets
= OSDictionary::withCapacity(1);
52 if (_nvramPartitionOffsets
== 0) return false;
54 _nvramPartitionLengths
= OSDictionary::withCapacity(1);
55 if (_nvramPartitionLengths
== 0) return false;
57 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
58 if (_registryPropertiesKey
== 0) return false;
63 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
66 UInt32 partitionOffset
, partitionLength
;
67 UInt32 freePartitionOffset
, freePartitionSize
;
68 UInt32 currentLength
, currentOffset
= 0;
69 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
71 if (_nvramController
!= 0) return;
73 _nvramController
= nvram
;
75 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
77 // Find the offsets for the OF, XPRAM, NameRegistry and PanicInfo partitions.
78 _ofPartitionOffset
= 0xFFFFFFFF;
79 _xpramPartitionOffset
= 0xFFFFFFFF;
80 _nrPartitionOffset
= 0xFFFFFFFF;
81 _piPartitionOffset
= 0xFFFFFFFF;
82 freePartitionOffset
= 0xFFFFFFFF;
83 freePartitionSize
= 0;
84 if (getPlatform()->getBootROMType()) {
85 // Look through the partitions to find the OF, MacOS partitions.
86 while (currentOffset
< kIODTNVRAMImageSize
) {
87 currentLength
= ((UInt16
*)(_nvramImage
+ currentOffset
))[1] * 16;
89 partitionOffset
= currentOffset
+ 16;
90 partitionLength
= currentLength
- 16;
92 if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
93 kIODTNVRAMOFPartitionName
, 12) == 0) {
94 _ofPartitionOffset
= partitionOffset
;
95 _ofPartitionSize
= partitionLength
;
96 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
97 kIODTNVRAMXPRAMPartitionName
, 12) == 0) {
98 _xpramPartitionOffset
= partitionOffset
;
99 _xpramPartitionSize
= kIODTNVRAMXPRAMSize
;
100 _nrPartitionOffset
= _xpramPartitionOffset
+ _xpramPartitionSize
;
101 _nrPartitionSize
= partitionLength
- _xpramPartitionSize
;
102 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
103 kIODTNVRAMPanicInfoPartitonName
, 12) == 0) {
104 _piPartitionOffset
= partitionOffset
;
105 _piPartitionSize
= partitionLength
;
106 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
107 kIODTNVRAMFreePartitionName
, 12) == 0) {
108 freePartitionOffset
= currentOffset
;
109 freePartitionSize
= currentLength
;
111 // Construct the partition ID from the signature and name.
112 sprintf(partitionID
, "0x%02x,",
113 *(UInt8
*)(_nvramImage
+ currentOffset
));
114 strncpy(partitionID
+ 5,
115 (const char *)(_nvramImage
+ currentOffset
+ 4), 12);
116 partitionID
[17] = '\0';
118 partitionOffsetNumber
= OSNumber::withNumber(partitionOffset
, 32);
119 partitionLengthNumber
= OSNumber::withNumber(partitionLength
, 32);
121 // Save the partition offset and length
122 _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
);
123 _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
);
125 partitionOffsetNumber
->release();
126 partitionLengthNumber
->release();
128 currentOffset
+= currentLength
;
131 // Use the fixed address for old world machines.
132 _ofPartitionOffset
= 0x1800;
133 _ofPartitionSize
= 0x0800;
134 _xpramPartitionOffset
= 0x1300;
135 _xpramPartitionSize
= 0x0100;
136 _nrPartitionOffset
= 0x1400;
137 _nrPartitionSize
= 0x0400;
140 if (_ofPartitionOffset
!= 0xFFFFFFFF)
141 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
142 if (_xpramPartitionOffset
!= 0xFFFFFFFF)
143 _xpramImage
= _nvramImage
+ _xpramPartitionOffset
;
144 if (_nrPartitionOffset
!= 0xFFFFFFFF)
145 _nrImage
= _nvramImage
+ _nrPartitionOffset
;
147 if (_piPartitionOffset
== 0xFFFFFFFF) {
148 if (freePartitionSize
> 0x20) {
149 // Set the signature to 0xa1.
150 _nvramImage
[freePartitionOffset
] = 0xa1;
151 // Set the checksum to 0.
152 _nvramImage
[freePartitionOffset
+ 1] = 0;
153 // Set the name for the Panic Info partition.
154 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
155 kIODTNVRAMPanicInfoPartitonName
, 12);
157 // Calculate the partition offset and size.
158 _piPartitionOffset
= freePartitionOffset
+ 0x10;
159 _piPartitionSize
= 0x800;
160 if (_piPartitionSize
+ 0x20 > freePartitionSize
)
161 _piPartitionSize
= freePartitionSize
- 0x20;
163 _piImage
= _nvramImage
+ _piPartitionOffset
;
165 // Zero the new partition.
166 bzero(_piImage
, _piPartitionSize
);
168 // Set the partition size.
169 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
170 (_piPartitionSize
/ 0x10) + 1;
172 // Set the partition checksum.
173 _nvramImage
[freePartitionOffset
+ 1] =
174 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
176 // Calculate the free partition offset and size.
177 freePartitionOffset
+= _piPartitionSize
+ 0x10;
178 freePartitionSize
-= _piPartitionSize
+ 0x10;
180 // Set the signature to 0x7f.
181 _nvramImage
[freePartitionOffset
] = 0x7f;
182 // Set the checksum to 0.
183 _nvramImage
[freePartitionOffset
+ 1] = 0;
184 // Set the name for the free partition.
185 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
186 kIODTNVRAMFreePartitionName
, 12);
187 // Set the partition size.
188 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
189 freePartitionSize
/ 0x10;
190 // Set the partition checksum.
191 _nvramImage
[freePartitionOffset
+ 1] =
192 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
194 // Set the nvram image as dirty.
195 _nvramImageDirty
= true;
198 _piImage
= _nvramImage
+ _piPartitionOffset
;
204 void IODTNVRAM::sync(void)
206 if (!_nvramImageDirty
&& !_ofImageDirty
) return;
208 // Don't try to sync OF Variables if the system has already paniced.
209 if (!_systemPaniced
) syncOFVariables();
211 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
212 _nvramController
->sync();
214 _nvramImageDirty
= false;
217 bool IODTNVRAM::serializeProperties(OSSerialize
*s
) const
222 OSDictionary
*dict
, *tmpDict
= 0;
223 OSCollectionIterator
*iter
= 0;
225 if (_ofDict
== 0) return false;
227 // Verify permissions.
228 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
229 if (result
!= kIOReturnSuccess
) {
230 tmpDict
= OSDictionary::withCapacity(1);
231 if (tmpDict
== 0) return false;
233 iter
= OSCollectionIterator::withCollection(_ofDict
);
234 if (iter
== 0) return false;
237 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
240 variablePerm
= getOFVariablePerm(key
);
241 if (variablePerm
!= kOFVariablePermRootOnly
) {
242 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
250 result
= dict
->serialize(s
);
252 if (tmpDict
!= 0) tmpDict
->release();
253 if (iter
!= 0) iter
->release();
258 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
263 if (_ofDict
== 0) return 0;
265 // Verify permissions.
266 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
267 if (result
!= kIOReturnSuccess
) {
268 variablePerm
= getOFVariablePerm(aKey
);
269 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
272 return _ofDict
->getObject(aKey
);
275 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
277 const OSSymbol
*keySymbol
;
278 OSObject
*theObject
= 0;
280 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
281 if (keySymbol
!= 0) {
282 theObject
= getProperty(keySymbol
);
283 keySymbol
->release();
289 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
292 UInt32 propType
, propPerm
;
294 OSObject
*propObject
= 0;
296 if (_ofDict
== 0) return false;
298 // Verify permissions.
299 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
300 if (result
!= kIOReturnSuccess
) {
301 propPerm
= getOFVariablePerm(aKey
);
302 if (propPerm
!= kOFVariablePermUserWrite
) return false;
305 // Don't allow creation of new properties on old world machines.
306 if (getPlatform()->getBootROMType() == 0) {
307 if (_ofDict
->getObject(aKey
) == 0) return false;
310 // Don't allow change of 'aapl,panic-info'.
311 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return false;
313 // Make sure the object is of the correct type.
314 propType
= getOFVariableType(aKey
);
316 case kOFVariableTypeBoolean
:
317 propObject
= OSDynamicCast(OSBoolean
, anObject
);
320 case kOFVariableTypeNumber
:
321 propObject
= OSDynamicCast(OSNumber
, anObject
);
324 case kOFVariableTypeString
:
325 propObject
= OSDynamicCast(OSString
, anObject
);
328 case kOFVariableTypeData
:
329 propObject
= OSDynamicCast(OSData
, anObject
);
330 if (propObject
== 0) {
331 tmpString
= OSDynamicCast(OSString
, anObject
);
332 if (tmpString
!= 0) {
333 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
334 tmpString
->getLength());
340 if (propObject
== 0) return false;
342 result
= _ofDict
->setObject(aKey
, propObject
);
345 if (getPlatform()->getBootROMType() == 0) {
346 updateOWBootArgs(aKey
, propObject
);
349 _ofImageDirty
= true;
355 void IODTNVRAM::removeProperty(const OSSymbol
*aKey
)
360 if (_ofDict
== 0) return;
362 // Verify permissions.
363 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
364 if (result
!= kIOReturnSuccess
) {
365 propPerm
= getOFVariablePerm(aKey
);
366 if (propPerm
!= kOFVariablePermUserWrite
) return;
369 // Don't allow removal of properties on old world machines.
370 if (getPlatform()->getBootROMType() == 0) return;
372 // Don't allow change of 'aapl,panic-info'.
373 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return;
375 // If the object exists, remove it from the dictionary.
376 result
= _ofDict
->getObject(aKey
) != 0;
378 _ofDict
->removeObject(aKey
);
380 _ofImageDirty
= true;
384 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
389 const OSString
*tmpStr
;
391 OSCollectionIterator
*iter
;
393 dict
= OSDynamicCast(OSDictionary
, properties
);
394 if (dict
== 0) return kIOReturnBadArgument
;
396 iter
= OSCollectionIterator::withCollection(dict
);
397 if (iter
== 0) return kIOReturnBadArgument
;
400 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
403 object
= dict
->getObject(key
);
404 if (object
== 0) continue;
406 if (key
->isEqualTo(kIONVRAMDeletePropertyKey
)) {
407 tmpStr
= OSDynamicCast(OSString
, object
);
409 key
= OSSymbol::withString(tmpStr
);
417 result
= setProperty(key
, object
);
423 if (result
) return kIOReturnSuccess
;
424 else return kIOReturnError
;
427 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
430 if (_xpramImage
== 0) return kIOReturnUnsupported
;
432 if ((buffer
== 0) || (length
== 0) ||
433 (offset
+ length
> kIODTNVRAMXPRAMSize
))
434 return kIOReturnBadArgument
;
436 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
438 return kIOReturnSuccess
;
441 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
444 if (_xpramImage
== 0) return kIOReturnUnsupported
;
446 if ((buffer
== 0) || (length
== 0) ||
447 (offset
+ length
> kIODTNVRAMXPRAMSize
))
448 return kIOReturnBadArgument
;
450 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
452 _nvramImageDirty
= true;
454 return kIOReturnSuccess
;
457 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
458 const OSSymbol
**name
,
463 if (getPlatform()->getBootROMType())
464 err
= readNVRAMPropertyType1(entry
, name
, value
);
466 err
= readNVRAMPropertyType0(entry
, name
, value
);
471 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
472 const OSSymbol
*name
,
477 if (getPlatform()->getBootROMType())
478 err
= writeNVRAMPropertyType1(entry
, name
, value
);
480 err
= writeNVRAMPropertyType0(entry
, name
, value
);
485 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
487 return _nvramPartitionLengths
;
490 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
491 IOByteCount offset
, UInt8
*buffer
,
494 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
495 UInt32 partitionOffset
, partitionLength
;
497 partitionOffsetNumber
=
498 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
499 partitionLengthNumber
=
500 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
502 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
503 return kIOReturnNotFound
;
505 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
506 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
508 if ((buffer
== 0) || (length
== 0) ||
509 (offset
+ length
> partitionLength
))
510 return kIOReturnBadArgument
;
512 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
514 return kIOReturnSuccess
;
517 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
518 IOByteCount offset
, UInt8
*buffer
,
521 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
522 UInt32 partitionOffset
, partitionLength
;
524 partitionOffsetNumber
=
525 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
526 partitionLengthNumber
=
527 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
529 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
530 return kIOReturnNotFound
;
532 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
533 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
535 if ((buffer
== 0) || (length
== 0) ||
536 (offset
+ length
> partitionLength
))
537 return kIOReturnBadArgument
;
539 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
541 _nvramImageDirty
= true;
543 return kIOReturnSuccess
;
546 UInt32
IODTNVRAM::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
548 if ((_piImage
== 0) || (length
<= 0)) return 0;
550 if (length
> (_piPartitionSize
- 4))
551 length
= _piPartitionSize
- 4;
553 // Save the Panic Info.
554 bcopy(buffer
, _piImage
+ 4, length
);
556 // Save the Panic Info length.
557 *(UInt32
*)_piImage
= length
;
559 _nvramImageDirty
= true;
561 _systemPaniced
= true;
568 UInt8
IODTNVRAM::calculatePartitionChecksum(UInt8
*partitionHeader
)
570 UInt8 cnt
, isum
, csum
= 0;
572 for (cnt
= 0; cnt
< 0x10; cnt
++) {
573 isum
= csum
+ partitionHeader
[cnt
];
574 if (isum
< csum
) isum
++;
581 struct OWVariablesHeader
{
596 typedef struct OWVariablesHeader OWVariablesHeader
;
598 IOReturn
IODTNVRAM::initOFVariables(void)
600 UInt32 cnt
, propOffset
, propType
;
601 UInt8
*propName
, *propData
;
602 UInt32 propNameLength
, propDataLength
;
603 const OSSymbol
*propSymbol
;
604 OSObject
*propObject
;
605 OWVariablesHeader
*owHeader
;
607 if (_ofImage
== 0) return kIOReturnNotReady
;
609 _ofDict
= OSDictionary::withCapacity(1);
610 if (_ofDict
== 0) return kIOReturnNoMemory
;
612 if (getPlatform()->getBootROMType()) {
614 while (cnt
< _ofPartitionSize
) {
615 // Break if there is no name.
616 if (_ofImage
[cnt
] == '\0') break;
618 // Find the length of the name.
619 propName
= _ofImage
+ cnt
;
620 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
622 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
625 // Break if the name goes past the end of the partition.
626 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
627 cnt
+= propNameLength
+ 1;
629 propData
= _ofImage
+ cnt
;
630 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
632 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
635 // Break if the data goes past the end of the partition.
636 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
637 cnt
+= propDataLength
+ 1;
639 if (convertPropToObject(propName
, propNameLength
,
640 propData
, propDataLength
,
641 &propSymbol
, &propObject
)) {
642 _ofDict
->setObject(propSymbol
, propObject
);
643 propSymbol
->release();
644 propObject
->release();
648 // Create the boot-args property if it is not in the dictionary.
649 if (_ofDict
->getObject("boot-args") == 0) {
650 propObject
= OSString::withCStringNoCopy("");
651 if (propObject
!= 0) {
652 _ofDict
->setObject("boot-args", propObject
);
653 propObject
->release();
657 // Create the 'aapl,panic-info' property if needed.
659 propDataLength
= *(UInt32
*)_piImage
;
660 if ((propDataLength
!= 0) && (propDataLength
< (_piPartitionSize
- 4))) {
661 propObject
= OSData::withBytes(_piImage
+ 4, propDataLength
);
662 _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
);
663 propObject
->release();
665 // Clear the length from _piImage and mark dirty.
666 *(UInt32
*)_piImage
= 0;
667 _nvramImageDirty
= true;
671 owHeader
= (OWVariablesHeader
*)_ofImage
;
672 if (!validateOWChecksum(_ofImage
)) {
675 return kIOReturnBadMedia
;
680 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
684 case kOFVariableTypeBoolean
:
685 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
688 case kOFVariableTypeNumber
:
689 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
692 case kOFVariableTypeString
:
693 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
695 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
696 propName
= IONew(UInt8
, propDataLength
+ 1);
698 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
699 propName
[propDataLength
] = '\0';
700 propObject
= OSString::withCString((const char *)propName
);
701 IODelete(propName
, UInt8
, propDataLength
+ 1);
706 if (propObject
== 0) break;
708 _ofDict
->setObject(propSymbol
, propObject
);
709 propSymbol
->release();
710 propObject
->release();
713 // Create the boot-args property.
714 propSymbol
= OSSymbol::withCString("boot-command");
715 if (propSymbol
!= 0) {
716 propObject
= _ofDict
->getObject(propSymbol
);
717 if (propObject
!= 0) {
718 updateOWBootArgs(propSymbol
, propObject
);
720 propSymbol
->release();
724 return kIOReturnSuccess
;
727 IOReturn
IODTNVRAM::syncOFVariables(void)
730 UInt32 cnt
, length
, maxLength
;
731 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
732 UInt8
*buffer
, *tmpBuffer
;
733 const UInt8
*tmpData
;
734 const OSSymbol
*tmpSymbol
;
736 OSBoolean
*tmpBoolean
;
739 OSCollectionIterator
*iter
;
740 OWVariablesHeader
*owHeader
, *owHeaderOld
;
742 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
744 if (!_ofImageDirty
) return kIOReturnSuccess
;
746 if (getPlatform()->getBootROMType()) {
747 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
748 if (buffer
== 0) return kIOReturnNoMemory
;
749 bzero(buffer
, _ofPartitionSize
);
752 maxLength
= _ofPartitionSize
;
754 iter
= OSCollectionIterator::withCollection(_ofDict
);
755 if (iter
== 0) ok
= false;
758 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
759 if (tmpSymbol
== 0) break;
761 // Don't save 'aapl,panic-info'.
762 if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue;
764 tmpObject
= _ofDict
->getObject(tmpSymbol
);
767 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
776 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
779 IODelete(buffer
, UInt8
, _ofPartitionSize
);
781 if (!ok
) return kIOReturnBadArgument
;
783 buffer
= IONew(UInt8
, _ofPartitionSize
);
784 if (buffer
== 0) return kIOReturnNoMemory
;
785 bzero(buffer
, _ofPartitionSize
);
787 owHeader
= (OWVariablesHeader
*)buffer
;
788 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
790 owHeader
->owMagic
= owHeaderOld
->owMagic
;
791 owHeader
->owVersion
= owHeaderOld
->owVersion
;
792 owHeader
->owPages
= owHeaderOld
->owPages
;
794 curOffset
= _ofPartitionSize
;
799 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
802 tmpObject
= _ofDict
->getObject(tmpSymbol
);
805 case kOFVariableTypeBoolean
:
806 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
807 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
810 case kOFVariableTypeNumber
:
811 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
812 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
815 case kOFVariableTypeString
:
816 tmpString
= OSDynamicCast(OSString
, tmpObject
);
817 tmpData
= (const UInt8
*)tmpString
->getCStringNoCopy();
818 tmpDataLength
= tmpString
->getLength();
820 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
825 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
826 curOffset
-= tmpDataLength
;
827 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
828 if (tmpDataLength
!= 0)
829 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
835 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
836 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
837 owHeader
->owNext
= 0;
839 owHeader
->owChecksum
= 0;
840 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
842 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
845 IODelete(buffer
, UInt8
, _ofPartitionSize
);
847 if (!ok
) return kIOReturnBadArgument
;
850 _ofImageDirty
= false;
851 _nvramImageDirty
= true;
853 return kIOReturnSuccess
;
857 const char *variableName
;
860 SInt32 variableOffset
;
862 typedef struct OFVariable OFVariable
;
865 kOWVariableOffsetNumber
= 8,
866 kOWVariableOffsetString
= 17
869 OFVariable gOFVariables
[] = {
870 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
871 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
872 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
873 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
874 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
875 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
876 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
877 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
878 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
879 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
880 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
881 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
882 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
883 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
884 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
885 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
886 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
887 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
888 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
889 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
890 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
891 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
892 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
893 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
894 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
895 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
896 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
897 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
898 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
899 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
900 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
901 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
902 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
903 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
904 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
905 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
906 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
907 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
908 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
909 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
910 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
911 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
912 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
913 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
914 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
915 {"boot-image", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
916 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
919 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
923 ofVar
= gOFVariables
;
925 if ((ofVar
->variableName
== 0) ||
926 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
930 return ofVar
->variableType
;
933 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
937 ofVar
= gOFVariables
;
939 if ((ofVar
->variableName
== 0) ||
940 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
944 return ofVar
->variablePerm
;
947 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
948 UInt32
*propType
, UInt32
*propOffset
)
952 ofVar
= gOFVariables
;
954 if (ofVar
->variableName
== 0) return false;
956 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
961 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
962 *propType
= ofVar
->variableType
;
965 case kOFVariableTypeBoolean
:
966 *propOffset
= 1 << (31 - variableNumber
);
969 case kOFVariableTypeNumber
:
970 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
973 case kOFVariableTypeString
:
974 *propOffset
= variableNumber
- kOWVariableOffsetString
;
981 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
982 UInt8
*propData
, UInt32 propDataLength
,
983 const OSSymbol
**propSymbol
,
984 OSObject
**propObject
)
987 const OSSymbol
*tmpSymbol
;
992 // Create the symbol.
993 propName
[propNameLength
] = '\0';
994 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
995 propName
[propNameLength
] = '=';
996 if (tmpSymbol
== 0) {
1000 propType
= getOFVariableType(tmpSymbol
);
1002 // Create the object.
1005 case kOFVariableTypeBoolean
:
1006 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
1007 tmpObject
= kOSBooleanTrue
;
1008 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
1009 tmpObject
= kOSBooleanFalse
;
1013 case kOFVariableTypeNumber
:
1014 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
1015 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
1018 case kOFVariableTypeString
:
1019 tmpString
= OSString::withCString((const char *)propData
);
1020 if (tmpString
!= 0) tmpObject
= tmpString
;
1023 case kOFVariableTypeData
:
1024 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
1028 if (tmpObject
== 0) {
1029 tmpSymbol
->release();
1033 *propSymbol
= tmpSymbol
;
1034 *propObject
= tmpObject
;
1039 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
1040 const OSSymbol
*propSymbol
, OSObject
*propObject
)
1042 const UInt8
*propName
;
1043 UInt32 propNameLength
, propDataLength
;
1044 UInt32 propType
, tmpValue
;
1045 OSBoolean
*tmpBoolean
= 0;
1046 OSNumber
*tmpNumber
= 0;
1047 OSString
*tmpString
= 0;
1048 OSData
*tmpData
= 0;
1050 propName
= (const UInt8
*)propSymbol
->getCStringNoCopy();
1051 propNameLength
= propSymbol
->getLength();
1052 propType
= getOFVariableType(propSymbol
);
1054 // Get the size of the data.
1055 propDataLength
= 0xFFFFFFFF;
1057 case kOFVariableTypeBoolean
:
1058 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
1059 if (tmpBoolean
!= 0) propDataLength
= 5;
1062 case kOFVariableTypeNumber
:
1063 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
1064 if (tmpNumber
!= 0) propDataLength
= 10;
1067 case kOFVariableTypeString
:
1068 tmpString
= OSDynamicCast(OSString
, propObject
);
1069 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
1072 case kOFVariableTypeData
:
1073 tmpData
= OSDynamicCast(OSData
, propObject
);
1075 tmpData
= escapeDataToData(tmpData
);
1076 propDataLength
= tmpData
->getLength();
1081 // Make sure the propertySize is known and will fit.
1082 if (propDataLength
== 0xFFFFFFFF) return false;
1083 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
1085 // Copy the property name equal sign.
1086 sprintf((char *)buffer
, "%s=", propName
);
1087 buffer
+= propNameLength
+ 1;
1090 case kOFVariableTypeBoolean
:
1091 if (tmpBoolean
->getValue()) {
1092 strcpy((char *)buffer
, "true");
1094 strcpy((char *)buffer
, "false");
1098 case kOFVariableTypeNumber
:
1099 tmpValue
= tmpNumber
->unsigned32BitValue();
1100 if (tmpValue
== 0xFFFFFFFF) {
1101 strcpy((char *)buffer
, "-1");
1102 } else if (tmpValue
< 1000) {
1103 sprintf((char *)buffer
, "%ld", tmpValue
);
1105 sprintf((char *)buffer
, "0x%lx", tmpValue
);
1109 case kOFVariableTypeString
:
1110 strcpy((char *)buffer
, tmpString
->getCStringNoCopy());
1113 case kOFVariableTypeData
:
1114 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
1119 propDataLength
= strlen((const char *)buffer
);
1121 *length
= propNameLength
+ propDataLength
+ 2;
1127 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
1129 UInt32 cnt
, checksum
= 0;
1130 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1132 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1133 checksum
+= tmpBuffer
[cnt
];
1135 return checksum
% 0x0000FFFF;
1138 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
1140 UInt32 cnt
, checksum
, sum
= 0;
1141 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1143 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1144 sum
+= tmpBuffer
[cnt
];
1146 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
1147 if (checksum
== 0x10000) checksum
--;
1148 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
1150 return checksum
== 0;
1153 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
1155 bool wasBootArgs
, bootr
= false;
1157 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
1158 const UInt8
*bootCommandData
, *bootArgsData
;
1160 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
1162 tmpString
= OSDynamicCast(OSString
, value
);
1163 if (tmpString
== 0) return;
1165 if (key
->isEqualTo("boot-command")) {
1166 wasBootArgs
= false;
1167 bootCommand
= tmpString
;
1168 } else if (key
->isEqualTo("boot-args")) {
1170 bootArgs
= tmpString
;
1171 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1172 if (bootCommand
== 0) return;
1175 bootCommandData
= (const UInt8
*)bootCommand
->getCStringNoCopy();
1176 bootCommandDataLength
= bootCommand
->getLength();
1178 if (bootCommandData
== 0) return;
1180 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1181 if ((bootCommandData
[cnt
] == 'b') &&
1182 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1184 while (bootCommandData
[cnt
] == ' ') cnt
++;
1190 _ofDict
->removeObject("boot-args");
1195 bootArgsData
= (const UInt8
*)bootArgs
->getCStringNoCopy();
1196 bootArgsDataLength
= bootArgs
->getLength();
1197 if (bootArgsData
== 0) return;
1199 tmpDataLength
= cnt
+ bootArgsDataLength
;
1200 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1201 if (tmpData
== 0) return;
1203 strncpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1204 tmpData
[cnt
] = '\0';
1205 strcat((char *)tmpData
, (const char *)bootArgsData
);
1207 bootCommand
= OSString::withCString((const char *)tmpData
);
1208 if (bootCommand
!= 0) {
1209 _ofDict
->setObject("boot-command", bootCommand
);
1210 bootCommand
->release();
1213 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1215 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1216 if (bootArgs
!= 0) {
1217 _ofDict
->setObject("boot-args", bootArgs
);
1218 bootArgs
->release();
1224 // Private methods for Name Registry access.
1227 kMaxNVNameLength
= 4,
1228 kMaxNVDataLength
= 8
1231 #pragma options align=mac68k
1232 struct NVRAMProperty
1234 IONVRAMDescriptor header
;
1236 UInt8 name
[ kMaxNVNameLength
];
1238 UInt8 data
[ kMaxNVDataLength
];
1240 #pragma options align=reset
1242 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1247 nvEnd
= *((UInt16
*)_nrImage
);
1248 if(getPlatform()->getBootROMType()) {
1249 // on NewWorld, offset to partition start
1252 // on old world, absolute
1253 nvEnd
-= _nrPartitionOffset
;
1255 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1259 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1260 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1264 offset
+= sizeof(NVRAMProperty
);
1267 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1275 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1276 const OSSymbol
**name
,
1279 IONVRAMDescriptor hdr
;
1280 NVRAMProperty
*prop
;
1284 char nameBuf
[kMaxNVNameLength
+ 1];
1286 if (_nrImage
== 0) return kIOReturnUnsupported
;
1287 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1289 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1290 if (err
!= kIOReturnSuccess
) return err
;
1292 if (searchNVRAMProperty(&hdr
, &offset
)) {
1293 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1295 length
= prop
->nameLength
;
1296 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1297 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1298 nameBuf
[length
] = 0;
1299 *name
= OSSymbol::withCString(nameBuf
);
1301 length
= prop
->dataLength
;
1302 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1303 *value
= OSData::withBytes(prop
->data
, length
);
1305 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1306 else return kIOReturnNoMemory
;
1309 return kIOReturnNoResources
;
1312 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1313 const OSSymbol
*name
,
1316 IONVRAMDescriptor hdr
;
1317 NVRAMProperty
*prop
;
1318 IOByteCount nameLength
;
1319 IOByteCount dataLength
;
1325 if (_nrImage
== 0) return kIOReturnUnsupported
;
1326 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1328 nameLength
= name
->getLength();
1329 dataLength
= value
->getLength();
1330 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1331 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1333 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1334 if (err
!= kIOReturnSuccess
) return err
;
1336 exists
= searchNVRAMProperty(&hdr
, &offset
);
1337 if (offset
== 0) return kIOReturnNoMemory
;
1339 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1340 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1342 prop
->nameLength
= nameLength
;
1343 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1344 prop
->dataLength
= dataLength
;
1345 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1348 nvLength
= offset
+ sizeof(NVRAMProperty
);
1349 if (getPlatform()->getBootROMType())
1352 nvLength
+= _nrPartitionOffset
;
1353 *((UInt16
*)_nrImage
) = nvLength
;
1356 _nvramImageDirty
= true;
1361 OSData
*IODTNVRAM::unescapeBytesToData(const UInt8
*bytes
, UInt32 length
)
1364 UInt32 totalLength
= 0;
1369 // Calculate the actual length of the data.
1372 for (cnt
= 0; cnt
< length
;) {
1373 byte
= bytes
[cnt
++];
1375 byte
= bytes
[cnt
++];
1383 totalLength
+= cnt2
;
1387 // Create an empty OSData of the correct size.
1388 data
= OSData::withCapacity(totalLength
);
1390 for (cnt
= 0; cnt
< length
;) {
1391 byte
= bytes
[cnt
++];
1393 byte
= bytes
[cnt
++];
1395 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1398 data
->appendByte(byte
, cnt2
);
1406 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1409 const UInt8
* startPtr
;
1410 const UInt8
* endPtr
;
1411 const UInt8
* wherePtr
;
1415 wherePtr
= (const UInt8
*) value
->getBytesNoCopy();
1416 endPtr
= wherePtr
+ value
->getLength();
1418 result
= OSData::withCapacity(endPtr
- wherePtr
);
1422 while (wherePtr
< endPtr
) {
1423 startPtr
= wherePtr
;
1425 if ((byte
== 0x00) || (byte
== 0xFF)) {
1427 ((wherePtr
- startPtr
) < 0x80) && (wherePtr
< endPtr
) && (byte
== *wherePtr
);
1429 ok
&= result
->appendByte(0xff, 1);
1430 byte
= (byte
& 0x80) | (wherePtr
- startPtr
);
1432 ok
&= result
->appendByte(byte
, 1);
1434 ok
&= result
->appendByte(0, 1);
1444 static bool IsApplePropertyName(const char * propName
)
1447 while ((c
= *propName
++)) {
1448 if ((c
>= 'A') && (c
<= 'Z'))
1455 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1456 const OSSymbol
**name
,
1459 IOReturn err
= kIOReturnNoResources
;
1461 const UInt8
*startPtr
;
1462 const UInt8
*endPtr
;
1463 const UInt8
*wherePtr
;
1464 const UInt8
*nvPath
= 0;
1465 const char *nvName
= 0;
1466 const char *resultName
= 0;
1467 const UInt8
*resultValue
= 0;
1468 UInt32 resultValueLen
= 0;
1471 if (_ofDict
== 0) return err
;
1472 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1473 if (data
== 0) return err
;
1475 startPtr
= (const UInt8
*) data
->getBytesNoCopy();
1476 endPtr
= startPtr
+ data
->getLength();
1478 wherePtr
= startPtr
;
1479 while (wherePtr
< endPtr
) {
1480 byte
= *(wherePtr
++);
1486 else if (nvName
== 0)
1487 nvName
= (const char *) startPtr
;
1489 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1491 compareEntry
->release();
1492 if (entry
== compareEntry
) {
1493 bool appleProp
= IsApplePropertyName(nvName
);
1494 if (!appleProp
|| !resultName
) {
1495 resultName
= nvName
;
1496 resultValue
= startPtr
;
1497 resultValueLen
= wherePtr
- startPtr
- 1;
1505 startPtr
= wherePtr
;
1508 *name
= OSSymbol::withCString(resultName
);
1509 *value
= unescapeBytesToData(resultValue
, resultValueLen
);
1510 if ((*name
!= 0) && (*value
!= 0))
1511 err
= kIOReturnSuccess
;
1513 err
= kIOReturnNoMemory
;
1518 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1519 const OSSymbol
*propName
,
1524 const UInt8
*startPtr
;
1525 const UInt8
*propStart
;
1526 const UInt8
*endPtr
;
1527 const UInt8
*wherePtr
;
1528 const UInt8
*nvPath
= 0;
1529 const char *nvName
= 0;
1534 bool settingAppleProp
;
1536 if (_ofDict
== 0) return kIOReturnNoResources
;
1538 settingAppleProp
= IsApplePropertyName(propName
->getCStringNoCopy());
1540 // copy over existing properties for other entries
1542 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1544 startPtr
= (const UInt8
*) oldData
->getBytesNoCopy();
1545 endPtr
= startPtr
+ oldData
->getLength();
1547 propStart
= startPtr
;
1548 wherePtr
= startPtr
;
1549 while (wherePtr
< endPtr
) {
1550 byte
= *(wherePtr
++);
1555 else if (nvName
== 0)
1556 nvName
= (const char *) startPtr
;
1558 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1560 compareEntry
->release();
1561 if (entry
== compareEntry
) {
1562 if ((settingAppleProp
&& propName
->isEqualTo(nvName
))
1563 || (!settingAppleProp
&& !IsApplePropertyName(nvName
))) {
1564 // delete old property (nvPath -> wherePtr)
1565 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1567 ok
&= data
->appendBytes(wherePtr
, endPtr
- wherePtr
);
1575 startPtr
= wherePtr
;
1579 // make the new property
1583 data
= OSData::withData(oldData
);
1585 data
= OSData::withCapacity(16);
1587 return kIOReturnNoMemory
;
1590 if (value
&& value
->getLength()) {
1591 // get entries in path
1592 OSArray
*array
= OSArray::withCapacity(5);
1595 return kIOReturnNoMemory
;
1598 array
->setObject(entry
);
1599 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1602 for (int i
= array
->getCount() - 3;
1603 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1606 name
= entry
->getName(gIODTPlane
);
1607 comp
= entry
->getLocation(gIODTPlane
);
1608 if( comp
&& (0 == strcmp("pci", name
))
1609 && (0 == strcmp("80000000", comp
))) {
1611 comp
= "/pci@80000000";
1614 ok
&= data
->appendBytes("/@", 2);
1618 ok
&= data
->appendByte('/', 1);
1622 ok
&= data
->appendBytes(comp
, strlen(comp
));
1624 ok
&= data
->appendByte(0, 1);
1628 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1630 // append escaped data
1631 oldData
= escapeDataToData(value
);
1632 ok
&= (oldData
!= 0);
1634 ok
&= data
->appendBytes(oldData
);
1637 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1639 _ofImageDirty
= true;
1643 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;