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 OSDefineMetaClassAndStructors(IODTNVRAM
, IOService
);
33 bool IODTNVRAM::init(IORegistryEntry
*old
, const IORegistryPlane
*plane
)
37 if (!super::init(old
, plane
)) return false;
39 dict
= OSDictionary::withCapacity(1);
40 if (dict
== 0) return false;
41 setPropertyTable(dict
);
43 _nvramImage
= IONew(UInt8
, kIODTNVRAMImageSize
);
44 if (_nvramImage
== 0) return false;
46 _nvramPartitionOffsets
= OSDictionary::withCapacity(1);
47 if (_nvramPartitionOffsets
== 0) return false;
49 _nvramPartitionLengths
= OSDictionary::withCapacity(1);
50 if (_nvramPartitionLengths
== 0) return false;
52 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
53 if (_registryPropertiesKey
== 0) return false;
58 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
61 UInt32 partitionOffset
, partitionLength
;
62 UInt32 freePartitionOffset
, freePartitionSize
;
63 UInt32 currentLength
, currentOffset
= 0;
64 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
66 if (_nvramController
!= 0) return;
68 _nvramController
= nvram
;
70 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
72 // Find the offsets for the OF, XPRAM, and NameRegistry partitions.
73 _ofPartitionOffset
= 0xFFFFFFFF;
74 _xpramPartitionOffset
= 0xFFFFFFFF;
75 _nrPartitionOffset
= 0xFFFFFFFF;
76 freePartitionOffset
= 0xFFFFFFFF;
77 freePartitionSize
= 0;
78 if (getPlatform()->getBootROMType()) {
79 // Look through the partitions to find the OF, MacOS partitions.
80 while (currentOffset
< kIODTNVRAMImageSize
) {
81 currentLength
= ((UInt16
*)(_nvramImage
+ currentOffset
))[1] * 16;
83 partitionOffset
= currentOffset
+ 16;
84 partitionLength
= currentLength
- 16;
86 if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
87 kIODTNVRAMOFPartitionName
, 12) == 0) {
88 _ofPartitionOffset
= partitionOffset
;
89 _ofPartitionSize
= partitionLength
;
90 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
91 kIODTNVRAMXPRAMPartitionName
, 12) == 0) {
92 _xpramPartitionOffset
= partitionOffset
;
93 _xpramPartitionSize
= kIODTNVRAMXPRAMSize
;
94 _nrPartitionOffset
= _xpramPartitionOffset
+ _xpramPartitionSize
;
95 _nrPartitionSize
= partitionLength
- _xpramPartitionSize
;
96 } else if (strncmp((const char *)_nvramImage
+ currentOffset
+ 4,
97 kIODTNVRAMFreePartitionName
, 12) == 0) {
98 freePartitionOffset
= currentOffset
;
99 freePartitionSize
= currentLength
;
101 // Construct the partition ID from the signature and name.
102 sprintf(partitionID
, "0x%02x,",
103 *(UInt8
*)(_nvramImage
+ currentOffset
));
104 strncpy(partitionID
+ 5,
105 (const char *)(_nvramImage
+ currentOffset
+ 4), 12);
106 partitionID
[17] = '\0';
108 partitionOffsetNumber
= OSNumber::withNumber(partitionOffset
, 32);
109 partitionLengthNumber
= OSNumber::withNumber(partitionLength
, 32);
111 // Save the partition offset and length
112 _nvramPartitionOffsets
->setObject(partitionID
, partitionOffsetNumber
);
113 _nvramPartitionLengths
->setObject(partitionID
, partitionLengthNumber
);
115 partitionOffsetNumber
->release();
116 partitionLengthNumber
->release();
118 currentOffset
+= currentLength
;
121 // Use the fixed address for old world machines.
122 _ofPartitionOffset
= 0x1800;
123 _ofPartitionSize
= 0x0800;
124 _xpramPartitionOffset
= 0x1300;
125 _xpramPartitionSize
= 0x0100;
126 _nrPartitionOffset
= 0x1400;
127 _nrPartitionSize
= 0x0400;
130 if (_ofPartitionOffset
!= 0xFFFFFFFF)
131 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
132 if (_xpramPartitionOffset
!= 0xFFFFFFFF)
133 _xpramImage
= _nvramImage
+ _xpramPartitionOffset
;
134 if (_nrPartitionOffset
!= 0xFFFFFFFF)
135 _nrImage
= _nvramImage
+ _nrPartitionOffset
;
140 void IODTNVRAM::sync(void)
142 if (!_nvramImageDirty
&& !_ofImageDirty
) return;
146 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
147 _nvramController
->sync();
149 _nvramImageDirty
= false;
152 bool IODTNVRAM::serializeProperties(OSSerialize
*serialize
) const
157 OSDictionary
*dict
, *tmpDict
= 0;
158 OSCollectionIterator
*iter
= 0;
160 if (_ofDict
== 0) return false;
162 // Verify permissions.
163 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
164 if (result
!= kIOReturnSuccess
) {
165 tmpDict
= OSDictionary::withCapacity(1);
166 if (tmpDict
== 0) return false;
168 iter
= OSCollectionIterator::withCollection(_ofDict
);
169 if (iter
== 0) return false;
172 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
175 variablePerm
= getOFVariablePerm(key
);
176 if (variablePerm
!= kOFVariablePermRootOnly
) {
177 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
185 result
= dict
->serialize(serialize
);
187 if (tmpDict
!= 0) tmpDict
->release();
188 if (iter
!= 0) iter
->release();
193 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
198 if (_ofDict
== 0) return 0;
200 // Verify permissions.
201 result
= IOUserClient::clientHasPrivilege(current_task(), "root");
202 if (result
!= kIOReturnSuccess
) {
203 variablePerm
= getOFVariablePerm(aKey
);
204 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
207 return _ofDict
->getObject(aKey
);
210 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
212 const OSSymbol
*keySymbol
;
213 OSObject
*theObject
= 0;
215 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
216 if (keySymbol
!= 0) {
217 theObject
= getProperty(keySymbol
);
218 keySymbol
->release();
224 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
227 UInt32 propType
, propPerm
;
229 OSObject
*propObject
= 0;
231 if (_ofDict
== 0) return false;
233 // Verify permissions.
234 result
= IOUserClient::clientHasPrivilege(current_task(), "root");
235 if (result
!= kIOReturnSuccess
) {
236 propPerm
= getOFVariablePerm(aKey
);
237 if (propPerm
!= kOFVariablePermUserWrite
) return false;
240 // Don't allow creation of new properties on old world machines.
241 if (getPlatform()->getBootROMType() == 0) {
242 if (_ofDict
->getObject(aKey
) == 0) return false;
245 // Make sure the object is of the correct type.
246 propType
= getOFVariableType(aKey
);
248 case kOFVariableTypeBoolean
:
249 propObject
= OSDynamicCast(OSBoolean
, anObject
);
252 case kOFVariableTypeNumber
:
253 propObject
= OSDynamicCast(OSNumber
, anObject
);
256 case kOFVariableTypeString
:
257 propObject
= OSDynamicCast(OSString
, anObject
);
260 case kOFVariableTypeData
:
261 propObject
= OSDynamicCast(OSData
, anObject
);
262 if (propObject
== 0) {
263 tmpString
= OSDynamicCast(OSString
, anObject
);
264 if (tmpString
!= 0) {
265 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
266 tmpString
->getLength());
272 if (propObject
== 0) return false;
274 result
= _ofDict
->setObject(aKey
, propObject
);
277 if (getPlatform()->getBootROMType() == 0) {
278 updateOWBootArgs(aKey
, propObject
);
281 _ofImageDirty
= true;
287 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
293 OSCollectionIterator
*iter
;
295 dict
= OSDynamicCast(OSDictionary
, properties
);
296 if (dict
== 0) return kIOReturnBadArgument
;
298 iter
= OSCollectionIterator::withCollection(dict
);
299 if (iter
== 0) return kIOReturnBadArgument
;
302 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
305 object
= dict
->getObject(key
);
306 if (object
== 0) continue;
308 result
= setProperty(key
, object
);
313 if (result
) return kIOReturnSuccess
;
314 else return kIOReturnError
;
317 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
320 if (_xpramImage
== 0) return kIOReturnUnsupported
;
322 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
323 (offset
+ length
> kIODTNVRAMXPRAMSize
))
324 return kIOReturnBadArgument
;
326 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
328 return kIOReturnSuccess
;
331 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
334 if (_xpramImage
== 0) return kIOReturnUnsupported
;
336 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
337 (offset
+ length
> kIODTNVRAMXPRAMSize
))
338 return kIOReturnBadArgument
;
340 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
342 _nvramImageDirty
= true;
344 return kIOReturnSuccess
;
347 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
348 const OSSymbol
**name
,
353 if (getPlatform()->getBootROMType())
354 err
= readNVRAMPropertyType1(entry
, name
, value
);
356 err
= readNVRAMPropertyType0(entry
, name
, value
);
361 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
362 const OSSymbol
*name
,
367 if (getPlatform()->getBootROMType())
368 err
= writeNVRAMPropertyType1(entry
, name
, value
);
370 err
= writeNVRAMPropertyType0(entry
, name
, value
);
375 OSDictionary
*IODTNVRAM::getNVRAMPartitions(void)
377 return _nvramPartitionLengths
;
380 IOReturn
IODTNVRAM::readNVRAMPartition(const OSSymbol
*partitionID
,
381 IOByteCount offset
, UInt8
*buffer
,
384 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
385 UInt32 partitionOffset
, partitionLength
;
387 partitionOffsetNumber
=
388 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
389 partitionLengthNumber
=
390 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
392 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
393 return kIOReturnNotFound
;
395 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
396 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
398 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
399 (offset
+ length
> partitionLength
))
400 return kIOReturnBadArgument
;
402 bcopy(_nvramImage
+ partitionOffset
+ offset
, buffer
, length
);
404 return kIOReturnSuccess
;
407 IOReturn
IODTNVRAM::writeNVRAMPartition(const OSSymbol
*partitionID
,
408 IOByteCount offset
, UInt8
*buffer
,
411 OSNumber
*partitionOffsetNumber
, *partitionLengthNumber
;
412 UInt32 partitionOffset
, partitionLength
;
414 partitionOffsetNumber
=
415 (OSNumber
*)_nvramPartitionOffsets
->getObject(partitionID
);
416 partitionLengthNumber
=
417 (OSNumber
*)_nvramPartitionLengths
->getObject(partitionID
);
419 if ((partitionOffsetNumber
== 0) || (partitionLengthNumber
== 0))
420 return kIOReturnNotFound
;
422 partitionOffset
= partitionOffsetNumber
->unsigned32BitValue();
423 partitionLength
= partitionLengthNumber
->unsigned32BitValue();
425 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
426 (offset
+ length
> partitionLength
))
427 return kIOReturnBadArgument
;
429 bcopy(buffer
, _nvramImage
+ partitionOffset
+ offset
, length
);
431 _nvramImageDirty
= true;
433 return kIOReturnSuccess
;
436 // Private methods for Open Firmware variable access.
438 struct OWVariablesHeader
{
453 typedef struct OWVariablesHeader OWVariablesHeader
;
455 IOReturn
IODTNVRAM::initOFVariables(void)
457 UInt32 cnt
, propOffset
, propType
;
458 UInt8
*propName
, *propData
;
459 UInt32 propNameLength
, propDataLength
;
460 const OSSymbol
*propSymbol
;
461 OSObject
*propObject
;
462 OWVariablesHeader
*owHeader
;
464 if (_ofImage
== 0) return kIOReturnNotReady
;
466 _ofDict
= OSDictionary::withCapacity(1);
467 if (_ofDict
== 0) return kIOReturnNoMemory
;
469 if (getPlatform()->getBootROMType()) {
471 while (cnt
< _ofPartitionSize
) {
472 // Break if there is no name.
473 if (_ofImage
[cnt
] == '\0') break;
475 // Find the length of the name.
476 propName
= _ofImage
+ cnt
;
477 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
479 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
482 // Break if the name goes past the end of the partition.
483 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
484 cnt
+= propNameLength
+ 1;
486 propData
= _ofImage
+ cnt
;
487 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
489 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
492 // Break if the data goes past the end of the partition.
493 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
494 cnt
+= propDataLength
+ 1;
496 if (convertPropToObject(propName
, propNameLength
,
497 propData
, propDataLength
,
498 &propSymbol
, &propObject
)) {
499 _ofDict
->setObject(propSymbol
, propObject
);
500 propSymbol
->release();
501 propObject
->release();
505 // Create the boot-args property if it is not in the dictionary.
506 if (_ofDict
->getObject("boot-args") == 0) {
507 propObject
= OSString::withCStringNoCopy("");
508 if (propObject
!= 0) {
509 _ofDict
->setObject("boot-args", propObject
);
510 propObject
->release();
514 owHeader
= (OWVariablesHeader
*)_ofImage
;
515 if (!validateOWChecksum(_ofImage
)) {
518 return kIOReturnBadMedia
;
523 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
527 case kOFVariableTypeBoolean
:
528 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
531 case kOFVariableTypeNumber
:
532 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
535 case kOFVariableTypeString
:
536 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
538 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
539 propName
= IONew(UInt8
, propDataLength
+ 1);
541 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
542 propName
[propDataLength
] = '\0';
543 propObject
= OSString::withCString((const char *)propName
);
544 IODelete(propName
, UInt8
, propDataLength
+ 1);
549 if (propObject
== 0) break;
551 _ofDict
->setObject(propSymbol
, propObject
);
552 propSymbol
->release();
553 propObject
->release();
556 // Create the boot-args property.
557 propSymbol
= OSSymbol::withCString("boot-command");
558 if (propSymbol
!= 0) {
559 propObject
= _ofDict
->getObject(propSymbol
);
560 if (propObject
!= 0) {
561 updateOWBootArgs(propSymbol
, propObject
);
563 propSymbol
->release();
567 return kIOReturnSuccess
;
570 IOReturn
IODTNVRAM::syncOFVariables(void)
573 UInt32 cnt
, length
, maxLength
;
574 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
575 UInt8
*buffer
, *tmpBuffer
, *tmpData
;
576 const OSSymbol
*tmpSymbol
;
578 OSBoolean
*tmpBoolean
;
581 OSCollectionIterator
*iter
;
582 OWVariablesHeader
*owHeader
, *owHeaderOld
;
584 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
586 if (!_ofImageDirty
) return kIOReturnSuccess
;
588 if (getPlatform()->getBootROMType()) {
589 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
590 if (buffer
== 0) return kIOReturnNoMemory
;
591 bzero(buffer
, _ofPartitionSize
);
594 maxLength
= _ofPartitionSize
;
596 iter
= OSCollectionIterator::withCollection(_ofDict
);
597 if (iter
== 0) ok
= false;
600 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
601 if (tmpSymbol
== 0) break;
603 tmpObject
= _ofDict
->getObject(tmpSymbol
);
606 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
615 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
618 IODelete(buffer
, UInt8
, _ofPartitionSize
);
620 if (!ok
) return kIOReturnBadArgument
;
622 buffer
= IONew(UInt8
, _ofPartitionSize
);
623 if (buffer
== 0) return kIOReturnNoMemory
;
624 bzero(buffer
, _ofPartitionSize
);
626 owHeader
= (OWVariablesHeader
*)buffer
;
627 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
629 owHeader
->owMagic
= owHeaderOld
->owMagic
;
630 owHeader
->owVersion
= owHeaderOld
->owVersion
;
631 owHeader
->owPages
= owHeaderOld
->owPages
;
633 curOffset
= _ofPartitionSize
;
638 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
641 tmpObject
= _ofDict
->getObject(tmpSymbol
);
644 case kOFVariableTypeBoolean
:
645 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
646 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
649 case kOFVariableTypeNumber
:
650 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
651 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
654 case kOFVariableTypeString
:
655 tmpString
= OSDynamicCast(OSString
, tmpObject
);
656 tmpData
= (UInt8
*) tmpString
->getCStringNoCopy();
657 tmpDataLength
= tmpString
->getLength();
659 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
664 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
665 curOffset
-= tmpDataLength
;
666 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
667 if (tmpDataLength
!= 0)
668 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
674 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
675 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
676 owHeader
->owNext
= 0;
678 owHeader
->owChecksum
= 0;
679 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
681 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
684 IODelete(buffer
, UInt8
, _ofPartitionSize
);
686 if (!ok
) return kIOReturnBadArgument
;
689 _ofImageDirty
= false;
690 _nvramImageDirty
= true;
692 return kIOReturnSuccess
;
699 SInt32 variableOffset
;
701 typedef struct OFVariable OFVariable
;
704 kOWVariableOffsetNumber
= 8,
705 kOWVariableOffsetString
= 17
708 OFVariable gOFVariables
[] = {
709 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
710 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
711 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
712 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
713 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
714 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
715 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
716 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
717 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
718 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
719 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
720 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
721 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
722 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
723 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
724 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
725 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
726 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
727 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
728 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
729 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
730 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
731 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
732 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
733 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
734 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
735 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
736 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
737 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
738 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
739 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
740 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
741 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
742 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
743 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
744 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
745 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
746 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
747 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
748 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
749 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
750 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
751 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
752 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
753 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
754 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
757 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
761 ofVar
= gOFVariables
;
763 if ((ofVar
->variableName
== 0) ||
764 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
768 return ofVar
->variableType
;
771 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
775 ofVar
= gOFVariables
;
777 if ((ofVar
->variableName
== 0) ||
778 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
782 return ofVar
->variablePerm
;
785 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
786 UInt32
*propType
, UInt32
*propOffset
)
790 ofVar
= gOFVariables
;
792 if (ofVar
->variableName
== 0) return false;
794 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
799 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
800 *propType
= ofVar
->variableType
;
803 case kOFVariableTypeBoolean
:
804 *propOffset
= 1 << (31 - variableNumber
);
807 case kOFVariableTypeNumber
:
808 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
811 case kOFVariableTypeString
:
812 *propOffset
= variableNumber
- kOWVariableOffsetString
;
819 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
820 UInt8
*propData
, UInt32 propDataLength
,
821 const OSSymbol
**propSymbol
,
822 OSObject
**propObject
)
825 const OSSymbol
*tmpSymbol
;
830 // Create the symbol.
831 propName
[propNameLength
] = '\0';
832 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
833 propName
[propNameLength
] = '=';
834 if (tmpSymbol
== 0) {
838 propType
= getOFVariableType(tmpSymbol
);
840 // Create the object.
843 case kOFVariableTypeBoolean
:
844 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
845 tmpObject
= kOSBooleanTrue
;
846 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
847 tmpObject
= kOSBooleanFalse
;
851 case kOFVariableTypeNumber
:
852 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
853 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
856 case kOFVariableTypeString
:
857 tmpString
= OSString::withCString((const char *)propData
);
858 if (tmpString
!= 0) tmpObject
= tmpString
;
861 case kOFVariableTypeData
:
862 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
866 if (tmpObject
== 0) {
867 tmpSymbol
->release();
871 *propSymbol
= tmpSymbol
;
872 *propObject
= tmpObject
;
877 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
878 const OSSymbol
*propSymbol
, OSObject
*propObject
)
881 UInt32 propNameLength
, propDataLength
;
882 UInt32 propType
, tmpValue
;
883 OSBoolean
*tmpBoolean
= 0;
884 OSNumber
*tmpNumber
= 0;
885 OSString
*tmpString
= 0;
888 propName
= (UInt8
*)propSymbol
->getCStringNoCopy();
889 propNameLength
= propSymbol
->getLength();
890 propType
= getOFVariableType(propSymbol
);
892 // Get the size of the data.
893 propDataLength
= 0xFFFFFFFF;
895 case kOFVariableTypeBoolean
:
896 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
897 if (tmpBoolean
!= 0) propDataLength
= 5;
900 case kOFVariableTypeNumber
:
901 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
902 if (tmpNumber
!= 0) propDataLength
= 10;
905 case kOFVariableTypeString
:
906 tmpString
= OSDynamicCast(OSString
, propObject
);
907 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
910 case kOFVariableTypeData
:
911 tmpData
= OSDynamicCast(OSData
, propObject
);
913 tmpData
= escapeDataToData(tmpData
);
914 propDataLength
= tmpData
->getLength();
919 // Make sure the propertySize is known and will fit.
920 if (propDataLength
== 0xFFFFFFFF) return false;
921 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
923 // Copy the property name equal sign.
924 sprintf((char *)buffer
, "%s=", propName
);
925 buffer
+= propNameLength
+ 1;
928 case kOFVariableTypeBoolean
:
929 if (tmpBoolean
->getValue()) {
930 strcpy((char *)buffer
, "true");
932 strcpy((char *)buffer
, "false");
936 case kOFVariableTypeNumber
:
937 tmpValue
= tmpNumber
->unsigned32BitValue();
938 if (tmpValue
== 0xFFFFFFFF) {
939 strcpy((char *)buffer
, "-1");
940 } else if (tmpValue
< 1000) {
941 sprintf((char *)buffer
, "%ld", tmpValue
);
943 sprintf((char *)buffer
, "0x%lx", tmpValue
);
947 case kOFVariableTypeString
:
948 strcpy((char *)buffer
, tmpString
->getCStringNoCopy());
951 case kOFVariableTypeData
:
952 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
957 propDataLength
= strlen((const char *)buffer
);
959 *length
= propNameLength
+ propDataLength
+ 2;
965 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
967 UInt32 cnt
, checksum
= 0;
968 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
970 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
971 checksum
+= tmpBuffer
[cnt
];
973 return checksum
% 0x0000FFFF;
976 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
978 UInt32 cnt
, checksum
, sum
= 0;
979 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
981 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
982 sum
+= tmpBuffer
[cnt
];
984 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
985 if (checksum
== 0x10000) checksum
--;
986 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
988 return checksum
== 0;
991 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
993 bool wasBootArgs
, bootr
= false;
995 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
996 UInt8
*bootCommandData
, *bootArgsData
, *tmpData
;
997 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
999 tmpString
= OSDynamicCast(OSString
, value
);
1000 if (tmpString
== 0) return;
1002 if (key
->isEqualTo("boot-command")) {
1003 wasBootArgs
= false;
1004 bootCommand
= tmpString
;
1005 } else if (key
->isEqualTo("boot-args")) {
1007 bootArgs
= tmpString
;
1008 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
1009 if (bootCommand
== 0) return;
1012 bootCommandData
= (UInt8
*)bootCommand
->getCStringNoCopy();
1013 bootCommandDataLength
= bootCommand
->getLength();
1015 if (bootCommandData
== 0) return;
1017 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
1018 if ((bootCommandData
[cnt
] == 'b') &&
1019 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
1021 while (bootCommandData
[cnt
] == ' ') cnt
++;
1027 _ofDict
->removeObject("boot-args");
1032 bootArgsData
= (UInt8
*)bootArgs
->getCStringNoCopy();
1033 bootArgsDataLength
= bootArgs
->getLength();
1034 if (bootArgsData
== 0) return;
1036 tmpDataLength
= cnt
+ bootArgsDataLength
;
1037 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
1038 if (tmpData
== 0) return;
1040 strncpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
1041 tmpData
[cnt
] = '\0';
1042 strcat((char *)tmpData
, (const char *)bootArgsData
);
1044 bootCommand
= OSString::withCString((const char *)tmpData
);
1045 if (bootCommand
!= 0) {
1046 _ofDict
->setObject("boot-command", bootCommand
);
1047 bootCommand
->release();
1050 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
1052 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
1053 if (bootArgs
!= 0) {
1054 _ofDict
->setObject("boot-args", bootArgs
);
1055 bootArgs
->release();
1061 // Private methods for Name Registry access.
1064 kMaxNVNameLength
= 4,
1065 kMaxNVDataLength
= 8
1068 #pragma options align=mac68k
1069 struct NVRAMProperty
1071 IONVRAMDescriptor header
;
1073 UInt8 name
[ kMaxNVNameLength
];
1075 UInt8 data
[ kMaxNVDataLength
];
1077 #pragma options align=reset
1079 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
1084 nvEnd
= *((UInt16
*)_nrImage
);
1085 if(getPlatform()->getBootROMType()) {
1086 // on NewWorld, offset to partition start
1089 // on old world, absolute
1090 nvEnd
-= _nrPartitionOffset
;
1092 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1096 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1097 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1101 offset
+= sizeof(NVRAMProperty
);
1104 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1112 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1113 const OSSymbol
**name
,
1116 IONVRAMDescriptor hdr
;
1117 NVRAMProperty
*prop
;
1121 char nameBuf
[kMaxNVNameLength
+ 1];
1123 if (_nrImage
== 0) return kIOReturnUnsupported
;
1124 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1126 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1127 if (err
!= kIOReturnSuccess
) return err
;
1129 if (searchNVRAMProperty(&hdr
, &offset
)) {
1130 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1132 length
= prop
->nameLength
;
1133 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1134 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1135 nameBuf
[length
] = 0;
1136 *name
= OSSymbol::withCString(nameBuf
);
1138 length
= prop
->dataLength
;
1139 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1140 *value
= OSData::withBytes(prop
->data
, length
);
1142 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1143 else return kIOReturnNoMemory
;
1146 return kIOReturnNoResources
;
1149 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1150 const OSSymbol
*name
,
1153 IONVRAMDescriptor hdr
;
1154 NVRAMProperty
*prop
;
1155 IOByteCount nameLength
;
1156 IOByteCount dataLength
;
1162 if (_nrImage
== 0) return kIOReturnUnsupported
;
1163 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1165 nameLength
= name
->getLength();
1166 dataLength
= value
->getLength();
1167 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1168 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1170 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1171 if (err
!= kIOReturnSuccess
) return err
;
1173 exists
= searchNVRAMProperty(&hdr
, &offset
);
1174 if (offset
== 0) return kIOReturnNoMemory
;
1176 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1177 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1179 prop
->nameLength
= nameLength
;
1180 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1181 prop
->dataLength
= dataLength
;
1182 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1185 nvLength
= offset
+ sizeof(NVRAMProperty
);
1186 if (getPlatform()->getBootROMType())
1189 nvLength
+= _nrPartitionOffset
;
1190 *((UInt16
*)_nrImage
) = nvLength
;
1193 _nvramImageDirty
= true;
1198 OSData
*IODTNVRAM::unescapeBytesToData(UInt8
*bytes
, UInt32 length
)
1201 UInt32 totalLength
= 0;
1206 // Calculate the actual length of the data.
1209 for (cnt
= 0; cnt
< length
;) {
1210 byte
= bytes
[cnt
++];
1212 byte
= bytes
[cnt
++];
1220 totalLength
+= cnt2
;
1224 // Create an empty OSData of the correct size.
1225 data
= OSData::withCapacity(totalLength
);
1227 for (cnt
= 0; cnt
< length
;) {
1228 byte
= bytes
[cnt
++];
1230 byte
= bytes
[cnt
++];
1232 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1235 data
->appendByte(byte
, cnt2
);
1243 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1252 where
= (UInt8
*) value
->getBytesNoCopy();
1253 end
= where
+ value
->getLength();
1255 result
= OSData::withCapacity(end
- where
);
1259 while (where
< end
) {
1262 if ((byte
== 0x00) || (byte
== 0xFF)) {
1264 ((where
- start
) < 0x80) && (where
< end
) && (byte
== *where
);
1266 ok
&= result
->appendByte(0xff, 1);
1267 byte
= (byte
& 0x80) | (where
- start
);
1269 ok
&= result
->appendByte(byte
, 1);
1271 ok
&= result
->appendByte(0, 1);
1281 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1282 const OSSymbol
**name
,
1285 IOReturn err
= kIOReturnNoResources
;
1294 if (_ofDict
== 0) return err
;
1295 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1296 if (data
== 0) return err
;
1298 start
= (UInt8
*) data
->getBytesNoCopy();
1299 end
= start
+ data
->getLength();
1302 while (where
< end
) {
1309 else if (nvName
== 0)
1312 IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
)) {
1313 *name
= OSSymbol::withCString((const char *) nvName
);
1314 *value
= unescapeBytesToData(start
, where
- start
- 1);
1315 if ((*name
!= 0) && (*value
!= 0))
1316 err
= kIOReturnSuccess
;
1318 err
= kIOReturnNoMemory
;
1321 nvPath
= nvName
= 0;
1329 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1330 const OSSymbol
*propName
,
1346 if (_ofDict
== 0) return kIOReturnNoResources
;
1348 // copy over existing properties for other entries
1350 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1352 start
= (UInt8
*) oldData
->getBytesNoCopy();
1353 end
= start
+ oldData
->getLength();
1357 while (where
< end
) {
1363 else if (nvName
== 0)
1366 IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
)) {
1367 // delete old property (nvPath -> where)
1368 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1370 ok
&= data
->appendBytes(where
, end
- where
);
1373 nvPath
= nvName
= 0;
1379 // make the new property
1383 data
= OSData::withData(oldData
);
1385 data
= OSData::withCapacity(16);
1387 return kIOReturnNoMemory
;
1390 // get entries in path
1391 OSArray
*array
= OSArray::withCapacity(5);
1394 return kIOReturnNoMemory
;
1397 array
->setObject(entry
);
1398 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1401 for (int i
= array
->getCount() - 3;
1402 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1405 name
= entry
->getName(gIODTPlane
);
1406 comp
= entry
->getLocation(gIODTPlane
);
1407 if( comp
&& (0 == strcmp("pci", name
))
1408 && (0 == strcmp("80000000", comp
))) {
1410 comp
= "/pci@80000000";
1413 ok
&= data
->appendBytes("/@", 2);
1417 ok
&= data
->appendByte('/', 1);
1421 ok
&= data
->appendBytes(comp
, strlen(comp
));
1423 ok
&= data
->appendByte(0, 1);
1427 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1429 // append escaped data
1430 oldData
= escapeDataToData(value
);
1431 ok
&= (oldData
!= 0);
1433 ok
&= data
->appendBytes(oldData
);
1436 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1438 _ofImageDirty
= true;
1442 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;