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 _registryPropertiesKey
= OSSymbol::withCStringNoCopy("aapl,pci");
47 if (_registryPropertiesKey
== 0) return false;
52 void IODTNVRAM::registerNVRAMController(IONVRAMController
*nvram
)
54 UInt32 currentOffset
= 0;
56 if (_nvramController
!= 0) return;
58 _nvramController
= nvram
;
60 _nvramController
->read(0, _nvramImage
, kIODTNVRAMImageSize
);
62 // Find the offsets for the OF, XPRAM and NameRegistry partitions in NVRAM.
63 _ofPartitionOffset
= 0xFFFFFFFF;
64 _xpramPartitionOffset
= 0xFFFFFFFF;
65 _nrPartitionOffset
= 0xFFFFFFFF;
66 if (getPlatform()->getBootROMType()) {
67 // Look through the partitions to find the OF, MacOS partitions.
68 while (currentOffset
< kIODTNVRAMImageSize
) {
69 if (strcmp((const char *)_nvramImage
+ currentOffset
+ 4, "common") == 0) {
70 _ofPartitionOffset
= currentOffset
+ 16;
72 (((UInt16
*)(_nvramImage
+ currentOffset
))[1] - 1) * 0x10;
73 } else if (strcmp((const char *)_nvramImage
+ currentOffset
+ 4, "APL,MacOS75") == 0) {
74 _xpramPartitionOffset
= currentOffset
+ 16;
75 _xpramPartitionSize
= kIODTNVRAMXPRAMSize
;
76 _nrPartitionOffset
= _xpramPartitionOffset
+ _xpramPartitionSize
;
78 (((UInt16
*)(_nvramImage
+ currentOffset
))[1] - 1) * 0x10 -
81 currentOffset
+= ((short *)(_nvramImage
+ currentOffset
))[1] * 16;
84 // Use the fixed address for old world machines.
85 _ofPartitionOffset
= 0x1800;
86 _ofPartitionSize
= 0x0800;
87 _xpramPartitionOffset
= 0x1300;
88 _xpramPartitionSize
= 0x0100;
89 _nrPartitionOffset
= 0x1400;
90 _nrPartitionSize
= 0x0400;
93 if (_ofPartitionOffset
!= 0xFFFFFFFF)
94 _ofImage
= _nvramImage
+ _ofPartitionOffset
;
95 if (_xpramPartitionOffset
!= 0xFFFFFFFF)
96 _xpramImage
= _nvramImage
+ _xpramPartitionOffset
;
97 if (_nrPartitionOffset
!= 0xFFFFFFFF)
98 _nrImage
= _nvramImage
+ _nrPartitionOffset
;
103 void IODTNVRAM::sync(void)
105 if (!_nvramImageDirty
&& !_ofImageDirty
) return;
109 _nvramController
->write(0, _nvramImage
, kIODTNVRAMImageSize
);
110 _nvramController
->sync();
112 _nvramImageDirty
= false;
115 bool IODTNVRAM::serializeProperties(OSSerialize
*serialize
) const
120 OSDictionary
*dict
, *tmpDict
= 0;
121 OSCollectionIterator
*iter
= 0;
123 if (_ofDict
== 0) return false;
125 // Verify permissions.
126 result
= IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeAdministrator
);
127 if (result
!= kIOReturnSuccess
) {
128 tmpDict
= OSDictionary::withCapacity(1);
129 if (tmpDict
== 0) return false;
131 iter
= OSCollectionIterator::withCollection(_ofDict
);
132 if (iter
== 0) return false;
135 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
138 variablePerm
= getOFVariablePerm(key
);
139 if (variablePerm
!= kOFVariablePermRootOnly
) {
140 tmpDict
->setObject(key
, _ofDict
->getObject(key
));
148 result
= dict
->serialize(serialize
);
150 if (tmpDict
!= 0) tmpDict
->release();
151 if (iter
!= 0) iter
->release();
156 OSObject
*IODTNVRAM::getProperty(const OSSymbol
*aKey
) const
161 if (_ofDict
== 0) return 0;
163 // Verify permissions.
164 result
= IOUserClient::clientHasPrivilege(current_task(), "root");
165 if (result
!= kIOReturnSuccess
) {
166 variablePerm
= getOFVariablePerm(aKey
);
167 if (variablePerm
== kOFVariablePermRootOnly
) return 0;
170 return _ofDict
->getObject(aKey
);
173 OSObject
*IODTNVRAM::getProperty(const char *aKey
) const
175 const OSSymbol
*keySymbol
;
176 OSObject
*theObject
= 0;
178 keySymbol
= OSSymbol::withCStringNoCopy(aKey
);
179 if (keySymbol
!= 0) {
180 theObject
= getProperty(keySymbol
);
181 keySymbol
->release();
187 bool IODTNVRAM::setProperty(const OSSymbol
*aKey
, OSObject
*anObject
)
190 UInt32 propType
, propPerm
;
192 OSObject
*propObject
= 0;
194 if (_ofDict
== 0) return false;
196 // Verify permissions.
197 result
= IOUserClient::clientHasPrivilege(current_task(), "root");
198 if (result
!= kIOReturnSuccess
) {
199 propPerm
= getOFVariablePerm(aKey
);
200 if (propPerm
!= kOFVariablePermUserWrite
) return false;
203 // Don't allow creation of new properties on old world machines.
204 if (getPlatform()->getBootROMType() == 0) {
205 if (_ofDict
->getObject(aKey
) == 0) return false;
208 // Make sure the object is of the correct type.
209 propType
= getOFVariableType(aKey
);
211 case kOFVariableTypeBoolean
:
212 propObject
= OSDynamicCast(OSBoolean
, anObject
);
215 case kOFVariableTypeNumber
:
216 propObject
= OSDynamicCast(OSNumber
, anObject
);
219 case kOFVariableTypeString
:
220 propObject
= OSDynamicCast(OSString
, anObject
);
223 case kOFVariableTypeData
:
224 propObject
= OSDynamicCast(OSData
, anObject
);
225 if (propObject
== 0) {
226 tmpString
= OSDynamicCast(OSString
, anObject
);
227 if (tmpString
!= 0) {
228 propObject
= OSData::withBytes(tmpString
->getCStringNoCopy(),
229 tmpString
->getLength());
235 if (propObject
== 0) return false;
237 result
= _ofDict
->setObject(aKey
, propObject
);
240 if (getPlatform()->getBootROMType() == 0) {
241 updateOWBootArgs(aKey
, propObject
);
244 _ofImageDirty
= true;
250 IOReturn
IODTNVRAM::setProperties(OSObject
*properties
)
256 OSCollectionIterator
*iter
;
258 dict
= OSDynamicCast(OSDictionary
, properties
);
259 if (dict
== 0) return kIOReturnBadArgument
;
261 iter
= OSCollectionIterator::withCollection(dict
);
262 if (iter
== 0) return kIOReturnBadArgument
;
265 key
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
268 object
= dict
->getObject(key
);
269 if (object
== 0) continue;
271 result
= setProperty(key
, object
);
276 if (result
) return kIOReturnSuccess
;
277 else return kIOReturnError
;
280 IOReturn
IODTNVRAM::readXPRAM(IOByteCount offset
, UInt8
*buffer
,
283 if ((_nvramImage
== 0) || (_xpramPartitionOffset
== 0))
284 return kIOReturnNotReady
;
286 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
287 (offset
+ length
> kIODTNVRAMXPRAMSize
))
288 return kIOReturnBadArgument
;
290 bcopy(_nvramImage
+ _xpramPartitionOffset
+ offset
, buffer
, length
);
292 return kIOReturnSuccess
;
295 IOReturn
IODTNVRAM::writeXPRAM(IOByteCount offset
, UInt8
*buffer
,
298 if ((_nvramImage
== 0) || (_xpramPartitionOffset
== 0))
299 return kIOReturnNotReady
;
301 if ((buffer
== 0) || (length
<= 0) || (offset
< 0) ||
302 (offset
+ length
> kIODTNVRAMXPRAMSize
))
303 return kIOReturnBadArgument
;
305 bcopy(buffer
, _nvramImage
+ _xpramPartitionOffset
+ offset
, length
);
307 _nvramImageDirty
= true;
309 return kIOReturnSuccess
;
312 IOReturn
IODTNVRAM::readNVRAMProperty(IORegistryEntry
*entry
,
313 const OSSymbol
**name
,
318 if (getPlatform()->getBootROMType())
319 err
= readNVRAMPropertyType1(entry
, name
, value
);
321 err
= readNVRAMPropertyType0(entry
, name
, value
);
326 IOReturn
IODTNVRAM::writeNVRAMProperty(IORegistryEntry
*entry
,
327 const OSSymbol
*name
,
332 if (getPlatform()->getBootROMType())
333 err
= writeNVRAMPropertyType1(entry
, name
, value
);
335 err
= writeNVRAMPropertyType0(entry
, name
, value
);
342 // Private methods for Open Firmware variable access.
344 struct OWVariablesHeader
{
359 typedef struct OWVariablesHeader OWVariablesHeader
;
361 IOReturn
IODTNVRAM::initOFVariables(void)
363 UInt32 cnt
, propOffset
, propType
;
364 UInt8
*propName
, *propData
;
365 UInt32 propNameLength
, propDataLength
;
366 const OSSymbol
*propSymbol
;
367 OSObject
*propObject
;
368 OWVariablesHeader
*owHeader
;
370 if (_ofImage
== 0) return kIOReturnNotReady
;
372 _ofDict
= OSDictionary::withCapacity(1);
373 if (_ofDict
== 0) return kIOReturnNoMemory
;
375 if (getPlatform()->getBootROMType()) {
377 while (cnt
< _ofPartitionSize
) {
378 // Break if there is no name.
379 if (_ofImage
[cnt
] == '\0') break;
381 // Find the length of the name.
382 propName
= _ofImage
+ cnt
;
383 for (propNameLength
= 0; (cnt
+ propNameLength
) < _ofPartitionSize
;
385 if (_ofImage
[cnt
+ propNameLength
] == '=') break;
388 // Break if the name goes past the end of the partition.
389 if ((cnt
+ propNameLength
) >= _ofPartitionSize
) break;
390 cnt
+= propNameLength
+ 1;
392 propData
= _ofImage
+ cnt
;
393 for (propDataLength
= 0; (cnt
+ propDataLength
) < _ofPartitionSize
;
395 if (_ofImage
[cnt
+ propDataLength
] == '\0') break;
398 // Break if the data goes past the end of the partition.
399 if ((cnt
+ propDataLength
) >= _ofPartitionSize
) break;
400 cnt
+= propDataLength
+ 1;
402 if (convertPropToObject(propName
, propNameLength
,
403 propData
, propDataLength
,
404 &propSymbol
, &propObject
)) {
405 _ofDict
->setObject(propSymbol
, propObject
);
406 propSymbol
->release();
407 propObject
->release();
411 // Create the boot-args property if it is not in the dictionary.
412 if (_ofDict
->getObject("boot-args") == 0) {
413 propObject
= OSString::withCStringNoCopy("");
414 if (propObject
!= 0) {
415 _ofDict
->setObject("boot-args", propObject
);
416 propObject
->release();
420 owHeader
= (OWVariablesHeader
*)_ofImage
;
421 if (!validateOWChecksum(_ofImage
)) {
424 return kIOReturnBadMedia
;
429 if (!getOWVariableInfo(cnt
++, &propSymbol
, &propType
, &propOffset
))
433 case kOFVariableTypeBoolean
:
434 propObject
= OSBoolean::withBoolean(owHeader
->owFlags
& propOffset
);
437 case kOFVariableTypeNumber
:
438 propObject
= OSNumber::withNumber(owHeader
->owNumbers
[propOffset
], 32);
441 case kOFVariableTypeString
:
442 propData
= _ofImage
+ owHeader
->owStrings
[propOffset
].offset
-
444 propDataLength
= owHeader
->owStrings
[propOffset
].length
;
445 propName
= IONew(UInt8
, propDataLength
+ 1);
447 strncpy((char *)propName
, (const char *)propData
, propDataLength
);
448 propName
[propDataLength
] = '\0';
449 propObject
= OSString::withCString((const char *)propName
);
450 IODelete(propName
, UInt8
, propDataLength
+ 1);
455 if (propObject
== 0) break;
457 _ofDict
->setObject(propSymbol
, propObject
);
458 propSymbol
->release();
459 propObject
->release();
462 // Create the boot-args property.
463 propSymbol
= OSSymbol::withCString("boot-command");
464 if (propSymbol
!= 0) {
465 propObject
= _ofDict
->getObject(propSymbol
);
466 if (propObject
!= 0) {
467 updateOWBootArgs(propSymbol
, propObject
);
469 propSymbol
->release();
473 return kIOReturnSuccess
;
476 IOReturn
IODTNVRAM::syncOFVariables(void)
479 UInt32 cnt
, length
, maxLength
;
480 UInt32 curOffset
, tmpOffset
, tmpType
, tmpDataLength
;
481 UInt8
*buffer
, *tmpBuffer
, *tmpData
;
482 const OSSymbol
*tmpSymbol
;
484 OSBoolean
*tmpBoolean
;
487 OSCollectionIterator
*iter
;
488 OWVariablesHeader
*owHeader
, *owHeaderOld
;
490 if ((_ofImage
== 0) || (_ofDict
== 0)) return kIOReturnNotReady
;
492 if (!_ofImageDirty
) return kIOReturnSuccess
;
494 if (getPlatform()->getBootROMType()) {
495 buffer
= tmpBuffer
= IONew(UInt8
, _ofPartitionSize
);
496 if (buffer
== 0) return kIOReturnNoMemory
;
497 bzero(buffer
, _ofPartitionSize
);
500 maxLength
= _ofPartitionSize
;
502 iter
= OSCollectionIterator::withCollection(_ofDict
);
503 if (iter
== 0) ok
= false;
506 tmpSymbol
= OSDynamicCast(OSSymbol
, iter
->getNextObject());
507 if (tmpSymbol
== 0) break;
509 tmpObject
= _ofDict
->getObject(tmpSymbol
);
512 ok
= convertObjectToProp(tmpBuffer
, &length
, tmpSymbol
, tmpObject
);
521 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
524 IODelete(buffer
, UInt8
, _ofPartitionSize
);
526 if (!ok
) return kIOReturnBadArgument
;
528 buffer
= IONew(UInt8
, _ofPartitionSize
);
529 if (buffer
== 0) return kIOReturnNoMemory
;
530 bzero(buffer
, _ofPartitionSize
);
532 owHeader
= (OWVariablesHeader
*)buffer
;
533 owHeaderOld
= (OWVariablesHeader
*)_ofImage
;
535 owHeader
->owMagic
= owHeaderOld
->owMagic
;
536 owHeader
->owVersion
= owHeaderOld
->owVersion
;
537 owHeader
->owPages
= owHeaderOld
->owPages
;
539 curOffset
= _ofPartitionSize
;
544 if (!getOWVariableInfo(cnt
++, &tmpSymbol
, &tmpType
, &tmpOffset
))
547 tmpObject
= _ofDict
->getObject(tmpSymbol
);
550 case kOFVariableTypeBoolean
:
551 tmpBoolean
= OSDynamicCast(OSBoolean
, tmpObject
);
552 if (tmpBoolean
->getValue()) owHeader
->owFlags
|= tmpOffset
;
555 case kOFVariableTypeNumber
:
556 tmpNumber
= OSDynamicCast(OSNumber
, tmpObject
);
557 owHeader
->owNumbers
[tmpOffset
] = tmpNumber
->unsigned32BitValue();
560 case kOFVariableTypeString
:
561 tmpString
= OSDynamicCast(OSString
, tmpObject
);
562 tmpData
= (UInt8
*) tmpString
->getCStringNoCopy();
563 tmpDataLength
= tmpString
->getLength();
565 if ((curOffset
- tmpDataLength
) < sizeof(OWVariablesHeader
)) {
570 owHeader
->owStrings
[tmpOffset
].length
= tmpDataLength
;
571 curOffset
-= tmpDataLength
;
572 owHeader
->owStrings
[tmpOffset
].offset
= curOffset
+ _ofPartitionOffset
;
573 if (tmpDataLength
!= 0)
574 bcopy(tmpData
, buffer
+ curOffset
, tmpDataLength
);
580 owHeader
->owHere
= _ofPartitionOffset
+ sizeof(OWVariablesHeader
);
581 owHeader
->owTop
= _ofPartitionOffset
+ curOffset
;
582 owHeader
->owNext
= 0;
584 owHeader
->owChecksum
= 0;
585 owHeader
->owChecksum
= ~generateOWChecksum(buffer
);
587 bcopy(buffer
, _ofImage
, _ofPartitionSize
);
590 IODelete(buffer
, UInt8
, _ofPartitionSize
);
592 if (!ok
) return kIOReturnBadArgument
;
595 _ofImageDirty
= false;
596 _nvramImageDirty
= true;
598 return kIOReturnSuccess
;
605 SInt32 variableOffset
;
607 typedef struct OFVariable OFVariable
;
610 kOWVariableOffsetNumber
= 8,
611 kOWVariableOffsetString
= 17
614 OFVariable gOFVariables
[] = {
615 {"little-endian?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 0},
616 {"real-mode?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 1},
617 {"auto-boot?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 2},
618 {"diag-switch?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 3},
619 {"fcode-debug?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 4},
620 {"oem-banner?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 5},
621 {"oem-logo?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 6},
622 {"use-nvramrc?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, 7},
623 {"use-generic?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
, -1},
624 {"default-mac-address?", kOFVariableTypeBoolean
, kOFVariablePermUserRead
,-1},
625 {"real-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 8},
626 {"real-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 9},
627 {"virt-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 10},
628 {"virt-size", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 11},
629 {"load-base", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 12},
630 {"pci-probe-list", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 13},
631 {"pci-probe-mask", kOFVariableTypeNumber
, kOFVariablePermUserRead
, -1},
632 {"screen-#columns", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 14},
633 {"screen-#rows", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 15},
634 {"selftest-#megs", kOFVariableTypeNumber
, kOFVariablePermUserRead
, 16},
635 {"boot-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 17},
636 {"boot-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 18},
637 {"boot-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
638 {"console-screen", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
639 {"diag-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 19},
640 {"diag-file", kOFVariableTypeString
, kOFVariablePermUserRead
, 20},
641 {"input-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 21},
642 {"output-device", kOFVariableTypeString
, kOFVariablePermUserRead
, 22},
643 {"input-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
644 {"output-device-1", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
645 {"mouse-device", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
646 {"oem-banner", kOFVariableTypeString
, kOFVariablePermUserRead
, 23},
647 {"oem-logo", kOFVariableTypeString
, kOFVariablePermUserRead
, 24},
648 {"nvramrc", kOFVariableTypeString
, kOFVariablePermUserRead
, 25},
649 {"boot-command", kOFVariableTypeString
, kOFVariablePermUserRead
, 26},
650 {"default-client-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
651 {"default-server-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
652 {"default-gateway-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
653 {"default-subnet-mask", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
654 {"default-router-ip", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
655 {"boot-script", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
656 {"boot-args", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
657 {"aapl,pci", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
658 {"security-mode", kOFVariableTypeString
, kOFVariablePermUserRead
, -1},
659 {"security-password", kOFVariableTypeData
, kOFVariablePermRootOnly
, -1},
660 {0, kOFVariableTypeData
, kOFVariablePermUserRead
, -1}
663 UInt32
IODTNVRAM::getOFVariableType(const OSSymbol
*propSymbol
) const
667 ofVar
= gOFVariables
;
669 if ((ofVar
->variableName
== 0) ||
670 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
674 return ofVar
->variableType
;
677 UInt32
IODTNVRAM::getOFVariablePerm(const OSSymbol
*propSymbol
) const
681 ofVar
= gOFVariables
;
683 if ((ofVar
->variableName
== 0) ||
684 propSymbol
->isEqualTo(ofVar
->variableName
)) break;
688 return ofVar
->variablePerm
;
691 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber
, const OSSymbol
**propSymbol
,
692 UInt32
*propType
, UInt32
*propOffset
)
696 ofVar
= gOFVariables
;
698 if (ofVar
->variableName
== 0) return false;
700 if (ofVar
->variableOffset
== (SInt32
) variableNumber
) break;
705 *propSymbol
= OSSymbol::withCStringNoCopy(ofVar
->variableName
);
706 *propType
= ofVar
->variableType
;
709 case kOFVariableTypeBoolean
:
710 *propOffset
= 1 << (31 - variableNumber
);
713 case kOFVariableTypeNumber
:
714 *propOffset
= variableNumber
- kOWVariableOffsetNumber
;
717 case kOFVariableTypeString
:
718 *propOffset
= variableNumber
- kOWVariableOffsetString
;
725 bool IODTNVRAM::convertPropToObject(UInt8
*propName
, UInt32 propNameLength
,
726 UInt8
*propData
, UInt32 propDataLength
,
727 const OSSymbol
**propSymbol
,
728 OSObject
**propObject
)
731 const OSSymbol
*tmpSymbol
;
736 // Create the symbol.
737 propName
[propNameLength
] = '\0';
738 tmpSymbol
= OSSymbol::withCString((const char *)propName
);
739 propName
[propNameLength
] = '=';
740 if (tmpSymbol
== 0) {
744 propType
= getOFVariableType(tmpSymbol
);
746 // Create the object.
749 case kOFVariableTypeBoolean
:
750 if (!strncmp("true", (const char *)propData
, propDataLength
)) {
751 tmpObject
= kOSBooleanTrue
;
752 } else if (!strncmp("false", (const char *)propData
, propDataLength
)) {
753 tmpObject
= kOSBooleanFalse
;
757 case kOFVariableTypeNumber
:
758 tmpNumber
= OSNumber::withNumber(strtol((const char *)propData
, 0, 0), 32);
759 if (tmpNumber
!= 0) tmpObject
= tmpNumber
;
762 case kOFVariableTypeString
:
763 tmpString
= OSString::withCString((const char *)propData
);
764 if (tmpString
!= 0) tmpObject
= tmpString
;
767 case kOFVariableTypeData
:
768 tmpObject
= unescapeBytesToData(propData
, propDataLength
);
772 if (tmpObject
== 0) {
773 tmpSymbol
->release();
777 *propSymbol
= tmpSymbol
;
778 *propObject
= tmpObject
;
783 bool IODTNVRAM::convertObjectToProp(UInt8
*buffer
, UInt32
*length
,
784 const OSSymbol
*propSymbol
, OSObject
*propObject
)
787 UInt32 propNameLength
, propDataLength
;
788 UInt32 propType
, tmpValue
;
789 OSBoolean
*tmpBoolean
= 0;
790 OSNumber
*tmpNumber
= 0;
791 OSString
*tmpString
= 0;
794 propName
= (UInt8
*)propSymbol
->getCStringNoCopy();
795 propNameLength
= propSymbol
->getLength();
796 propType
= getOFVariableType(propSymbol
);
798 // Get the size of the data.
799 propDataLength
= 0xFFFFFFFF;
801 case kOFVariableTypeBoolean
:
802 tmpBoolean
= OSDynamicCast(OSBoolean
, propObject
);
803 if (tmpBoolean
!= 0) propDataLength
= 5;
806 case kOFVariableTypeNumber
:
807 tmpNumber
= OSDynamicCast(OSNumber
, propObject
);
808 if (tmpNumber
!= 0) propDataLength
= 10;
811 case kOFVariableTypeString
:
812 tmpString
= OSDynamicCast(OSString
, propObject
);
813 if (tmpString
!= 0) propDataLength
= tmpString
->getLength();
816 case kOFVariableTypeData
:
817 tmpData
= OSDynamicCast(OSData
, propObject
);
819 tmpData
= escapeDataToData(tmpData
);
820 propDataLength
= tmpData
->getLength();
825 // Make sure the propertySize is known and will fit.
826 if (propDataLength
== 0xFFFFFFFF) return false;
827 if ((propNameLength
+ propDataLength
+ 2) > *length
) return false;
829 // Copy the property name equal sign.
830 sprintf((char *)buffer
, "%s=", propName
);
831 buffer
+= propNameLength
+ 1;
834 case kOFVariableTypeBoolean
:
835 if (tmpBoolean
->getValue()) {
836 strcpy((char *)buffer
, "true");
838 strcpy((char *)buffer
, "false");
842 case kOFVariableTypeNumber
:
843 tmpValue
= tmpNumber
->unsigned32BitValue();
844 if (tmpValue
== 0xFFFFFFFF) {
845 strcpy((char *)buffer
, "-1");
846 } else if (tmpValue
< 1000) {
847 sprintf((char *)buffer
, "%ld", tmpValue
);
849 sprintf((char *)buffer
, "0x%lx", tmpValue
);
853 case kOFVariableTypeString
:
854 strcpy((char *)buffer
, tmpString
->getCStringNoCopy());
857 case kOFVariableTypeData
:
858 bcopy(tmpData
->getBytesNoCopy(), buffer
, propDataLength
);
863 propDataLength
= strlen((const char *)buffer
);
865 *length
= propNameLength
+ propDataLength
+ 2;
871 UInt16
IODTNVRAM::generateOWChecksum(UInt8
*buffer
)
873 UInt32 cnt
, checksum
= 0;
874 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
876 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
877 checksum
+= tmpBuffer
[cnt
];
879 return checksum
% 0x0000FFFF;
882 bool IODTNVRAM::validateOWChecksum(UInt8
*buffer
)
884 UInt32 cnt
, checksum
, sum
= 0;
885 UInt16
*tmpBuffer
= (UInt16
*)buffer
;
887 for (cnt
= 0; cnt
< _ofPartitionSize
/ 2; cnt
++)
888 sum
+= tmpBuffer
[cnt
];
890 checksum
= (sum
>> 16) + (sum
& 0x0000FFFF);
891 if (checksum
== 0x10000) checksum
--;
892 checksum
= (checksum
^ 0x0000FFFF) & 0x0000FFFF;
894 return checksum
== 0;
897 void IODTNVRAM::updateOWBootArgs(const OSSymbol
*key
, OSObject
*value
)
899 bool wasBootArgs
, bootr
= false;
901 OSString
*tmpString
, *bootCommand
, *bootArgs
= 0;
902 UInt8
*bootCommandData
, *bootArgsData
, *tmpData
;
903 UInt32 bootCommandDataLength
, bootArgsDataLength
, tmpDataLength
;
905 tmpString
= OSDynamicCast(OSString
, value
);
906 if (tmpString
== 0) return;
908 if (key
->isEqualTo("boot-command")) {
910 bootCommand
= tmpString
;
911 } else if (key
->isEqualTo("boot-args")) {
913 bootArgs
= tmpString
;
914 bootCommand
= OSDynamicCast(OSString
, _ofDict
->getObject("boot-command"));
915 if (bootCommand
== 0) return;
918 bootCommandData
= (UInt8
*)bootCommand
->getCStringNoCopy();
919 bootCommandDataLength
= bootCommand
->getLength();
921 if (bootCommandData
== 0) return;
923 for (cnt
= 0; cnt
< bootCommandDataLength
; cnt
++) {
924 if ((bootCommandData
[cnt
] == 'b') &&
925 !strncmp("bootr", (const char *)bootCommandData
+ cnt
, 5)) {
927 while (bootCommandData
[cnt
] == ' ') cnt
++;
933 _ofDict
->removeObject("boot-args");
938 bootArgsData
= (UInt8
*)bootArgs
->getCStringNoCopy();
939 bootArgsDataLength
= bootArgs
->getLength();
940 if (bootArgsData
== 0) return;
942 tmpDataLength
= cnt
+ bootArgsDataLength
;
943 tmpData
= IONew(UInt8
, tmpDataLength
+ 1);
944 if (tmpData
== 0) return;
946 strncpy((char *)tmpData
, (const char *)bootCommandData
, cnt
);
948 strcat((char *)tmpData
, (const char *)bootArgsData
);
950 bootCommand
= OSString::withCString((const char *)tmpData
);
951 if (bootCommand
!= 0) {
952 _ofDict
->setObject("boot-command", bootCommand
);
953 bootCommand
->release();
956 IODelete(tmpData
, UInt8
, tmpDataLength
+ 1);
958 bootArgs
= OSString::withCString((const char *)(bootCommandData
+ cnt
));
960 _ofDict
->setObject("boot-args", bootArgs
);
967 // Private methods for Name Registry access.
970 kMaxNVNameLength
= 4,
974 #pragma options align=mac68k
977 IONVRAMDescriptor header
;
979 UInt8 name
[ kMaxNVNameLength
];
981 UInt8 data
[ kMaxNVDataLength
];
983 #pragma options align=reset
985 bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor
*hdr
, UInt32
*where
)
990 nvEnd
= *((UInt16
*)_nrImage
);
991 if(getPlatform()->getBootROMType()) {
992 // on NewWorld, offset to partition start
995 // on old world, absolute
996 nvEnd
-= _nrPartitionOffset
;
998 if((nvEnd
< 0) || (nvEnd
>= kIODTNVRAMNameRegistrySize
))
1002 while ((offset
+ sizeof(NVRAMProperty
)) <= (UInt32
)nvEnd
) {
1003 if (bcmp(_nrImage
+ offset
, hdr
, sizeof(*hdr
)) == 0) {
1007 offset
+= sizeof(NVRAMProperty
);
1010 if ((nvEnd
+ sizeof(NVRAMProperty
)) <= kIODTNVRAMNameRegistrySize
)
1018 IOReturn
IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry
*entry
,
1019 const OSSymbol
**name
,
1022 IONVRAMDescriptor hdr
;
1023 NVRAMProperty
*prop
;
1027 char nameBuf
[kMaxNVNameLength
+ 1];
1029 if (_nrImage
== 0) return kIOReturnUnsupported
;
1030 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1032 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1033 if (err
!= kIOReturnSuccess
) return err
;
1035 if (searchNVRAMProperty(&hdr
, &offset
)) {
1036 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1038 length
= prop
->nameLength
;
1039 if (length
> kMaxNVNameLength
) length
= kMaxNVNameLength
;
1040 strncpy(nameBuf
, (const char *)prop
->name
, length
);
1041 nameBuf
[length
] = 0;
1042 *name
= OSSymbol::withCString(nameBuf
);
1044 length
= prop
->dataLength
;
1045 if (length
> kMaxNVDataLength
) length
= kMaxNVDataLength
;
1046 *value
= OSData::withBytes(prop
->data
, length
);
1048 if ((*name
!= 0) && (*value
!= 0)) return kIOReturnSuccess
;
1049 else return kIOReturnNoMemory
;
1052 return kIOReturnNoResources
;
1055 IOReturn
IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry
*entry
,
1056 const OSSymbol
*name
,
1059 IONVRAMDescriptor hdr
;
1060 NVRAMProperty
*prop
;
1061 IOByteCount nameLength
;
1062 IOByteCount dataLength
;
1068 if (_nrImage
== 0) return kIOReturnUnsupported
;
1069 if ((entry
== 0) || (name
== 0) || (value
== 0)) return kIOReturnBadArgument
;
1071 nameLength
= name
->getLength();
1072 dataLength
= value
->getLength();
1073 if (nameLength
> kMaxNVNameLength
) return kIOReturnNoSpace
;
1074 if (dataLength
> kMaxNVDataLength
) return kIOReturnNoSpace
;
1076 err
= IODTMakeNVDescriptor(entry
, &hdr
);
1077 if (err
!= kIOReturnSuccess
) return err
;
1079 exists
= searchNVRAMProperty(&hdr
, &offset
);
1080 if (offset
== 0) return kIOReturnNoMemory
;
1082 prop
= (NVRAMProperty
*)(_nrImage
+ offset
);
1083 if (!exists
) bcopy(&hdr
, &prop
->header
, sizeof(hdr
));
1085 prop
->nameLength
= nameLength
;
1086 bcopy(name
->getCStringNoCopy(), prop
->name
, nameLength
);
1087 prop
->dataLength
= dataLength
;
1088 bcopy(value
->getBytesNoCopy(), prop
->data
, dataLength
);
1091 nvLength
= offset
+ sizeof(NVRAMProperty
);
1092 if (getPlatform()->getBootROMType())
1095 nvLength
+= _nrPartitionOffset
;
1096 *((UInt16
*)_nrImage
) = nvLength
;
1099 _nvramImageDirty
= true;
1104 OSData
*IODTNVRAM::unescapeBytesToData(UInt8
*bytes
, UInt32 length
)
1107 UInt32 totalLength
= 0;
1112 // Calculate the actual length of the data.
1115 for (cnt
= 0; cnt
< length
;) {
1116 byte
= bytes
[cnt
++];
1118 byte
= bytes
[cnt
++];
1126 totalLength
+= cnt2
;
1130 // Create an empty OSData of the correct size.
1131 data
= OSData::withCapacity(totalLength
);
1133 for (cnt
= 0; cnt
< length
;) {
1134 byte
= bytes
[cnt
++];
1136 byte
= bytes
[cnt
++];
1138 byte
= (byte
& 0x80) ? 0xFF : 0x00;
1141 data
->appendByte(byte
, cnt2
);
1149 OSData
* IODTNVRAM::escapeDataToData(OSData
* value
)
1158 where
= (UInt8
*) value
->getBytesNoCopy();
1159 end
= where
+ value
->getLength();
1161 result
= OSData::withCapacity(end
- where
);
1165 while (where
< end
) {
1168 if ((byte
== 0x00) || (byte
== 0xFF)) {
1170 ((where
- start
) < 0x80) && (where
< end
) && (byte
== *where
);
1172 ok
&= result
->appendByte(0xff, 1);
1173 byte
= (byte
& 0x80) | (where
- start
);
1175 ok
&= result
->appendByte(byte
, 1);
1177 ok
&= result
->appendByte(0, 1);
1187 IOReturn
IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry
*entry
,
1188 const OSSymbol
**name
,
1191 IOReturn err
= kIOReturnNoResources
;
1200 if (_ofDict
== 0) return err
;
1201 data
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1202 if (data
== 0) return err
;
1204 start
= (UInt8
*) data
->getBytesNoCopy();
1205 end
= start
+ data
->getLength();
1208 while (where
< end
) {
1215 else if (nvName
== 0)
1218 IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
)) {
1219 *name
= OSSymbol::withCString((const char *) nvName
);
1220 *value
= unescapeBytesToData(start
, where
- start
- 1);
1221 if ((*name
!= 0) && (*value
!= 0))
1222 err
= kIOReturnSuccess
;
1224 err
= kIOReturnNoMemory
;
1227 nvPath
= nvName
= 0;
1235 IOReturn
IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry
*entry
,
1236 const OSSymbol
*propName
,
1252 if (_ofDict
== 0) return kIOReturnNoResources
;
1254 // copy over existing properties for other entries
1256 oldData
= OSDynamicCast(OSData
, _ofDict
->getObject(_registryPropertiesKey
));
1258 start
= (UInt8
*) oldData
->getBytesNoCopy();
1259 end
= start
+ oldData
->getLength();
1263 while (where
< end
) {
1269 else if (nvName
== 0)
1272 IORegistryEntry::fromPath((const char *) nvPath
, gIODTPlane
)) {
1273 // delete old property (nvPath -> where)
1274 data
= OSData::withBytes(propStart
, nvPath
- propStart
);
1276 ok
&= data
->appendBytes(where
, end
- where
);
1279 nvPath
= nvName
= 0;
1285 // make the new property
1289 data
= OSData::withData(oldData
);
1291 data
= OSData::withCapacity(16);
1293 return kIOReturnNoMemory
;
1296 // get entries in path
1297 OSArray
*array
= OSArray::withCapacity(5);
1300 return kIOReturnNoMemory
;
1303 array
->setObject(entry
);
1304 while ((entry
= entry
->getParentEntry(gIODTPlane
)));
1307 for (int i
= array
->getCount() - 3;
1308 (entry
= (IORegistryEntry
*) array
->getObject(i
));
1311 name
= entry
->getName(gIODTPlane
);
1312 comp
= entry
->getLocation(gIODTPlane
);
1313 if( comp
&& (0 == strcmp("pci", name
))
1314 && (0 == strcmp("80000000", comp
))) {
1316 comp
= "/pci@80000000";
1319 ok
&= data
->appendBytes("/@", 2);
1323 ok
&= data
->appendByte('/', 1);
1327 ok
&= data
->appendBytes(comp
, strlen(comp
));
1329 ok
&= data
->appendByte(0, 1);
1333 ok
&= data
->appendBytes(propName
->getCStringNoCopy(), propName
->getLength() + 1);
1335 // append escaped data
1336 oldData
= escapeDataToData(value
);
1337 ok
&= (oldData
!= 0);
1339 ok
&= data
->appendBytes(oldData
);
1342 ok
= _ofDict
->setObject(_registryPropertiesKey
, data
);
1344 _ofImageDirty
= true;
1348 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;