]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IONVRAM.cpp
xnu-4570.71.2.tar.gz
[apple/xnu.git] / iokit / Kernel / IONVRAM.cpp
index 6a819b459c7fab720e4a6ea938d05c0399ae254c..94d6b75dd77d0ce7bb88afa83cf6ef4874ee2d64 100644 (file)
@@ -118,7 +118,9 @@ void IODTNVRAM::registerNVRAMController(IONVRAMController *nvram)
     _nvramController->read(0, _nvramImage, kIODTNVRAMImageSize);
     initNVRAMImage();
   } else {
-    syncOFVariables();
+    IOLockLock(_ofLock);
+    (void) syncVariables();
+    IOLockUnlock(_ofLock);
   }
 }
 
@@ -139,9 +141,11 @@ void IODTNVRAM::initNVRAMImage(void)
   // Look through the partitions to find the OF, MacOS partitions.
   while (currentOffset < kIODTNVRAMImageSize) {
     currentLength = ((UInt16 *)(_nvramImage + currentOffset))[1] * 16;
-    
+
+    if (currentLength < 16) break;
     partitionOffset = currentOffset + 16;
     partitionLength = currentLength - 16;
+    if ((partitionOffset + partitionLength) > kIODTNVRAMImageSize) break;
     
     if (strncmp((const char *)_nvramImage + currentOffset + 4,
                kIODTNVRAMOFPartitionName, 12) == 0) {
@@ -381,14 +385,13 @@ bool IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject)
   bool     result;
   UInt32   propType, propPerm;
   OSString *tmpString;
-  OSObject *propObject = 0;
-  
+  OSObject *propObject = 0, *oldObject;
+
   if (_ofDict == 0) return false;
-  
+
   // Verify permissions.
   propPerm = getOFVariablePerm(aKey);
-  result = IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege);
-  if (result != kIOReturnSuccess) {
+  if (IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege) != kIOReturnSuccess) {
     if (propPerm != kOFVariablePermUserWrite) return false;
   }
   if (propPerm == kOFVariablePermKernelOnly && current_task() != kernel_task) return 0;
@@ -408,15 +411,15 @@ bool IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject)
   case kOFVariableTypeBoolean :
     propObject = OSDynamicCast(OSBoolean, anObject);
     break;
-    
+
   case kOFVariableTypeNumber :
     propObject = OSDynamicCast(OSNumber, anObject);
     break;
-    
+
   case kOFVariableTypeString :
     propObject = OSDynamicCast(OSString, anObject);
     break;
-    
+
   case kOFVariableTypeData :
     propObject = OSDynamicCast(OSData, anObject);
     if (propObject == 0) {
@@ -428,17 +431,36 @@ bool IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject)
     }
     break;
   }
-  
+
   if (propObject == 0) return false;
 
   IOLockLock(_ofLock);
+
+  oldObject = _ofDict->getObject(aKey);
+  if (oldObject) {
+    oldObject->retain();
+  }
   result = _ofDict->setObject(aKey, propObject);
-  IOLockUnlock(_ofLock);
 
   if (result) {
-    syncOFVariables();
+    if (syncVariables() != kIOReturnSuccess) {
+        if (oldObject) {
+          _ofDict->setObject(aKey, oldObject);
+        }
+        else {
+          _ofDict->removeObject(aKey);
+        }
+        (void) syncVariables();
+        result = false;
+    }
   }
-  
+
+  if (oldObject) {
+    oldObject->release();
+  }
+
+  IOLockUnlock(_ofLock);
+
   return result;
 }
 
@@ -473,11 +495,12 @@ void IODTNVRAM::removeProperty(const OSSymbol *aKey)
   if (result) {
     _ofDict->removeObject(aKey);
   }
-  IOLockUnlock(_ofLock);
 
   if (result) {
-    syncOFVariables();
+    (void) syncVariables();
   }
+
+  IOLockUnlock(_ofLock);
 }
 
 IOReturn IODTNVRAM::setProperties(OSObject *properties)
@@ -582,7 +605,7 @@ IOReturn IODTNVRAM::readNVRAMPartition(const OSSymbol *partitionID,
                                       IOByteCount length)
 {
   OSNumber *partitionOffsetNumber, *partitionLengthNumber;
-  UInt32   partitionOffset, partitionLength;
+  UInt32   partitionOffset, partitionLength, end;
   
   partitionOffsetNumber =
     (OSNumber *)_nvramPartitionOffsets->getObject(partitionID);
@@ -595,8 +618,8 @@ IOReturn IODTNVRAM::readNVRAMPartition(const OSSymbol *partitionID,
   partitionOffset = partitionOffsetNumber->unsigned32BitValue();
   partitionLength = partitionLengthNumber->unsigned32BitValue();
   
-  if ((buffer == 0) || (length == 0) ||
-      (offset + length > partitionLength))
+  if (os_add_overflow(offset, length, &end)) return kIOReturnBadArgument;
+  if ((buffer == 0) || (length == 0) || (end > partitionLength))
     return kIOReturnBadArgument;
   
   bcopy(_nvramImage + partitionOffset + offset, buffer, length);
@@ -609,7 +632,7 @@ IOReturn IODTNVRAM::writeNVRAMPartition(const OSSymbol *partitionID,
                                        IOByteCount length)
 {
   OSNumber *partitionOffsetNumber, *partitionLengthNumber;
-  UInt32   partitionOffset, partitionLength;
+  UInt32   partitionOffset, partitionLength, end;
   
   partitionOffsetNumber =
     (OSNumber *)_nvramPartitionOffsets->getObject(partitionID);
@@ -622,8 +645,8 @@ IOReturn IODTNVRAM::writeNVRAMPartition(const OSSymbol *partitionID,
   partitionOffset = partitionOffsetNumber->unsigned32BitValue();
   partitionLength = partitionLengthNumber->unsigned32BitValue();
   
-  if ((buffer == 0) || (length == 0) ||
-      (offset + length > partitionLength))
+  if (os_add_overflow(offset, length, &end)) return kIOReturnBadArgument;
+  if ((buffer == 0) || (length == 0) || (end > partitionLength))
     return kIOReturnBadArgument;
   
   bcopy(buffer, _nvramImage + partitionOffset + offset, length);
@@ -736,7 +759,6 @@ IOReturn IODTNVRAM::initOFVariables(void)
     }
   }
   
-  // Create the 'aapl,panic-info' property if needed.
   if (_piImage != 0) {
     propDataLength = *(UInt32 *)_piImage;
     if ((propDataLength != 0) && (propDataLength <= (_piPartitionSize - 4))) {
@@ -756,6 +778,11 @@ IOReturn IODTNVRAM::initOFVariables(void)
 }
 
 IOReturn IODTNVRAM::syncOFVariables(void)
+{
+  return kIOReturnUnsupported;
+}
+
+IOReturn IODTNVRAM::syncVariables(void)
 {
   bool                 ok;
   UInt32               length, maxLength;
@@ -763,29 +790,30 @@ IOReturn IODTNVRAM::syncOFVariables(void)
   const OSSymbol       *tmpSymbol;
   OSObject             *tmpObject;
   OSCollectionIterator *iter;
-  
+
+  IOLockAssert(_ofLock, kIOLockAssertOwned);
+
   if ((_ofImage == 0) || (_ofDict == 0) || _systemPaniced) return kIOReturnNotReady;
-  
+
   buffer = tmpBuffer = IONew(UInt8, _ofPartitionSize);
   if (buffer == 0) return kIOReturnNoMemory;
   bzero(buffer, _ofPartitionSize);
-  
+
   ok = true;
   maxLength = _ofPartitionSize;
 
-  IOLockLock(_ofLock);
   iter = OSCollectionIterator::withCollection(_ofDict);
   if (iter == 0) ok = false;
-  
+
   while (ok) {
     tmpSymbol = OSDynamicCast(OSSymbol, iter->getNextObject());
     if (tmpSymbol == 0) break;
-    
+
     // Don't save 'aapl,panic-info'.
     if (tmpSymbol->isEqualTo(kIODTNVRAMPanicInfoKey)) continue;
-    
+
     tmpObject = _ofDict->getObject(tmpSymbol);
-    
+
     length = maxLength;
     ok = convertObjectToProp(tmpBuffer, &length, tmpSymbol, tmpObject);
     if (ok) {
@@ -794,21 +822,20 @@ IOReturn IODTNVRAM::syncOFVariables(void)
     }
   }
   iter->release();
-  IOLockUnlock(_ofLock);
-  
+
   if (ok) {
     bcopy(buffer, _ofImage, _ofPartitionSize);
   }
-  
+
   IODelete(buffer, UInt8, _ofPartitionSize);
-  
+
   if (!ok) return kIOReturnBadArgument;
-  
+
   if (_nvramController != 0) {
-    _nvramController->write(0, _nvramImage, kIODTNVRAMImageSize);
+    return _nvramController->write(0, _nvramImage, kIODTNVRAMImageSize);
   }
-  
-  return kIOReturnSuccess;
+
+  return kIOReturnNotReady;
 }
 
 struct OFVariable {
@@ -824,6 +851,7 @@ enum {
   kOWVariableOffsetString = 17
 };
 
+static const
 OFVariable gOFVariables[] = {
   {"little-endian?", kOFVariableTypeBoolean, kOFVariablePermUserRead, 0},
   {"real-mode?", kOFVariableTypeBoolean, kOFVariablePermUserRead, 1},
@@ -872,12 +900,22 @@ OFVariable gOFVariables[] = {
   {"security-password", kOFVariableTypeData, kOFVariablePermRootOnly, -1},
   {"boot-image", kOFVariableTypeData, kOFVariablePermUserWrite, -1},
   {"com.apple.System.fp-state", kOFVariableTypeData, kOFVariablePermKernelOnly, -1},
+#if CONFIG_EMBEDDED
+  {"backlight-level", kOFVariableTypeData, kOFVariablePermUserWrite, -1},
+  {"com.apple.System.sep.art", kOFVariableTypeData, kOFVariablePermKernelOnly, -1},
+  {"com.apple.System.boot-nonce", kOFVariableTypeString, kOFVariablePermKernelOnly, -1},
+  {"darkboot", kOFVariableTypeBoolean, kOFVariablePermUserWrite, -1},
+  {"acc-mb-ld-lifetime", kOFVariableTypeNumber, kOFVariablePermKernelOnly, -1},
+  {"acc-cm-override-charger-count", kOFVariableTypeNumber, kOFVariablePermKernelOnly, -1},
+  {"acc-cm-override-count", kOFVariableTypeNumber, kOFVariablePermKernelOnly, -1},
+  {"enter-tdm-mode", kOFVariableTypeBoolean, kOFVariablePermUserWrite, -1},
+#endif
   {0, kOFVariableTypeData, kOFVariablePermUserRead, -1}
 };
 
 UInt32 IODTNVRAM::getOFVariableType(const OSSymbol *propSymbol) const
 {
-  OFVariable *ofVar;
+  const OFVariable *ofVar;
   
   ofVar = gOFVariables;
   while (1) {
@@ -891,7 +929,7 @@ UInt32 IODTNVRAM::getOFVariableType(const OSSymbol *propSymbol) const
 
 UInt32 IODTNVRAM::getOFVariablePerm(const OSSymbol *propSymbol) const
 {
-  OFVariable *ofVar;
+  const OFVariable *ofVar;
   
   ofVar = gOFVariables;
   while (1) {
@@ -906,7 +944,7 @@ UInt32 IODTNVRAM::getOFVariablePerm(const OSSymbol *propSymbol) const
 bool IODTNVRAM::getOWVariableInfo(UInt32 variableNumber, const OSSymbol **propSymbol,
                                  UInt32 *propType, UInt32 *propOffset)
 {
-  OFVariable *ofVar;
+  const OFVariable *ofVar;
   
   ofVar = gOFVariables;
   while (1) {
@@ -999,7 +1037,7 @@ bool IODTNVRAM::convertObjectToProp(UInt8 *buffer, UInt32 *length,
                                    const OSSymbol *propSymbol, OSObject *propObject)
 {
   const UInt8    *propName;
-  UInt32         propNameLength, propDataLength;
+  UInt32         propNameLength, propDataLength, remaining;
   UInt32         propType, tmpValue;
   OSBoolean      *tmpBoolean = 0;
   OSNumber       *tmpNumber = 0;
@@ -1043,29 +1081,30 @@ bool IODTNVRAM::convertObjectToProp(UInt8 *buffer, UInt32 *length,
   
   // Copy the property name equal sign.
   buffer += snprintf((char *)buffer, *length, "%s=", propName);
-  
+  remaining = *length - propNameLength - 1;
+
   switch (propType) {
   case kOFVariableTypeBoolean :
     if (tmpBoolean->getValue()) {
-      strlcpy((char *)buffer, "true", *length - propNameLength);
+      strlcpy((char *)buffer, "true", remaining);
     } else {
-      strlcpy((char *)buffer, "false", *length - propNameLength);
+      strlcpy((char *)buffer, "false", remaining);
     }
     break;
     
   case kOFVariableTypeNumber :
     tmpValue = tmpNumber->unsigned32BitValue();
     if (tmpValue == 0xFFFFFFFF) {
-      strlcpy((char *)buffer, "-1", *length - propNameLength);
+      strlcpy((char *)buffer, "-1", remaining);
     } else if (tmpValue < 1000) {
-      snprintf((char *)buffer, *length - propNameLength, "%d", (uint32_t)tmpValue);
+      snprintf((char *)buffer, remaining, "%d", (uint32_t)tmpValue);
     } else {
-      snprintf((char *)buffer, *length - propNameLength, "0x%x", (uint32_t)tmpValue);
+      snprintf((char *)buffer, remaining, "0x%x", (uint32_t)tmpValue);
     }
     break;
     
   case kOFVariableTypeString :
-    strlcpy((char *)buffer, tmpString->getCStringNoCopy(), *length - propNameLength);
+    strlcpy((char *)buffer, tmpString->getCStringNoCopy(), remaining);
     break;
     
   case kOFVariableTypeData :
@@ -1363,7 +1402,7 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry,
                                            const OSSymbol *propName,
                                            OSData *value)
 {
-  OSData       *oldData;
+  OSData       *oldData, *escapedData;
   OSData       *data = 0;
   const UInt8  *startPtr;
   const UInt8  *propStart;
@@ -1387,9 +1426,10 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry,
 
   oldData = OSDynamicCast(OSData, _ofDict->getObject(_registryPropertiesKey));
   if (oldData) {
+
     startPtr = (const UInt8 *) oldData->getBytesNoCopy();
     endPtr = startPtr + oldData->getLength();
-    
+
     propStart = startPtr;
     wherePtr = startPtr;
     while (wherePtr < endPtr) {
@@ -1417,7 +1457,7 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry,
         nvPath = 0;
         nvName = 0;
       }
-        
+
       startPtr = wherePtr;
     }
   }
@@ -1463,22 +1503,39 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry,
 
     // append prop name
     ok &= data->appendBytes(propName->getCStringNoCopy(), propName->getLength() + 1);
-  
+
     // append escaped data
-    oldData = escapeDataToData(value);
-    ok &= (oldData != 0);
-    if (ok) ok &= data->appendBytes(oldData);
+    escapedData = escapeDataToData(value);
+    ok &= (escapedData != 0);
+    if (ok) ok &= data->appendBytes(escapedData);
 
   } while (false);
 
+  oldData->retain();
   if (ok) {
     ok = _ofDict->setObject(_registryPropertiesKey, data);
   }
 
-  IOLockUnlock(_ofLock);
   if (data) data->release();
 
-  if (ok) syncOFVariables();
+  if (ok) {
+    if (syncVariables() != kIOReturnSuccess) {
+      if (oldData) {
+        _ofDict->setObject(_registryPropertiesKey, oldData);
+      }
+      else {
+        _ofDict->removeObject(_registryPropertiesKey);
+      }
+      (void) syncVariables();
+      ok = false;
+    }
+  }
+
+  if (oldData) {
+    oldData->release();
+  }
+
+  IOLockUnlock(_ofLock);
 
   return ok ? kIOReturnSuccess : kIOReturnNoMemory;
 }