2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <IOKit/IOLib.h>
24 #include <IOKit/IONVRAM.h>
25 #include <IOKit/IOPlatformExpert.h>
26 #include <IOKit/IOUserClient.h>
27 #include <IOKit/IOKitKeys.h>
29 #define super IOService
31 #define kIONVRAMPrivilege kIOClientPrivilegeAdministrator
32 //#define kIONVRAMPrivilege kIOClientPrivilegeLocalUser
35 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
);
37 bool IODTNVRAM::init(IORegistryEntry
*old
, const IORegistryPlane
*plane
)
41 if (!super::init(old
, plane
)) return false;
43 dict
= OSDictionary::withCapacity(1);
44 if (dict
== 0) return false;
45 setPropertyTable(dict
);
47 _nvramImage
= IONew(UInt8
, kIODTNVRAMImageSize
);
48 if (_nvramImage
== 0) return false;
50 _nvramPartitionOffsets
= OSDictionary::withCapacity(1);
51 if (_nvramPartitionOffsets
== 0) return false;
53 _nvramPartitionLengths
= OSDictionary::withCapacity(1);
54 if (_nvramPartitionLengths
== 0) return false;
56 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
57 if (_registryPropertiesKey
== 0) return false;
62 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
65 UInt32 partitionOffset
, partitionLength
;
66 UInt32 freePartitionOffset
, freePartitionSize
;
67 UInt32 currentLength
, currentOffset
= 0;
68 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
70 if (_nvramController
!= 0) return;
72 _nvramController
= nvram
;
74 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
76 // Find the offsets for the OF, XPRAM, NameRegistry and PanicInfo partitions.
77 _ofPartitionOffset
= 0xFFFFFFFF;
78 _xpramPartitionOffset
= 0xFFFFFFFF;
79 _nrPartitionOffset
= 0xFFFFFFFF;
80 _piPartitionOffset
= 0xFFFFFFFF;
81 freePartitionOffset
= 0xFFFFFFFF;
82 freePartitionSize
= 0;
83 if (getPlatform()->getBootROMType()) {
84 // Look through the partitions to find the OF, MacOS partitions.
85 while (currentOffset
< kIODTNVRAMImageSize
) {
86 currentLength
= ((UInt16
*)(_nvramImage
+ currentOffset
))[1] * 16;
88 partitionOffset
= currentOffset
+ 16;
89 partitionLength
= currentLength
- 16;
91 if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
92 kIODTNVRAMOFPartitionName
, 12) == 0) {
93 _ofPartitionOffset
= partitionOffset
;
94 _ofPartitionSize
= partitionLength
;
95 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
96 kIODTNVRAMXPRAMPartitionName
, 12) == 0) {
97 _xpramPartitionOffset
= partitionOffset
;
98 _xpramPartitionSize
= kIODTNVRAMXPRAMSize
;
99 _nrPartitionOffset
= _xpramPartitionOffset
+ _xpramPartitionSize
;
100 _nrPartitionSize
= partitionLength
- _xpramPartitionSize
;
101 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
102 kIODTNVRAMPanicInfoPartitonName
, 12) == 0) {
103 _piPartitionOffset
= partitionOffset
;
104 _piPartitionSize
= partitionLength
;
105 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
106 kIODTNVRAMFreePartitionName
, 12) == 0) {
107 freePartitionOffset
= currentOffset
;
108 freePartitionSize
= currentLength
;
110 // Construct the partition ID from the signature and name.
111 sprintf(partitionID
, "0x%02x,",
112 *(UInt8
*)(_nvramImage
+ currentOffset
));
113 strncpy(partitionID
+ 5,
114 (const char *)(_nvramImage
+ currentOffset
+ 4), 12);
115 partitionID
[17] = '\0';
117 partitionOffsetNumber
= OSNumber::withNumber(partitionOffset
, 32);
118 partitionLengthNumber
= OSNumber::withNumber(partitionLength
, 32);
120 // Save the partition offset and length
121 _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
);
122 _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
);
124 partitionOffsetNumber
->release();
125 partitionLengthNumber
->release();
127 currentOffset
+= currentLength
;
130 // Use the fixed address for old world machines.
131 _ofPartitionOffset
= 0x1800;
132 _ofPartitionSize
= 0x0800;
133 _xpramPartitionOffset
= 0x1300;
134 _xpramPartitionSize
= 0x0100;
135 _nrPartitionOffset
= 0x1400;
136 _nrPartitionSize
= 0x0400;
139 if (_ofPartitionOffset
!= 0xFFFFFFFF)
140 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
141 if (_xpramPartitionOffset
!= 0xFFFFFFFF)
142 _xpramImage
= _nvramImage
+ _xpramPartitionOffset
;
143 if (_nrPartitionOffset
!= 0xFFFFFFFF)
144 _nrImage
= _nvramImage
+ _nrPartitionOffset
;
146 if (_piPartitionOffset
== 0xFFFFFFFF) {
147 if (freePartitionSize
> 0x20) {
148 // Set the signature to 0xa1.
149 _nvramImage
[freePartitionOffset
] = 0xa1;
150 // Set the checksum to 0.
151 _nvramImage
[freePartitionOffset
+ 1] = 0;
152 // Set the name for the Panic Info partition.
153 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
154 kIODTNVRAMPanicInfoPartitonName
, 12);
156 // Calculate the partition offset and size.
157 _piPartitionOffset
= freePartitionOffset
+ 0x10;
158 _piPartitionSize
= 0x800;
159 if (_piPartitionSize
+ 0x20 > freePartitionSize
)
160 _piPartitionSize
= freePartitionSize
- 0x20;
162 _piImage
= _nvramImage
+ _piPartitionOffset
;
164 // Zero the new partition.
165 bzero(_piImage
, _piPartitionSize
);
167 // Set the partition size.
168 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
169 (_piPartitionSize
/ 0x10) + 1;
171 // Set the partition checksum.
172 _nvramImage
[freePartitionOffset
+ 1] =
173 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
175 // Calculate the free partition offset and size.
176 freePartitionOffset
+= _piPartitionSize
+ 0x10;
177 freePartitionSize
-= _piPartitionSize
+ 0x10;
179 // Set the signature to 0x7f.
180 _nvramImage
[freePartitionOffset
] = 0x7f;
181 // Set the checksum to 0.
182 _nvramImage
[freePartitionOffset
+ 1] = 0;
183 // Set the name for the free partition.
184 strncpy((char *)(_nvramImage
+ freePartitionOffset
+ 4),
185 kIODTNVRAMFreePartitionName
, 12);
186 // Set the partition size.
187 *(UInt16
*)(_nvramImage
+ freePartitionOffset
+ 2) =
188 freePartitionSize
/ 0x10;
189 // Set the partition checksum.
190 _nvramImage
[freePartitionOffset
+ 1] =
191 calculatePartitionChecksum(_nvramImage
+ freePartitionOffset
);
193 // Set the nvram image as dirty.
194 _nvramImageDirty
= true;
197 _piImage
= _nvramImage
+ _piPartitionOffset
;
203 void IODTNVRAM::sync(void)
205 if (!_nvramImageDirty
&& !_ofImageDirty
) return;
207 // Don't try to sync OF Variables if the system has already paniced.
208 if (!_systemPaniced
) syncOFVariables();
210 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
211 _nvramController
->sync();
213 _nvramImageDirty
= false;
216 bool IODTNVRAM::serializeProperties(OSSerialize
*s
) const
221 OSDictionary
*dict
, *tmpDict
= 0;
222 OSCollectionIterator
*iter
= 0;
224 if (_ofDict
== 0) return false;
226 // Verify permissions.
227 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
228 if (result
!= kIOReturnSuccess
) {
229 tmpDict
= OSDictionary::withCapacity(1);
230 if (tmpDict
== 0) return false;
232 iter
= OSCollectionIterator::withCollection(_ofDict
);
233 if (iter
== 0) return false;
236 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
239 variablePerm
= getOFVariablePerm(key
);
240 if (variablePerm
!= kOFVariablePermRootOnly
) {
241 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
249 result
= dict
->serialize(s
);
251 if (tmpDict
!= 0) tmpDict
->release();
252 if (iter
!= 0) iter
->release();
257 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
262 if (_ofDict
== 0) return 0;
264 // Verify permissions.
265 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
266 if (result
!= kIOReturnSuccess
) {
267 variablePerm
= getOFVariablePerm(aKey
);
268 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
271 return _ofDict
->getObject(aKey
);
274 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
276 const OSSymbol
*keySymbol
;
277 OSObject
*theObject
= 0;
279 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
280 if (keySymbol
!= 0) {
281 theObject
= getProperty(keySymbol
);
282 keySymbol
->release();
288 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
291 UInt32 propType
, propPerm
;
293 OSObject
*propObject
= 0;
295 if (_ofDict
== 0) return false;
297 // Verify permissions.
298 result
= IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege
);
299 if (result
!= kIOReturnSuccess
) {
300 propPerm
= getOFVariablePerm(aKey
);
301 if (propPerm
!= kOFVariablePermUserWrite
) return false;
304 // Don't allow creation of new properties on old world machines.
305 if (getPlatform()->getBootROMType() == 0) {
306 if (_ofDict
->getObject(aKey
) == 0) return false;
309 // Don't allow change of 'aapl,panic-info'.
310 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return false;
312 // Make sure the object is of the correct type.
313 propType
= getOFVariableType(aKey
);
315 case kOFVariableTypeBoolean
:
316 propObject
= OSDynamicCast(OSBoolean
, anObject
);
319 case kOFVariableTypeNumber
:
320 propObject
= OSDynamicCast(OSNumber
, anObject
);
323 case kOFVariableTypeString
:
324 propObject
= OSDynamicCast(OSString
, anObject
);
327 case kOFVariableTypeData
:
328 propObject
= OSDynamicCast(OSData
, anObject
);
329 if (propObject
== 0) {
330 tmpString
= OSDynamicCast(OSString
, anObject
);
331 if (tmpString
!= 0) {
332 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
333 tmpString
->getLength());
339 if (propObject
== 0) return false;
341 result
= _ofDict
->setObject(aKey
, propObject
);
344 if (getPlatform()->getBootROMType() == 0) {
345 updateOWBootArgs(aKey
, propObject
);
348 _ofImageDirty
= true;
354 void IODTNVRAM::removeProperty(const OSSymbol
*aKey
)
359 if (_ofDict
== 0) return;
361 // Verify permissions.
362 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
363 if (result
!= kIOReturnSuccess
) {
364 propPerm
= getOFVariablePerm(aKey
);
365 if (propPerm
!= kOFVariablePermUserWrite
) return;
368 // Don't allow removal of properties on old world machines.
369 if (getPlatform()->getBootROMType() == 0) return;
371 // Don't allow change of 'aapl,panic-info'.
372 if (aKey
->isEqualTo(kIODTNVRAMPanicInfoKey
)) return;
374 // If the object exists, remove it from the dictionary.
375 result
= _ofDict
->getObject(aKey
) != 0;
377 _ofDict
->removeObject(aKey
);
379 _ofImageDirty
= true;
383 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
388 const OSString
*tmpStr
;
390 OSCollectionIterator
*iter
;
392 dict
= OSDynamicCast(OSDictionary
, properties
);
393 if (dict
== 0) return kIOReturnBadArgument
;
395 iter
= OSCollectionIterator::withCollection(dict
);
396 if (iter
== 0) return kIOReturnBadArgument
;
399 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
402 object
= dict
->getObject(key
);
403 if (object
== 0) continue;
405 if (key
->isEqualTo(kIONVRAMDeletePropertyKey
)) {
406 tmpStr
= OSDynamicCast(OSString
, object
);
408 key
= OSSymbol::withString(tmpStr
);
416 result
= setProperty(key
, object
);
422 if (result
) return kIOReturnSuccess
;
423 else return kIOReturnError
;
426 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
429 if (_xpramImage
== 0) return kIOReturnUnsupported
;
431 if ((buffer
== 0) || (length
== 0) ||
432 (offset
+ length
> kIODTNVRAMXPRAMSize
))
433 return kIOReturnBadArgument
;
435 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
437 return kIOReturnSuccess
;
440 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
443 if (_xpramImage
== 0) return kIOReturnUnsupported
;
445 if ((buffer
== 0) || (length
== 0) ||
446 (offset
+ length
> kIODTNVRAMXPRAMSize
))
447 return kIOReturnBadArgument
;
449 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
451 _nvramImageDirty
= true;
453 return kIOReturnSuccess
;
456 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
457 const OSSymbol
**name
,
462 if (getPlatform()->getBootROMType())
463 err
= readNVRAMPropertyType1(entry
, name
, value
);
465 err
= readNVRAMPropertyType0(entry
, name
, value
);
470 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
471 const OSSymbol
*name
,
476 if (getPlatform()->getBootROMType())
477 err
= writeNVRAMPropertyType1(entry
, name
, value
);
479 err
= writeNVRAMPropertyType0(entry
, name
, value
);
484 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
486 return _nvramPartitionLengths
;
489 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
490 IOByteCount offset
, UInt8
*buffer
,
493 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
494 UInt32 partitionOffset
, partitionLength
;
496 partitionOffsetNumber
=
497 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
498 partitionLengthNumber
=
499 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
501 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
502 return kIOReturnNotFound
;
504 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
505 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
507 if ((buffer
== 0) || (length
== 0) ||
508 (offset
+ length
> partitionLength
))
509 return kIOReturnBadArgument
;
511 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
513 return kIOReturnSuccess
;
516 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
517 IOByteCount offset
, UInt8
*buffer
,
520 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
521 UInt32 partitionOffset
, partitionLength
;
523 partitionOffsetNumber
=
524 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
525 partitionLengthNumber
=
526 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
528 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
529 return kIOReturnNotFound
;
531 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
532 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
534 if ((buffer
== 0) || (length
== 0) ||
535 (offset
+ length
> partitionLength
))
536 return kIOReturnBadArgument
;
538 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
540 _nvramImageDirty
= true;
542 return kIOReturnSuccess
;
545 UInt32
IODTNVRAM::savePanicInfo(UInt8
*buffer
, IOByteCount length
)
547 if ((_piImage
== 0) || (length
<= 0)) return 0;
549 if (length
> (_piPartitionSize
- 4))
550 length
= _piPartitionSize
- 4;
552 // Save the Panic Info.
553 bcopy(buffer
, _piImage
+ 4, length
);
555 // Save the Panic Info length.
556 *(UInt32
*)_piImage
= length
;
558 _nvramImageDirty
= true;
560 _systemPaniced
= true;
567 UInt8
IODTNVRAM::calculatePartitionChecksum(UInt8
*partitionHeader
)
569 UInt8 cnt
, isum
, csum
= 0;
571 for (cnt
= 0; cnt
< 0x10; cnt
++) {
572 isum
= csum
+ partitionHeader
[cnt
];
573 if (isum
< csum
) isum
++;
580 struct OWVariablesHeader
{
595 typedef struct OWVariablesHeader OWVariablesHeader
;
597 IOReturn
IODTNVRAM::initOFVariables(void)
599 UInt32 cnt
, propOffset
, propType
;
600 UInt8
*propName
, *propData
;
601 UInt32 propNameLength
, propDataLength
;
602 const OSSymbol
*propSymbol
;
603 OSObject
*propObject
;
604 OWVariablesHeader
*owHeader
;
606 if (_ofImage
== 0) return kIOReturnNotReady
;
608 _ofDict
= OSDictionary::withCapacity(1);
609 if (_ofDict
== 0) return kIOReturnNoMemory
;
611 if (getPlatform()->getBootROMType()) {
613 while (cnt
< _ofPartitionSize
) {
614 // Break if there is no name.
615 if (_ofImage
[cnt
] == '\0') break;
617 // Find the length of the name.
618 propName
= _ofImage
+ cnt
;
619 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
621 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
624 // Break if the name goes past the end of the partition.
625 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
626 cnt
+= propNameLength
+ 1;
628 propData
= _ofImage
+ cnt
;
629 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
631 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
634 // Break if the data goes past the end of the partition.
635 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
636 cnt
+= propDataLength
+ 1;
638 if (convertPropToObject(propName
, propNameLength
,
639 propData
, propDataLength
,
640 &propSymbol
, &propObject
)) {
641 _ofDict
->setObject(propSymbol
, propObject
);
642 propSymbol
->release();
643 propObject
->release();
647 // Create the boot-args property if it is not in the dictionary.
648 if (_ofDict
->getObject("boot-args") == 0) {
649 propObject
= OSString::withCStringNoCopy("");
650 if (propObject
!= 0) {
651 _ofDict
->setObject("boot-args", propObject
);
652 propObject
->release();
656 // Create the 'aapl,panic-info' property if needed.
658 propDataLength
= *(UInt32
*)_piImage
;
659 if ((propDataLength
!= 0) && (propDataLength
< (_piPartitionSize
- 4))) {
660 propObject
= OSData::withBytes(_piImage
+ 4, propDataLength
);
661 _ofDict
->setObject(kIODTNVRAMPanicInfoKey
, propObject
);
662 propObject
->release();
664 // Clear the length from _piImage and mark dirty.
665 *(UInt32
*)_piImage
= 0;
666 _nvramImageDirty
= true;
670 owHeader
= (OWVariablesHeader
*)_ofImage
;
671 if (!validateOWChecksum(_ofImage
)) {
674 return kIOReturnBadMedia
;
679 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
683 case kOFVariableTypeBoolean
:
684 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
687 case kOFVariableTypeNumber
:
688 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
691 case kOFVariableTypeString
:
692 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
694 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
695 propName
= IONew(UInt8
, propDataLength
+ 1);
697 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
698 propName
[propDataLength
] = '\0';
699 propObject
= OSString::withCString((const char *)propName
);
700 IODelete(propName
, UInt8
, propDataLength
+ 1);
705 if (propObject
== 0) break;
707 _ofDict
->setObject(propSymbol
, propObject
);
708 propSymbol
->release();
709 propObject
->release();
712 // Create the boot-args property.
713 propSymbol
= OSSymbol::withCString("boot-command");
714 if (propSymbol
!= 0) {
715 propObject
= _ofDict
->getObject(propSymbol
);
716 if (propObject
!= 0) {
717 updateOWBootArgs(propSymbol
, propObject
);
719 propSymbol
->release();
723 return kIOReturnSuccess
;
726 IOReturn
IODTNVRAM::syncOFVariables(void)
729 UInt32 cnt
, length
, maxLength
;
730 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
731 UInt8
*buffer
, *tmpBuffer
;
732 const UInt8
*tmpData
;
733 const OSSymbol
*tmpSymbol
;
735 OSBoolean
*tmpBoolean
;
738 OSCollectionIterator
*iter
;
739 OWVariablesHeader
*owHeader
, *owHeaderOld
;
741 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
743 if (!_ofImageDirty
) return kIOReturnSuccess
;
745 if (getPlatform()->getBootROMType()) {
746 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
747 if (buffer
== 0) return kIOReturnNoMemory
;
748 bzero(buffer
, _ofPartitionSize
);
751 maxLength
= _ofPartitionSize
;
753 iter
= OSCollectionIterator::withCollection(_ofDict
);
754 if (iter
== 0) ok
= false;
757 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
758 if (tmpSymbol
== 0) break;
760 // Don't save 'aapl,panic-info'.
761 if (tmpSymbol
->isEqualTo(kIODTNVRAMPanicInfoKey
)) continue;
763 tmpObject
= _ofDict
->getObject(tmpSymbol
);
766 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
775 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
778 IODelete(buffer
, UInt8
, _ofPartitionSize
);
780 if (!ok
) return kIOReturnBadArgument
;
782 buffer
= IONew(UInt8
, _ofPartitionSize
);
783 if (buffer
== 0) return kIOReturnNoMemory
;
784 bzero(buffer
, _ofPartitionSize
);
786 owHeader
= (OWVariablesHeader
*)buffer
;
787 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
789 owHeader
->owMagic
= owHeaderOld
->owMagic
;
790 owHeader
->owVersion
= owHeaderOld
->owVersion
;
791 owHeader
->owPages
= owHeaderOld
->owPages
;
793 curOffset
= _ofPartitionSize
;
798 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
801 tmpObject
= _ofDict
->getObject(tmpSymbol
);
804 case kOFVariableTypeBoolean
:
805 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
806 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
809 case kOFVariableTypeNumber
:
810 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
811 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
814 case kOFVariableTypeString
:
815 tmpString
= OSDynamicCast(OSString
, tmpObject
);
816 tmpData
= (const UInt8
*)tmpString
->getCStringNoCopy();
817 tmpDataLength
= tmpString
->getLength();
819 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
824 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
825 curOffset
-= tmpDataLength
;
826 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
827 if (tmpDataLength
!= 0)
828 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
834 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
835 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
836 owHeader
->owNext
= 0;
838 owHeader
->owChecksum
= 0;
839 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
841 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
844 IODelete(buffer
, UInt8
, _ofPartitionSize
);
846 if (!ok
) return kIOReturnBadArgument
;
849 _ofImageDirty
= false;
850 _nvramImageDirty
= true;
852 return kIOReturnSuccess
;
856 const char *variableName
;
859 SInt32 variableOffset
;
861 typedef struct OFVariable OFVariable
;
864 kOWVariableOffsetNumber
= 8,
865 kOWVariableOffsetString
= 17
868 OFVariable gOFVariables
[] = {
869 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
870 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
871 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
872 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
873 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
874 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
875 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
876 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
877 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
878 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
879 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
880 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
881 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
882 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
883 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
884 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
885 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
886 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
887 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
888 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
889 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
890 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
891 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
892 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
893 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
894 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
895 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
896 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
897 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
898 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
899 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
900 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
901 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
902 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
903 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
904 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
905 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
906 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
907 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
908 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
909 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
910 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
911 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
912 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
913 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
914 {"boot-image", kOFVariableTypeData
, kOFVariablePermUserWrite
, -1},
915 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
918 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
922 ofVar
= gOFVariables
;
924 if ((ofVar
->variableName
== 0) ||
925 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
929 return ofVar
->variableType
;
932 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
936 ofVar
= gOFVariables
;
938 if ((ofVar
->variableName
== 0) ||
939 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
943 return ofVar
->variablePerm
;
946 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
947 UInt32
*propType
, UInt32
*propOffset
)
951 ofVar
= gOFVariables
;
953 if (ofVar
->variableName
== 0) return false;
955 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
960 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
961 *propType
= ofVar
->variableType
;
964 case kOFVariableTypeBoolean
:
965 *propOffset
= 1 << (31 - variableNumber
);
968 case kOFVariableTypeNumber
:
969 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
972 case kOFVariableTypeString
:
973 *propOffset
= variableNumber
- kOWVariableOffsetString
;
980 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
981 UInt8
*propData
, UInt32 propDataLength
,
982 const OSSymbol
**propSymbol
,
983 OSObject
**propObject
)
986 const OSSymbol
*tmpSymbol
;
991 // Create the symbol.
992 propName
[propNameLength
] = '\0';
993 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
994 propName
[propNameLength
] = '=';
995 if (tmpSymbol
== 0) {
999 propType
= getOFVariableType(tmpSymbol
);
1001 // Create the object.
1004 case kOFVariableTypeBoolean
:
1005 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
1006 tmpObject
= kOSBooleanTrue
;
1007 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
1008 tmpObject
= kOSBooleanFalse
;
1012 case kOFVariableTypeNumber
:
1013 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
1014 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
1017 case kOFVariableTypeString
:
1018 tmpString
= OSString::withCString((const char *)propData
);
1019 if (tmpString
!= 0) tmpObject
= tmpString
;
1022 case kOFVariableTypeData
:
1023 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
1027 if (tmpObject
== 0) {
1028 tmpSymbol
->release();
1032 *propSymbol
= tmpSymbol
;
1033 *propObject
= tmpObject
;
1038 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
1039 const OSSymbol
*propSymbol
, OSObject
*propObject
)
1041 const UInt8
*propName
;
1042 UInt32 propNameLength
, propDataLength
;
1043 UInt32 propType
, tmpValue
;
1044 OSBoolean
*tmpBoolean
= 0;
1045 OSNumber
*tmpNumber
= 0;
1046 OSString
*tmpString
= 0;
1047 OSData
*tmpData
= 0;
1049 propName
= (const UInt8
*)propSymbol
->getCStringNoCopy();
1050 propNameLength
= propSymbol
->getLength();
1051 propType
= getOFVariableType(propSymbol
);
1053 // Get the size of the data.
1054 propDataLength
= 0xFFFFFFFF;
1056 case kOFVariableTypeBoolean
:
1057 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
1058 if (tmpBoolean
!= 0) propDataLength
= 5;
1061 case kOFVariableTypeNumber
:
1062 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
1063 if (tmpNumber
!= 0) propDataLength
= 10;
1066 case kOFVariableTypeString
:
1067 tmpString
= OSDynamicCast(OSString
, propObject
);
1068 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
1071 case kOFVariableTypeData
:
1072 tmpData
= OSDynamicCast(OSData
, propObject
);
1074 tmpData
= escapeDataToData(tmpData
);
1075 propDataLength
= tmpData
->getLength();
1080 // Make sure the propertySize is known and will fit.
1081 if (propDataLength
== 0xFFFFFFFF) return false;
1082 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
1084 // Copy the property name equal sign.
1085 sprintf((char *)buffer
, "%s=", propName
);
1086 buffer
+= propNameLength
+ 1;
1089 case kOFVariableTypeBoolean
:
1090 if (tmpBoolean
->getValue()) {
1091 strcpy((char *)buffer
, "true");
1093 strcpy((char *)buffer
, "false");
1097 case kOFVariableTypeNumber
:
1098 tmpValue
= tmpNumber
->unsigned32BitValue();
1099 if (tmpValue
== 0xFFFFFFFF) {
1100 strcpy((char *)buffer
, "-1");
1101 } else if (tmpValue
< 1000) {
1102 sprintf((char *)buffer
, "%ld", tmpValue
);
1104 sprintf((char *)buffer
, "0x%lx", tmpValue
);
1108 case kOFVariableTypeString
:
1109 strcpy((char *)buffer
, tmpString
->getCStringNoCopy());
1112 case kOFVariableTypeData
:
1113 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
1118 propDataLength
= strlen((const char *)buffer
);
1120 *length
= propNameLength
+ propDataLength
+ 2;
1126 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
1128 UInt32 cnt
, checksum
= 0;
1129 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1131 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1132 checksum
+= tmpBuffer
[cnt
];
1134 return checksum
% 0x0000FFFF;
1137 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
1139 UInt32 cnt
, checksum
, sum
= 0;
1140 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
1142 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
1143 sum
+= tmpBuffer
[cnt
];
1145 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
1146 if (checksum
== 0x10000) checksum
--;
1147 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
1149 return checksum
== 0;
1152 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
1154 bool wasBootArgs
, bootr
= false;
1156 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
1157 const UInt8
*bootCommandData
, *bootArgsData
;
1159 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
1161 tmpString
= OSDynamicCast(OSString
, value
);
1162 if (tmpString
== 0) return;
1164 if (key
->isEqualTo("boot-command")) {
1165 wasBootArgs
= false;
1166 bootCommand
= tmpString
;
1167 } else if (key
->isEqualTo("boot-args")) {
1169 bootArgs
= tmpString
;
1170 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1171 if (bootCommand
== 0) return;
1174 bootCommandData
= (const UInt8
*)bootCommand
->getCStringNoCopy();
1175 bootCommandDataLength
= bootCommand
->getLength();
1177 if (bootCommandData
== 0) return;
1179 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1180 if ((bootCommandData
[cnt
] == 'b') &&
1181 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1183 while (bootCommandData
[cnt
] == ' ') cnt
++;
1189 _ofDict
->removeObject("boot-args");
1194 bootArgsData
= (const UInt8
*)bootArgs
->getCStringNoCopy();
1195 bootArgsDataLength
= bootArgs
->getLength();
1196 if (bootArgsData
== 0) return;
1198 tmpDataLength
= cnt
+ bootArgsDataLength
;
1199 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1200 if (tmpData
== 0) return;
1202 strncpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1203 tmpData
[cnt
] = '\0';
1204 strcat((char *)tmpData
, (const char *)bootArgsData
);
1206 bootCommand
= OSString::withCString((const char *)tmpData
);
1207 if (bootCommand
!= 0) {
1208 _ofDict
->setObject("boot-command", bootCommand
);
1209 bootCommand
->release();
1212 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1214 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1215 if (bootArgs
!= 0) {
1216 _ofDict
->setObject("boot-args", bootArgs
);
1217 bootArgs
->release();
1223 // Private methods for Name Registry access.
1226 kMaxNVNameLength
= 4,
1227 kMaxNVDataLength
= 8
1230 #pragma options align=mac68k
1231 struct NVRAMProperty
1233 IONVRAMDescriptor header
;
1235 UInt8 name
[ kMaxNVNameLength
];
1237 UInt8 data
[ kMaxNVDataLength
];
1239 #pragma options align=reset
1241 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1246 nvEnd
= *((UInt16
*)_nrImage
);
1247 if(getPlatform()->getBootROMType()) {
1248 // on NewWorld, offset to partition start
1251 // on old world, absolute
1252 nvEnd
-= _nrPartitionOffset
;
1254 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1258 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1259 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1263 offset
+= sizeof(NVRAMProperty
);
1266 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1274 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1275 const OSSymbol
**name
,
1278 IONVRAMDescriptor hdr
;
1279 NVRAMProperty
*prop
;
1283 char nameBuf
[kMaxNVNameLength
+ 1];
1285 if (_nrImage
== 0) return kIOReturnUnsupported
;
1286 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1288 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1289 if (err
!= kIOReturnSuccess
) return err
;
1291 if (searchNVRAMProperty(&hdr
, &offset
)) {
1292 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1294 length
= prop
->nameLength
;
1295 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1296 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1297 nameBuf
[length
] = 0;
1298 *name
= OSSymbol::withCString(nameBuf
);
1300 length
= prop
->dataLength
;
1301 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1302 *value
= OSData::withBytes(prop
->data
, length
);
1304 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1305 else return kIOReturnNoMemory
;
1308 return kIOReturnNoResources
;
1311 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1312 const OSSymbol
*name
,
1315 IONVRAMDescriptor hdr
;
1316 NVRAMProperty
*prop
;
1317 IOByteCount nameLength
;
1318 IOByteCount dataLength
;
1324 if (_nrImage
== 0) return kIOReturnUnsupported
;
1325 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1327 nameLength
= name
->getLength();
1328 dataLength
= value
->getLength();
1329 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1330 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1332 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1333 if (err
!= kIOReturnSuccess
) return err
;
1335 exists
= searchNVRAMProperty(&hdr
, &offset
);
1336 if (offset
== 0) return kIOReturnNoMemory
;
1338 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1339 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1341 prop
->nameLength
= nameLength
;
1342 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1343 prop
->dataLength
= dataLength
;
1344 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1347 nvLength
= offset
+ sizeof(NVRAMProperty
);
1348 if (getPlatform()->getBootROMType())
1351 nvLength
+= _nrPartitionOffset
;
1352 *((UInt16
*)_nrImage
) = nvLength
;
1355 _nvramImageDirty
= true;
1360 OSData
*IODTNVRAM::unescapeBytesToData(const UInt8
*bytes
, UInt32 length
)
1363 UInt32 totalLength
= 0;
1368 // Calculate the actual length of the data.
1371 for (cnt
= 0; cnt
< length
;) {
1372 byte
= bytes
[cnt
++];
1374 byte
= bytes
[cnt
++];
1382 totalLength
+= cnt2
;
1386 // Create an empty OSData of the correct size.
1387 data
= OSData::withCapacity(totalLength
);
1389 for (cnt
= 0; cnt
< length
;) {
1390 byte
= bytes
[cnt
++];
1392 byte
= bytes
[cnt
++];
1394 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1397 data
->appendByte(byte
, cnt2
);
1405 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1408 const UInt8
* startPtr
;
1409 const UInt8
* endPtr
;
1410 const UInt8
* wherePtr
;
1414 wherePtr
= (const UInt8
*) value
->getBytesNoCopy();
1415 endPtr
= wherePtr
+ value
->getLength();
1417 result
= OSData::withCapacity(endPtr
- wherePtr
);
1421 while (wherePtr
< endPtr
) {
1422 startPtr
= wherePtr
;
1424 if ((byte
== 0x00) || (byte
== 0xFF)) {
1426 ((wherePtr
- startPtr
) < 0x80) && (wherePtr
< endPtr
) && (byte
== *wherePtr
);
1428 ok
&= result
->appendByte(0xff, 1);
1429 byte
= (byte
& 0x80) | (wherePtr
- startPtr
);
1431 ok
&= result
->appendByte(byte
, 1);
1433 ok
&= result
->appendByte(0, 1);
1443 static bool IsApplePropertyName(const char * propName
)
1446 while ((c
= *propName
++)) {
1447 if ((c
>= 'A') && (c
<= 'Z'))
1454 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1455 const OSSymbol
**name
,
1458 IOReturn err
= kIOReturnNoResources
;
1460 const UInt8
*startPtr
;
1461 const UInt8
*endPtr
;
1462 const UInt8
*wherePtr
;
1463 const UInt8
*nvPath
= 0;
1464 const char *nvName
= 0;
1465 const char *resultName
= 0;
1466 const UInt8
*resultValue
= 0;
1467 UInt32 resultValueLen
= 0;
1470 if (_ofDict
== 0) return err
;
1471 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1472 if (data
== 0) return err
;
1474 startPtr
= (const UInt8
*) data
->getBytesNoCopy();
1475 endPtr
= startPtr
+ data
->getLength();
1477 wherePtr
= startPtr
;
1478 while (wherePtr
< endPtr
) {
1479 byte
= *(wherePtr
++);
1485 else if (nvName
== 0)
1486 nvName
= (const char *) startPtr
;
1488 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1490 compareEntry
->release();
1491 if (entry
== compareEntry
) {
1492 bool appleProp
= IsApplePropertyName(nvName
);
1493 if (!appleProp
|| !resultName
) {
1494 resultName
= nvName
;
1495 resultValue
= startPtr
;
1496 resultValueLen
= wherePtr
- startPtr
- 1;
1504 startPtr
= wherePtr
;
1507 *name
= OSSymbol::withCString(resultName
);
1508 *value
= unescapeBytesToData(resultValue
, resultValueLen
);
1509 if ((*name
!= 0) && (*value
!= 0))
1510 err
= kIOReturnSuccess
;
1512 err
= kIOReturnNoMemory
;
1517 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1518 const OSSymbol
*propName
,
1523 const UInt8
*startPtr
;
1524 const UInt8
*propStart
;
1525 const UInt8
*endPtr
;
1526 const UInt8
*wherePtr
;
1527 const UInt8
*nvPath
= 0;
1528 const char *nvName
= 0;
1533 bool settingAppleProp
;
1535 if (_ofDict
== 0) return kIOReturnNoResources
;
1537 settingAppleProp
= IsApplePropertyName(propName
->getCStringNoCopy());
1539 // copy over existing properties for other entries
1541 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1543 startPtr
= (const UInt8
*) oldData
->getBytesNoCopy();
1544 endPtr
= startPtr
+ oldData
->getLength();
1546 propStart
= startPtr
;
1547 wherePtr
= startPtr
;
1548 while (wherePtr
< endPtr
) {
1549 byte
= *(wherePtr
++);
1554 else if (nvName
== 0)
1555 nvName
= (const char *) startPtr
;
1557 IORegistryEntry
* compareEntry
= IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
);
1559 compareEntry
->release();
1560 if (entry
== compareEntry
) {
1561 if ((settingAppleProp
&& propName
->isEqualTo(nvName
))
1562 || (!settingAppleProp
&& !IsApplePropertyName(nvName
))) {
1563 // delete old property (nvPath -> wherePtr)
1564 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1566 ok
&= data
->appendBytes(wherePtr
, endPtr
- wherePtr
);
1574 startPtr
= wherePtr
;
1578 // make the new property
1582 data
= OSData::withData(oldData
);
1584 data
= OSData::withCapacity(16);
1586 return kIOReturnNoMemory
;
1589 if (value
&& value
->getLength()) {
1590 // get entries in path
1591 OSArray
*array
= OSArray::withCapacity(5);
1594 return kIOReturnNoMemory
;
1597 array
->setObject(entry
);
1598 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1601 for (int i
= array
->getCount() - 3;
1602 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1605 name
= entry
->getName(gIODTPlane
);
1606 comp
= entry
->getLocation(gIODTPlane
);
1607 if( comp
&& (0 == strcmp("pci", name
))
1608 && (0 == strcmp("80000000", comp
))) {
1610 comp
= "/pci@80000000";
1613 ok
&= data
->appendBytes("/@", 2);
1617 ok
&= data
->appendByte('/', 1);
1621 ok
&= data
->appendBytes(comp
, strlen(comp
));
1623 ok
&= data
->appendByte(0, 1);
1627 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1629 // append escaped data
1630 oldData
= escapeDataToData(value
);
1631 ok
&= (oldData
!= 0);
1633 ok
&= data
->appendBytes(oldData
);
1636 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1638 _ofImageDirty
= true;
1642 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;