]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IONVRAM.cpp
xnu-201.42.3.tar.gz
[apple/xnu.git] / iokit / Kernel / IONVRAM.cpp
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
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>
28
29#define super IOService
30
31OSDefineMetaClassAndStructors(IODTNVRAM, IOService);
32
33bool IODTNVRAM::init(IORegistryEntry *old, const IORegistryPlane *plane)
34{
35 OSDictionary *dict;
36
37 if (!super::init(old, plane)) return false;
38
39 dict = OSDictionary::withCapacity(1);
40 if (dict == 0) return false;
41 setPropertyTable(dict);
42
43 _nvramImage = IONew(UInt8, kIODTNVRAMImageSize);
44 if (_nvramImage == 0) return false;
d52fe63f
A
45
46 _nvramPartitionOffsets = OSDictionary::withCapacity(1);
47 if (_nvramPartitionOffsets == 0) return false;
48
49 _nvramPartitionLengths = OSDictionary::withCapacity(1);
50 if (_nvramPartitionLengths == 0) return false;
51
1c79356b
A
52 _registryPropertiesKey = OSSymbol::withCStringNoCopy("aapl,pci");
53 if (_registryPropertiesKey == 0) return false;
54
55 return true;
56}
57
58void IODTNVRAM::registerNVRAMController(IONVRAMController *nvram)
59{
d52fe63f
A
60 char partitionID[18];
61 UInt32 partitionOffset, partitionLength;
62 UInt32 freePartitionOffset, freePartitionSize;
63 UInt32 currentLength, currentOffset = 0;
64 OSNumber *partitionOffsetNumber, *partitionLengthNumber;
1c79356b
A
65
66 if (_nvramController != 0) return;
67
68 _nvramController = nvram;
69
70 _nvramController->read(0, _nvramImage, kIODTNVRAMImageSize);
71
d52fe63f 72 // Find the offsets for the OF, XPRAM, and NameRegistry partitions.
1c79356b
A
73 _ofPartitionOffset = 0xFFFFFFFF;
74 _xpramPartitionOffset = 0xFFFFFFFF;
75 _nrPartitionOffset = 0xFFFFFFFF;
d52fe63f
A
76 freePartitionOffset = 0xFFFFFFFF;
77 freePartitionSize = 0;
1c79356b
A
78 if (getPlatform()->getBootROMType()) {
79 // Look through the partitions to find the OF, MacOS partitions.
80 while (currentOffset < kIODTNVRAMImageSize) {
d52fe63f
A
81 currentLength = ((UInt16 *)(_nvramImage + currentOffset))[1] * 16;
82
83 partitionOffset = currentOffset + 16;
84 partitionLength = currentLength - 16;
85
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;
1c79356b
A
93 _xpramPartitionSize = kIODTNVRAMXPRAMSize;
94 _nrPartitionOffset = _xpramPartitionOffset + _xpramPartitionSize;
d52fe63f
A
95 _nrPartitionSize = partitionLength - _xpramPartitionSize;
96 } else if (strncmp((const char *)_nvramImage + currentOffset + 4,
97 kIODTNVRAMFreePartitionName, 12) == 0) {
98 freePartitionOffset = currentOffset;
99 freePartitionSize = currentLength;
100 } else {
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';
107
108 partitionOffsetNumber = OSNumber::withNumber(partitionOffset, 32);
109 partitionLengthNumber = OSNumber::withNumber(partitionLength, 32);
110
111 // Save the partition offset and length
112 _nvramPartitionOffsets->setObject(partitionID, partitionOffsetNumber);
113 _nvramPartitionLengths->setObject(partitionID, partitionLengthNumber);
114
115 partitionOffsetNumber->release();
116 partitionLengthNumber->release();
1c79356b 117 }
d52fe63f 118 currentOffset += currentLength;
1c79356b
A
119 }
120 } else {
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;
128 }
129
130 if (_ofPartitionOffset != 0xFFFFFFFF)
131 _ofImage = _nvramImage + _ofPartitionOffset;
132 if (_xpramPartitionOffset != 0xFFFFFFFF)
133 _xpramImage = _nvramImage + _xpramPartitionOffset;
134 if (_nrPartitionOffset != 0xFFFFFFFF)
135 _nrImage = _nvramImage + _nrPartitionOffset;
136
137 initOFVariables();
138}
139
140void IODTNVRAM::sync(void)
141{
142 if (!_nvramImageDirty && !_ofImageDirty) return;
143
144 syncOFVariables();
145
146 _nvramController->write(0, _nvramImage, kIODTNVRAMImageSize);
147 _nvramController->sync();
148
149 _nvramImageDirty = false;
150}
151
152bool IODTNVRAM::serializeProperties(OSSerialize *serialize) const
153{
154 bool result;
155 UInt32 variablePerm;
156 const OSSymbol *key;
157 OSDictionary *dict, *tmpDict = 0;
158 OSCollectionIterator *iter = 0;
159
160 if (_ofDict == 0) return false;
161
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;
167
168 iter = OSCollectionIterator::withCollection(_ofDict);
169 if (iter == 0) return false;
170
171 while (1) {
172 key = OSDynamicCast(OSSymbol, iter->getNextObject());
173 if (key == 0) break;
174
175 variablePerm = getOFVariablePerm(key);
176 if (variablePerm != kOFVariablePermRootOnly) {
177 tmpDict->setObject(key, _ofDict->getObject(key));
178 }
179 }
180 dict = tmpDict;
181 } else {
182 dict = _ofDict;
183 }
184
185 result = dict->serialize(serialize);
186
187 if (tmpDict != 0) tmpDict->release();
188 if (iter != 0) iter->release();
189
190 return result;
191}
192
193OSObject *IODTNVRAM::getProperty(const OSSymbol *aKey) const
194{
195 IOReturn result;
196 UInt32 variablePerm;
197
198 if (_ofDict == 0) return 0;
199
200 // Verify permissions.
201 result = IOUserClient::clientHasPrivilege(current_task(), "root");
202 if (result != kIOReturnSuccess) {
203 variablePerm = getOFVariablePerm(aKey);
204 if (variablePerm == kOFVariablePermRootOnly) return 0;
205 }
206
207 return _ofDict->getObject(aKey);
208}
209
210OSObject *IODTNVRAM::getProperty(const char *aKey) const
211{
212 const OSSymbol *keySymbol;
213 OSObject *theObject = 0;
214
215 keySymbol = OSSymbol::withCStringNoCopy(aKey);
216 if (keySymbol != 0) {
217 theObject = getProperty(keySymbol);
218 keySymbol->release();
219 }
220
221 return theObject;
222}
223
224bool IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject)
225{
226 bool result;
227 UInt32 propType, propPerm;
228 OSString *tmpString;
229 OSObject *propObject = 0;
230
231 if (_ofDict == 0) return false;
232
233 // Verify permissions.
234 result = IOUserClient::clientHasPrivilege(current_task(), "root");
235 if (result != kIOReturnSuccess) {
236 propPerm = getOFVariablePerm(aKey);
237 if (propPerm != kOFVariablePermUserWrite) return false;
238 }
239
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;
243 }
244
245 // Make sure the object is of the correct type.
246 propType = getOFVariableType(aKey);
247 switch (propType) {
248 case kOFVariableTypeBoolean :
249 propObject = OSDynamicCast(OSBoolean, anObject);
250 break;
251
252 case kOFVariableTypeNumber :
253 propObject = OSDynamicCast(OSNumber, anObject);
254 break;
255
256 case kOFVariableTypeString :
257 propObject = OSDynamicCast(OSString, anObject);
258 break;
259
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());
267 }
268 }
269 break;
270 }
271
272 if (propObject == 0) return false;
273
274 result = _ofDict->setObject(aKey, propObject);
275
276 if (result) {
277 if (getPlatform()->getBootROMType() == 0) {
278 updateOWBootArgs(aKey, propObject);
279 }
280
281 _ofImageDirty = true;
282 }
283
284 return result;
285}
286
287IOReturn IODTNVRAM::setProperties(OSObject *properties)
288{
289 bool result = true;
290 OSObject *object;
291 const OSSymbol *key;
292 OSDictionary *dict;
293 OSCollectionIterator *iter;
294
295 dict = OSDynamicCast(OSDictionary, properties);
296 if (dict == 0) return kIOReturnBadArgument;
297
298 iter = OSCollectionIterator::withCollection(dict);
299 if (iter == 0) return kIOReturnBadArgument;
300
301 while (result) {
302 key = OSDynamicCast(OSSymbol, iter->getNextObject());
303 if (key == 0) break;
304
305 object = dict->getObject(key);
306 if (object == 0) continue;
307
308 result = setProperty(key, object);
309 }
310
311 iter->release();
312
313 if (result) return kIOReturnSuccess;
314 else return kIOReturnError;
315}
316
317IOReturn IODTNVRAM::readXPRAM(IOByteCount offset, UInt8 *buffer,
318 IOByteCount length)
319{
fa4905b1 320 if (_xpramImage == 0) return kIOReturnUnsupported;
1c79356b
A
321
322 if ((buffer == 0) || (length <= 0) || (offset < 0) ||
323 (offset + length > kIODTNVRAMXPRAMSize))
324 return kIOReturnBadArgument;
325
326 bcopy(_nvramImage + _xpramPartitionOffset + offset, buffer, length);
327
328 return kIOReturnSuccess;
329}
330
331IOReturn IODTNVRAM::writeXPRAM(IOByteCount offset, UInt8 *buffer,
332 IOByteCount length)
333{
fa4905b1 334 if (_xpramImage == 0) return kIOReturnUnsupported;
1c79356b
A
335
336 if ((buffer == 0) || (length <= 0) || (offset < 0) ||
337 (offset + length > kIODTNVRAMXPRAMSize))
338 return kIOReturnBadArgument;
339
340 bcopy(buffer, _nvramImage + _xpramPartitionOffset + offset, length);
341
342 _nvramImageDirty = true;
343
344 return kIOReturnSuccess;
345}
346
347IOReturn IODTNVRAM::readNVRAMProperty(IORegistryEntry *entry,
348 const OSSymbol **name,
349 OSData **value)
350{
351 IOReturn err;
352
353 if (getPlatform()->getBootROMType())
354 err = readNVRAMPropertyType1(entry, name, value);
355 else
356 err = readNVRAMPropertyType0(entry, name, value);
357
358 return err;
359}
360
361IOReturn IODTNVRAM::writeNVRAMProperty(IORegistryEntry *entry,
362 const OSSymbol *name,
363 OSData *value)
364{
365 IOReturn err;
366
367 if (getPlatform()->getBootROMType())
368 err = writeNVRAMPropertyType1(entry, name, value);
369 else
370 err = writeNVRAMPropertyType0(entry, name, value);
371
372 return err;
373}
374
d52fe63f
A
375OSDictionary *IODTNVRAM::getNVRAMPartitions(void)
376{
377 return _nvramPartitionLengths;
378}
1c79356b 379
d52fe63f
A
380IOReturn IODTNVRAM::readNVRAMPartition(const OSSymbol *partitionID,
381 IOByteCount offset, UInt8 *buffer,
382 IOByteCount length)
383{
384 OSNumber *partitionOffsetNumber, *partitionLengthNumber;
385 UInt32 partitionOffset, partitionLength;
386
387 partitionOffsetNumber =
388 (OSNumber *)_nvramPartitionOffsets->getObject(partitionID);
389 partitionLengthNumber =
390 (OSNumber *)_nvramPartitionLengths->getObject(partitionID);
391
392 if ((partitionOffsetNumber == 0) || (partitionLengthNumber == 0))
393 return kIOReturnNotFound;
394
395 partitionOffset = partitionOffsetNumber->unsigned32BitValue();
396 partitionLength = partitionLengthNumber->unsigned32BitValue();
397
398 if ((buffer == 0) || (length <= 0) || (offset < 0) ||
399 (offset + length > partitionLength))
400 return kIOReturnBadArgument;
401
402 bcopy(_nvramImage + partitionOffset + offset, buffer, length);
403
404 return kIOReturnSuccess;
405}
406
407IOReturn IODTNVRAM::writeNVRAMPartition(const OSSymbol *partitionID,
408 IOByteCount offset, UInt8 *buffer,
409 IOByteCount length)
410{
411 OSNumber *partitionOffsetNumber, *partitionLengthNumber;
412 UInt32 partitionOffset, partitionLength;
413
414 partitionOffsetNumber =
415 (OSNumber *)_nvramPartitionOffsets->getObject(partitionID);
416 partitionLengthNumber =
417 (OSNumber *)_nvramPartitionLengths->getObject(partitionID);
418
419 if ((partitionOffsetNumber == 0) || (partitionLengthNumber == 0))
420 return kIOReturnNotFound;
421
422 partitionOffset = partitionOffsetNumber->unsigned32BitValue();
423 partitionLength = partitionLengthNumber->unsigned32BitValue();
424
425 if ((buffer == 0) || (length <= 0) || (offset < 0) ||
426 (offset + length > partitionLength))
427 return kIOReturnBadArgument;
428
429 bcopy(buffer, _nvramImage + partitionOffset + offset, length);
430
431 _nvramImageDirty = true;
432
433 return kIOReturnSuccess;
434}
1c79356b
A
435
436// Private methods for Open Firmware variable access.
437
438struct OWVariablesHeader {
439 UInt16 owMagic;
440 UInt8 owVersion;
441 UInt8 owPages;
442 UInt16 owChecksum;
443 UInt16 owHere;
444 UInt16 owTop;
445 UInt16 owNext;
446 UInt32 owFlags;
447 UInt32 owNumbers[9];
448 struct {
449 UInt16 offset;
450 UInt16 length;
451 } owStrings[10];
452};
453typedef struct OWVariablesHeader OWVariablesHeader;
454
455IOReturn IODTNVRAM::initOFVariables(void)
456{
457 UInt32 cnt, propOffset, propType;
458 UInt8 *propName, *propData;
459 UInt32 propNameLength, propDataLength;
460 const OSSymbol *propSymbol;
461 OSObject *propObject;
462 OWVariablesHeader *owHeader;
463
464 if (_ofImage == 0) return kIOReturnNotReady;
465
466 _ofDict = OSDictionary::withCapacity(1);
467 if (_ofDict == 0) return kIOReturnNoMemory;
468
469 if (getPlatform()->getBootROMType()) {
470 cnt = 0;
471 while (cnt < _ofPartitionSize) {
472 // Break if there is no name.
473 if (_ofImage[cnt] == '\0') break;
474
475 // Find the length of the name.
476 propName = _ofImage + cnt;
477 for (propNameLength = 0; (cnt + propNameLength) < _ofPartitionSize;
478 propNameLength++) {
479 if (_ofImage[cnt + propNameLength] == '=') break;
480 }
481
482 // Break if the name goes past the end of the partition.
483 if ((cnt + propNameLength) >= _ofPartitionSize) break;
484 cnt += propNameLength + 1;
485
486 propData = _ofImage + cnt;
487 for (propDataLength = 0; (cnt + propDataLength) < _ofPartitionSize;
488 propDataLength++) {
489 if (_ofImage[cnt + propDataLength] == '\0') break;
490 }
491
492 // Break if the data goes past the end of the partition.
493 if ((cnt + propDataLength) >= _ofPartitionSize) break;
494 cnt += propDataLength + 1;
495
496 if (convertPropToObject(propName, propNameLength,
497 propData, propDataLength,
498 &propSymbol, &propObject)) {
499 _ofDict->setObject(propSymbol, propObject);
500 propSymbol->release();
501 propObject->release();
502 }
503 }
504
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();
511 }
512 }
513 } else {
514 owHeader = (OWVariablesHeader *)_ofImage;
515 if (!validateOWChecksum(_ofImage)) {
516 _ofDict->release();
517 _ofDict = 0;
518 return kIOReturnBadMedia;
519 }
520
521 cnt = 0;
522 while (1) {
523 if (!getOWVariableInfo(cnt++, &propSymbol, &propType, &propOffset))
524 break;
525
526 switch (propType) {
527 case kOFVariableTypeBoolean :
528 propObject = OSBoolean::withBoolean(owHeader->owFlags & propOffset);
529 break;
530
531 case kOFVariableTypeNumber :
532 propObject = OSNumber::withNumber(owHeader->owNumbers[propOffset], 32);
533 break;
534
535 case kOFVariableTypeString :
536 propData = _ofImage + owHeader->owStrings[propOffset].offset -
537 _ofPartitionOffset;
538 propDataLength = owHeader->owStrings[propOffset].length;
539 propName = IONew(UInt8, propDataLength + 1);
540 if (propName != 0) {
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);
545 }
546 break;
547 }
548
549 if (propObject == 0) break;
550
551 _ofDict->setObject(propSymbol, propObject);
552 propSymbol->release();
553 propObject->release();
554 }
555
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);
562 }
563 propSymbol->release();
564 }
565 }
566
567 return kIOReturnSuccess;
568}
569
570IOReturn IODTNVRAM::syncOFVariables(void)
571{
572 bool ok;
573 UInt32 cnt, length, maxLength;
574 UInt32 curOffset, tmpOffset, tmpType, tmpDataLength;
575 UInt8 *buffer, *tmpBuffer, *tmpData;
576 const OSSymbol *tmpSymbol;
577 OSObject *tmpObject;
578 OSBoolean *tmpBoolean;
579 OSNumber *tmpNumber;
580 OSString *tmpString;
581 OSCollectionIterator *iter;
582 OWVariablesHeader *owHeader, *owHeaderOld;
583
584 if ((_ofImage == 0) || (_ofDict == 0)) return kIOReturnNotReady;
585
586 if (!_ofImageDirty) return kIOReturnSuccess;
587
588 if (getPlatform()->getBootROMType()) {
589 buffer = tmpBuffer = IONew(UInt8, _ofPartitionSize);
590 if (buffer == 0) return kIOReturnNoMemory;
591 bzero(buffer, _ofPartitionSize);
592
593 ok = true;
594 maxLength = _ofPartitionSize;
595
596 iter = OSCollectionIterator::withCollection(_ofDict);
597 if (iter == 0) ok = false;
598
599 while (ok) {
600 tmpSymbol = OSDynamicCast(OSSymbol, iter->getNextObject());
601 if (tmpSymbol == 0) break;
602
603 tmpObject = _ofDict->getObject(tmpSymbol);
604
605 length = maxLength;
606 ok = convertObjectToProp(tmpBuffer, &length, tmpSymbol, tmpObject);
607 if (ok) {
608 tmpBuffer += length;
609 maxLength -= length;
610 }
611 }
612 iter->release();
613
614 if (ok) {
615 bcopy(buffer, _ofImage, _ofPartitionSize);
616 }
617
618 IODelete(buffer, UInt8, _ofPartitionSize);
619
620 if (!ok) return kIOReturnBadArgument;
621 } else {
622 buffer = IONew(UInt8, _ofPartitionSize);
623 if (buffer == 0) return kIOReturnNoMemory;
624 bzero(buffer, _ofPartitionSize);
625
626 owHeader = (OWVariablesHeader *)buffer;
627 owHeaderOld = (OWVariablesHeader *)_ofImage;
628
629 owHeader->owMagic = owHeaderOld->owMagic;
630 owHeader->owVersion = owHeaderOld->owVersion;
631 owHeader->owPages = owHeaderOld->owPages;
632
633 curOffset = _ofPartitionSize;
634
635 ok = true;
636 cnt = 0;
637 while (ok) {
638 if (!getOWVariableInfo(cnt++, &tmpSymbol, &tmpType, &tmpOffset))
639 break;
640
641 tmpObject = _ofDict->getObject(tmpSymbol);
642
643 switch (tmpType) {
644 case kOFVariableTypeBoolean :
645 tmpBoolean = OSDynamicCast(OSBoolean, tmpObject);
646 if (tmpBoolean->getValue()) owHeader->owFlags |= tmpOffset;
647 break;
648
649 case kOFVariableTypeNumber :
650 tmpNumber = OSDynamicCast(OSNumber, tmpObject);
651 owHeader->owNumbers[tmpOffset] = tmpNumber->unsigned32BitValue();
652 break;
653
654 case kOFVariableTypeString :
655 tmpString = OSDynamicCast(OSString, tmpObject);
656 tmpData = (UInt8 *) tmpString->getCStringNoCopy();
657 tmpDataLength = tmpString->getLength();
658
659 if ((curOffset - tmpDataLength) < sizeof(OWVariablesHeader)) {
660 ok = false;
661 break;
662 }
663
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);
669 break;
670 }
671 }
672
673 if (ok) {
674 owHeader->owHere = _ofPartitionOffset + sizeof(OWVariablesHeader);
675 owHeader->owTop = _ofPartitionOffset + curOffset;
676 owHeader->owNext = 0;
677
678 owHeader->owChecksum = 0;
679 owHeader->owChecksum = ~generateOWChecksum(buffer);
680
681 bcopy(buffer, _ofImage, _ofPartitionSize);
682 }
683
684 IODelete(buffer, UInt8, _ofPartitionSize);
685
686 if (!ok) return kIOReturnBadArgument;
687 }
688
689 _ofImageDirty = false;
690 _nvramImageDirty = true;
691
692 return kIOReturnSuccess;
693}
694
695struct OFVariable {
696 char *variableName;
697 UInt32 variableType;
698 UInt32 variablePerm;
699 SInt32 variableOffset;
700};
701typedef struct OFVariable OFVariable;
702
703enum {
704 kOWVariableOffsetNumber = 8,
705 kOWVariableOffsetString = 17
706};
707
708OFVariable 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}
755};
756
757UInt32 IODTNVRAM::getOFVariableType(const OSSymbol *propSymbol) const
758{
759 OFVariable *ofVar;
760
761 ofVar = gOFVariables;
762 while (1) {
763 if ((ofVar->variableName == 0) ||
764 propSymbol->isEqualTo(ofVar->variableName)) break;
765 ofVar++;
766 }
767
768 return ofVar->variableType;
769}
770
771UInt32 IODTNVRAM::getOFVariablePerm(const OSSymbol *propSymbol) const
772{
773 OFVariable *ofVar;
774
775 ofVar = gOFVariables;
776 while (1) {
777 if ((ofVar->variableName == 0) ||
778 propSymbol->isEqualTo(ofVar->variableName)) break;
779 ofVar++;
780 }
781
782 return ofVar->variablePerm;
783}
784
785bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber, const OSSymbol **propSymbol,
786 UInt32 *propType, UInt32 *propOffset)
787{
788 OFVariable *ofVar;
789
790 ofVar = gOFVariables;
791 while (1) {
792 if (ofVar->variableName == 0) return false;
793
794 if (ofVar->variableOffset == (SInt32) variableNumber) break;
795
796 ofVar++;
797 }
798
799 *propSymbol = OSSymbol::withCStringNoCopy(ofVar->variableName);
800 *propType = ofVar->variableType;
801
802 switch (*propType) {
803 case kOFVariableTypeBoolean :
804 *propOffset = 1 << (31 - variableNumber);
805 break;
806
807 case kOFVariableTypeNumber :
808 *propOffset = variableNumber - kOWVariableOffsetNumber;
809 break;
810
811 case kOFVariableTypeString :
812 *propOffset = variableNumber - kOWVariableOffsetString;
813 break;
814 }
815
816 return true;
817}
818
819bool IODTNVRAM::convertPropToObject(UInt8 *propName, UInt32 propNameLength,
820 UInt8 *propData, UInt32 propDataLength,
821 const OSSymbol **propSymbol,
822 OSObject **propObject)
823{
824 UInt32 propType;
825 const OSSymbol *tmpSymbol;
826 OSObject *tmpObject;
827 OSNumber *tmpNumber;
828 OSString *tmpString;
829
830 // Create the symbol.
831 propName[propNameLength] = '\0';
832 tmpSymbol = OSSymbol::withCString((const char *)propName);
833 propName[propNameLength] = '=';
834 if (tmpSymbol == 0) {
835 return false;
836 }
837
838 propType = getOFVariableType(tmpSymbol);
839
840 // Create the object.
841 tmpObject = 0;
842 switch (propType) {
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;
848 }
849 break;
850
851 case kOFVariableTypeNumber :
852 tmpNumber = OSNumber::withNumber(strtol((const char *)propData, 0, 0), 32);
853 if (tmpNumber != 0) tmpObject = tmpNumber;
854 break;
855
856 case kOFVariableTypeString :
857 tmpString = OSString::withCString((const char *)propData);
858 if (tmpString != 0) tmpObject = tmpString;
859 break;
860
861 case kOFVariableTypeData :
862 tmpObject = unescapeBytesToData(propData, propDataLength);
863 break;
864 }
865
866 if (tmpObject == 0) {
867 tmpSymbol->release();
868 return false;
869 }
870
871 *propSymbol = tmpSymbol;
872 *propObject = tmpObject;
873
874 return true;
875}
876
877bool IODTNVRAM::convertObjectToProp(UInt8 *buffer, UInt32 *length,
878 const OSSymbol *propSymbol, OSObject *propObject)
879{
880 UInt8 *propName;
881 UInt32 propNameLength, propDataLength;
882 UInt32 propType, tmpValue;
883 OSBoolean *tmpBoolean = 0;
884 OSNumber *tmpNumber = 0;
885 OSString *tmpString = 0;
886 OSData *tmpData = 0;
887
888 propName = (UInt8 *)propSymbol->getCStringNoCopy();
889 propNameLength = propSymbol->getLength();
890 propType = getOFVariableType(propSymbol);
891
892 // Get the size of the data.
893 propDataLength = 0xFFFFFFFF;
894 switch (propType) {
895 case kOFVariableTypeBoolean :
896 tmpBoolean = OSDynamicCast(OSBoolean, propObject);
897 if (tmpBoolean != 0) propDataLength = 5;
898 break;
899
900 case kOFVariableTypeNumber :
901 tmpNumber = OSDynamicCast(OSNumber, propObject);
902 if (tmpNumber != 0) propDataLength = 10;
903 break;
904
905 case kOFVariableTypeString :
906 tmpString = OSDynamicCast(OSString, propObject);
907 if (tmpString != 0) propDataLength = tmpString->getLength();
908 break;
909
910 case kOFVariableTypeData :
911 tmpData = OSDynamicCast(OSData, propObject);
912 if (tmpData != 0) {
913 tmpData = escapeDataToData(tmpData);
914 propDataLength = tmpData->getLength();
915 }
916 break;
917 }
918
919 // Make sure the propertySize is known and will fit.
920 if (propDataLength == 0xFFFFFFFF) return false;
921 if ((propNameLength + propDataLength + 2) > *length) return false;
922
923 // Copy the property name equal sign.
924 sprintf((char *)buffer, "%s=", propName);
925 buffer += propNameLength + 1;
926
927 switch (propType) {
928 case kOFVariableTypeBoolean :
929 if (tmpBoolean->getValue()) {
930 strcpy((char *)buffer, "true");
931 } else {
932 strcpy((char *)buffer, "false");
933 }
934 break;
935
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);
942 } else {
943 sprintf((char *)buffer, "0x%lx", tmpValue);
944 }
945 break;
946
947 case kOFVariableTypeString :
948 strcpy((char *)buffer, tmpString->getCStringNoCopy());
949 break;
950
951 case kOFVariableTypeData :
952 bcopy(tmpData->getBytesNoCopy(), buffer, propDataLength);
953 tmpData->release();
954 break;
955 }
956
957 propDataLength = strlen((const char *)buffer);
958
959 *length = propNameLength + propDataLength + 2;
960
961 return true;
962}
963
964
965UInt16 IODTNVRAM::generateOWChecksum(UInt8 *buffer)
966{
967 UInt32 cnt, checksum = 0;
968 UInt16 *tmpBuffer = (UInt16 *)buffer;
969
970 for (cnt = 0; cnt < _ofPartitionSize / 2; cnt++)
971 checksum += tmpBuffer[cnt];
972
973 return checksum % 0x0000FFFF;
974}
975
976bool IODTNVRAM::validateOWChecksum(UInt8 *buffer)
977{
978 UInt32 cnt, checksum, sum = 0;
979 UInt16 *tmpBuffer = (UInt16 *)buffer;
980
981 for (cnt = 0; cnt < _ofPartitionSize / 2; cnt++)
982 sum += tmpBuffer[cnt];
983
984 checksum = (sum >> 16) + (sum & 0x0000FFFF);
985 if (checksum == 0x10000) checksum--;
986 checksum = (checksum ^ 0x0000FFFF) & 0x0000FFFF;
987
988 return checksum == 0;
989}
990
991void IODTNVRAM::updateOWBootArgs(const OSSymbol *key, OSObject *value)
992{
993 bool wasBootArgs, bootr = false;
994 UInt32 cnt;
995 OSString *tmpString, *bootCommand, *bootArgs = 0;
996 UInt8 *bootCommandData, *bootArgsData, *tmpData;
997 UInt32 bootCommandDataLength, bootArgsDataLength, tmpDataLength;
998
999 tmpString = OSDynamicCast(OSString, value);
1000 if (tmpString == 0) return;
1001
1002 if (key->isEqualTo("boot-command")) {
1003 wasBootArgs = false;
1004 bootCommand = tmpString;
1005 } else if (key->isEqualTo("boot-args")) {
1006 wasBootArgs = true;
1007 bootArgs = tmpString;
1008 bootCommand = OSDynamicCast(OSString, _ofDict->getObject("boot-command"));
1009 if (bootCommand == 0) return;
1010 } else return;
1011
1012 bootCommandData = (UInt8 *)bootCommand->getCStringNoCopy();
1013 bootCommandDataLength = bootCommand->getLength();
1014
1015 if (bootCommandData == 0) return;
1016
1017 for (cnt = 0; cnt < bootCommandDataLength; cnt++) {
1018 if ((bootCommandData[cnt] == 'b') &&
1019 !strncmp("bootr", (const char *)bootCommandData + cnt, 5)) {
1020 cnt += 5;
1021 while (bootCommandData[cnt] == ' ') cnt++;
1022 bootr = true;
1023 break;
1024 }
1025 }
1026 if (!bootr) {
1027 _ofDict->removeObject("boot-args");
1028 return;
1029 }
1030
1031 if (wasBootArgs) {
1032 bootArgsData = (UInt8 *)bootArgs->getCStringNoCopy();
1033 bootArgsDataLength = bootArgs->getLength();
1034 if (bootArgsData == 0) return;
1035
1036 tmpDataLength = cnt + bootArgsDataLength;
1037 tmpData = IONew(UInt8, tmpDataLength + 1);
1038 if (tmpData == 0) return;
1039
1040 strncpy((char *)tmpData, (const char *)bootCommandData, cnt);
1041 tmpData[cnt] = '\0';
1042 strcat((char *)tmpData, (const char *)bootArgsData);
1043
1044 bootCommand = OSString::withCString((const char *)tmpData);
1045 if (bootCommand != 0) {
1046 _ofDict->setObject("boot-command", bootCommand);
1047 bootCommand->release();
1048 }
1049
1050 IODelete(tmpData, UInt8, tmpDataLength + 1);
1051 } else {
1052 bootArgs = OSString::withCString((const char *)(bootCommandData + cnt));
1053 if (bootArgs != 0) {
1054 _ofDict->setObject("boot-args", bootArgs);
1055 bootArgs->release();
1056 }
1057 }
1058}
1059
1060
1061// Private methods for Name Registry access.
1062
1063enum {
1064 kMaxNVNameLength = 4,
1065 kMaxNVDataLength = 8
1066};
1067
1068#pragma options align=mac68k
1069struct NVRAMProperty
1070{
1071 IONVRAMDescriptor header;
1072 UInt8 nameLength;
1073 UInt8 name[ kMaxNVNameLength ];
1074 UInt8 dataLength;
1075 UInt8 data[ kMaxNVDataLength ];
1076};
1077#pragma options align=reset
1078
1079bool IODTNVRAM::searchNVRAMProperty(IONVRAMDescriptor *hdr, UInt32 *where)
1080{
1081 UInt32 offset;
1082 SInt32 nvEnd;
1083
1084 nvEnd = *((UInt16 *)_nrImage);
1085 if(getPlatform()->getBootROMType()) {
1086 // on NewWorld, offset to partition start
1087 nvEnd -= 0x100;
1088 } else {
1089 // on old world, absolute
1090 nvEnd -= _nrPartitionOffset;
1091 }
1092 if((nvEnd < 0) || (nvEnd >= kIODTNVRAMNameRegistrySize))
1093 nvEnd = 2;
1094
1095 offset = 2;
1096 while ((offset + sizeof(NVRAMProperty)) <= (UInt32)nvEnd) {
1097 if (bcmp(_nrImage + offset, hdr, sizeof(*hdr)) == 0) {
1098 *where = offset;
1099 return true;
1100 }
1101 offset += sizeof(NVRAMProperty);
1102 }
1103
1104 if ((nvEnd + sizeof(NVRAMProperty)) <= kIODTNVRAMNameRegistrySize)
1105 *where = nvEnd;
1106 else
1107 *where = 0;
1108
1109 return false;
1110}
1111
1112IOReturn IODTNVRAM::readNVRAMPropertyType0(IORegistryEntry *entry,
1113 const OSSymbol **name,
1114 OSData **value)
1115{
1116 IONVRAMDescriptor hdr;
1117 NVRAMProperty *prop;
1118 IOByteCount length;
1119 UInt32 offset;
1120 IOReturn err;
1121 char nameBuf[kMaxNVNameLength + 1];
1122
1123 if (_nrImage == 0) return kIOReturnUnsupported;
1124 if ((entry == 0) || (name == 0) || (value == 0)) return kIOReturnBadArgument;
1125
1126 err = IODTMakeNVDescriptor(entry, &hdr);
1127 if (err != kIOReturnSuccess) return err;
1128
1129 if (searchNVRAMProperty(&hdr, &offset)) {
1130 prop = (NVRAMProperty *)(_nrImage + offset);
1131
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);
1137
1138 length = prop->dataLength;
1139 if (length > kMaxNVDataLength) length = kMaxNVDataLength;
1140 *value = OSData::withBytes(prop->data, length);
1141
1142 if ((*name != 0) && (*value != 0)) return kIOReturnSuccess;
1143 else return kIOReturnNoMemory;
1144 }
1145
1146 return kIOReturnNoResources;
1147}
1148
1149IOReturn IODTNVRAM::writeNVRAMPropertyType0(IORegistryEntry *entry,
1150 const OSSymbol *name,
1151 OSData *value)
1152{
1153 IONVRAMDescriptor hdr;
1154 NVRAMProperty *prop;
1155 IOByteCount nameLength;
1156 IOByteCount dataLength;
1157 UInt32 offset;
1158 IOReturn err;
1159 UInt16 nvLength;
1160 bool exists;
1161
1162 if (_nrImage == 0) return kIOReturnUnsupported;
1163 if ((entry == 0) || (name == 0) || (value == 0)) return kIOReturnBadArgument;
1164
1165 nameLength = name->getLength();
1166 dataLength = value->getLength();
1167 if (nameLength > kMaxNVNameLength) return kIOReturnNoSpace;
1168 if (dataLength > kMaxNVDataLength) return kIOReturnNoSpace;
1169
1170 err = IODTMakeNVDescriptor(entry, &hdr);
1171 if (err != kIOReturnSuccess) return err;
1172
1173 exists = searchNVRAMProperty(&hdr, &offset);
1174 if (offset == 0) return kIOReturnNoMemory;
1175
1176 prop = (NVRAMProperty *)(_nrImage + offset);
1177 if (!exists) bcopy(&hdr, &prop->header, sizeof(hdr));
1178
1179 prop->nameLength = nameLength;
1180 bcopy(name->getCStringNoCopy(), prop->name, nameLength);
1181 prop->dataLength = dataLength;
1182 bcopy(value->getBytesNoCopy(), prop->data, dataLength);
1183
1184 if (!exists) {
1185 nvLength = offset + sizeof(NVRAMProperty);
1186 if (getPlatform()->getBootROMType())
1187 nvLength += 0x100;
1188 else
1189 nvLength += _nrPartitionOffset;
1190 *((UInt16 *)_nrImage) = nvLength;
1191 }
1192
1193 _nvramImageDirty = true;
1194
1195 return err;
1196}
1197
1198OSData *IODTNVRAM::unescapeBytesToData(UInt8 *bytes, UInt32 length)
1199{
1200 OSData *data = 0;
1201 UInt32 totalLength = 0;
1202 UInt32 cnt, cnt2;
1203 UInt8 byte;
1204 bool ok;
1205
1206 // Calculate the actual length of the data.
1207 ok = true;
1208 totalLength = 0;
1209 for (cnt = 0; cnt < length;) {
1210 byte = bytes[cnt++];
1211 if (byte == 0xFF) {
1212 byte = bytes[cnt++];
1213 if (byte == 0x00) {
1214 ok = false;
1215 break;
1216 }
1217 cnt2 = byte & 0x7F;
1218 } else
1219 cnt2 = 1;
1220 totalLength += cnt2;
1221 }
1222
1223 if (ok) {
1224 // Create an empty OSData of the correct size.
1225 data = OSData::withCapacity(totalLength);
1226 if (data != 0) {
1227 for (cnt = 0; cnt < length;) {
1228 byte = bytes[cnt++];
1229 if (byte == 0xFF) {
1230 byte = bytes[cnt++];
1231 cnt2 = byte & 0x7F;
1232 byte = (byte & 0x80) ? 0xFF : 0x00;
1233 } else
1234 cnt2 = 1;
1235 data->appendByte(byte, cnt2);
1236 }
1237 }
1238 }
1239
1240 return data;
1241}
1242
1243OSData * IODTNVRAM::escapeDataToData(OSData * value)
1244{
1245 OSData * result;
1246 UInt8 * start;
1247 UInt8 * end;
1248 UInt8 * where;
1249 UInt8 byte;
1250 bool ok = true;
1251
1252 where = (UInt8 *) value->getBytesNoCopy();
1253 end = where + value->getLength();
1254
1255 result = OSData::withCapacity(end - where);
1256 if (!result)
1257 return result;
1258
1259 while (where < end) {
1260 start = where;
1261 byte = *where++;
1262 if ((byte == 0x00) || (byte == 0xFF)) {
1263 for (;
1264 ((where - start) < 0x80) && (where < end) && (byte == *where);
1265 where++) {}
1266 ok &= result->appendByte(0xff, 1);
1267 byte = (byte & 0x80) | (where - start);
1268 }
1269 ok &= result->appendByte(byte, 1);
1270 }
1271 ok &= result->appendByte(0, 1);
1272
1273 if (!ok) {
1274 result->release();
1275 result = 0;
1276 }
1277
1278 return result;
1279}
1280
1281IOReturn IODTNVRAM::readNVRAMPropertyType1(IORegistryEntry *entry,
1282 const OSSymbol **name,
1283 OSData **value)
1284{
1285 IOReturn err = kIOReturnNoResources;
1286 OSData *data;
1287 UInt8 *start;
1288 UInt8 *end;
1289 UInt8 *where;
1290 UInt8 *nvPath = 0;
1291 UInt8 *nvName = 0;
1292 UInt8 byte;
1293
1294 if (_ofDict == 0) return err;
1295 data = OSDynamicCast(OSData, _ofDict->getObject(_registryPropertiesKey));
1296 if (data == 0) return err;
1297
1298 start = (UInt8 *) data->getBytesNoCopy();
1299 end = start + data->getLength();
1300
1301 where = start;
1302 while (where < end) {
1303 byte = *(where++);
1304 if (byte)
1305 continue;
1306
1307 if (nvPath == 0)
1308 nvPath = start;
1309 else if (nvName == 0)
1310 nvName = start;
1311 else if (entry ==
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;
1317 else
1318 err = kIOReturnNoMemory;
1319 break;
1320 } else
1321 nvPath = nvName = 0;
1322
1323 start = where;
1324 }
1325
1326 return err;
1327}
1328
1329IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry,
1330 const OSSymbol *propName,
1331 OSData *value)
1332{
1333 OSData *oldData;
1334 OSData *data = 0;
1335 UInt8 *start;
1336 UInt8 *propStart;
1337 UInt8 *end;
1338 UInt8 *where;
1339 UInt8 *nvPath = 0;
1340 UInt8 *nvName = 0;
1341 const char * comp;
1342 const char * name;
1343 UInt8 byte;
1344 bool ok = true;
1345
1346 if (_ofDict == 0) return kIOReturnNoResources;
1347
1348 // copy over existing properties for other entries
1349
1350 oldData = OSDynamicCast(OSData, _ofDict->getObject(_registryPropertiesKey));
1351 if (oldData) {
1352 start = (UInt8 *) oldData->getBytesNoCopy();
1353 end = start + oldData->getLength();
1354
1355 propStart = start;
1356 where = start;
1357 while (where < end) {
1358 byte = *(where++);
1359 if (byte)
1360 continue;
1361 if (nvPath == 0)
1362 nvPath = start;
1363 else if (nvName == 0)
1364 nvName = start;
1365 else if (entry ==
1366 IORegistryEntry::fromPath((const char *) nvPath, gIODTPlane)) {
1367 // delete old property (nvPath -> where)
1368 data = OSData::withBytes(propStart, nvPath - propStart);
1369 if (data)
1370 ok &= data->appendBytes(where, end - where);
1371 break;
1372 } else
1373 nvPath = nvName = 0;
1374
1375 start = where;
1376 }
1377 }
1378
1379 // make the new property
1380
1381 if (!data) {
1382 if (oldData)
1383 data = OSData::withData(oldData);
1384 else
1385 data = OSData::withCapacity(16);
1386 if (!data)
1387 return kIOReturnNoMemory;
1388 }
1389
1390 // get entries in path
1391 OSArray *array = OSArray::withCapacity(5);
1392 if (!array) {
1393 data->release();
1394 return kIOReturnNoMemory;
1395 }
1396 do
1397 array->setObject(entry);
1398 while ((entry = entry->getParentEntry(gIODTPlane)));
1399
1400 // append path
1401 for (int i = array->getCount() - 3;
1402 (entry = (IORegistryEntry *) array->getObject(i));
1403 i--) {
1404
1405 name = entry->getName(gIODTPlane);
1406 comp = entry->getLocation(gIODTPlane);
1407 if( comp && (0 == strcmp("pci", name))
1408 && (0 == strcmp("80000000", comp))) {
1409 // yosemite hack
1410 comp = "/pci@80000000";
1411 } else {
1412 if (comp)
1413 ok &= data->appendBytes("/@", 2);
1414 else {
1415 if (!name)
1416 continue;
1417 ok &= data->appendByte('/', 1);
1418 comp = name;
1419 }
1420 }
1421 ok &= data->appendBytes(comp, strlen(comp));
1422 }
1423 ok &= data->appendByte(0, 1);
1424 array->release();
1425
1426 // append prop name
1427 ok &= data->appendBytes(propName->getCStringNoCopy(), propName->getLength() + 1);
1428
1429 // append escaped data
1430 oldData = escapeDataToData(value);
1431 ok &= (oldData != 0);
1432 if (ok)
1433 ok &= data->appendBytes(oldData);
1434
1435 if (ok) {
1436 ok = _ofDict->setObject(_registryPropertiesKey, data);
1437 if (ok)
1438 _ofImageDirty = true;
1439 }
1440 data->release();
1441
1442 return ok ? kIOReturnSuccess : kIOReturnNoMemory;
1443}