Loading...
iokit/Kernel/IONVRAMCHRPHandler.cpp xnu-12377.101.15 /dev/null
--- xnu/xnu-12377.101.15/iokit/Kernel/IONVRAMCHRPHandler.cpp
+++ /dev/null
@@ -1,1282 +0,0 @@
-/*
- * Copyright (c) 2021-2022 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#include <libkern/c++/OSBoundedPtr.h>
-
-#define NVRAM_CHRP_APPLE_HEADER_NAME_V1  "nvram"
-#define NVRAM_CHRP_APPLE_HEADER_NAME_V2  "2nvram"
-
-#define NVRAM_CHRP_PARTITION_NAME_COMMON_V1   "common"
-#define NVRAM_CHRP_PARTITION_NAME_SYSTEM_V1   "system"
-#define NVRAM_CHRP_PARTITION_NAME_COMMON_V2   "2common"
-#define NVRAM_CHRP_PARTITION_NAME_SYSTEM_V2   "2system"
-
-#define NVRAM_CHRP_LENGTH_BLOCK_SIZE 0x10 // CHRP length field is in 16 byte blocks
-
-typedef struct chrp_nvram_header { //16 bytes
-	uint8_t  sig;
-	uint8_t  cksum; // checksum on sig, len, and name
-	uint16_t len;   // total length of the partition in 16 byte blocks starting with the signature
-	// and ending with the last byte of data area, ie len includes its own header size
-	char     name[12];
-	uint8_t  data[0];
-} chrp_nvram_header_t;
-
-typedef struct apple_nvram_header {  // 16 + 16 bytes
-	struct   chrp_nvram_header chrp;
-	uint32_t adler;
-	uint32_t generation;
-	uint8_t  padding[8];
-} apple_nvram_header_t;
-
-typedef struct {
-	NVRAMPartitionType type;
-	uint32_t           offset;
-	uint32_t           size;
-} NVRAMRegionInfo;
-
-class IONVRAMCHRPHandler : public IODTNVRAMFormatHandler, IOTypedOperatorsMixin<IONVRAMCHRPHandler>
-{
-private:
-	bool              _newData;
-	bool              _reload;
-	IONVRAMController *_nvramController;
-	IODTNVRAM         *_provider;
-	NVRAMVersion      _version;
-	uint32_t          _generation;
-
-	uint8_t           *_nvramImage;
-
-	uint32_t          _commonPartitionOffset;
-	uint32_t          _commonPartitionSize;
-
-	uint32_t          _systemPartitionOffset;
-	uint32_t          _systemPartitionSize;
-
-	OSSharedPtr<OSDictionary> _varDict;
-
-	uint32_t          _commonUsed;
-	uint32_t          _systemUsed;
-
-	IORWLock          *_variableLock;
-	IOLock            *_controllerLock;
-
-	uint32_t findCurrentBank(uint32_t *gen);
-	IOReturn unserializeImage(const uint8_t *image, IOByteCount length);
-	IOReturn serializeVariables(void);
-
-	IOReturn reloadInternal(void);
-	IOReturn setVariableInternal(const uuid_t varGuid, const char *variableName, OSObject *object);
-
-	static OSSharedPtr<OSData> unescapeBytesToData(const uint8_t *bytes, uint32_t length);
-	static OSSharedPtr<OSData> escapeDataToData(OSData * value);
-
-	static bool convertPropToObject(const uint8_t *propName, uint32_t propNameLength, const uint8_t *propData, uint32_t propDataLength,
-	    LIBKERN_RETURNS_RETAINED const OSSymbol **propSymbol, LIBKERN_RETURNS_RETAINED OSObject **propObject);
-	static bool convertPropToObject(const uint8_t *propName, uint32_t propNameLength, const uint8_t *propData, uint32_t propDataLength,
-	    OSSharedPtr<const OSSymbol>& propSymbol, OSSharedPtr<OSObject>& propObject);
-	static bool convertObjectToProp(uint8_t *buffer, uint32_t *length, const OSSymbol *propSymbol, OSObject *propObject);
-	static bool convertObjectToProp(uint8_t *buffer, uint32_t *length, const char *propSymbol, OSObject *propObject);
-
-public:
-	virtual
-	~IONVRAMCHRPHandler() APPLE_KEXT_OVERRIDE;
-	IONVRAMCHRPHandler();
-	static bool isValidImage(const uint8_t *image, IOByteCount length);
-	static  IONVRAMCHRPHandler *init(IODTNVRAM *provider, const uint8_t *image, IOByteCount length);
-
-	virtual IOReturn unserializeVariables(void) APPLE_KEXT_OVERRIDE;
-	virtual IOReturn setVariable(const uuid_t varGuid, const char *variableName, OSObject *object) APPLE_KEXT_OVERRIDE;
-	virtual bool     setController(IONVRAMController *controller) APPLE_KEXT_OVERRIDE;
-	virtual IOReturn sync(void) APPLE_KEXT_OVERRIDE;
-	virtual IOReturn flush(const uuid_t guid, IONVRAMOperation op) APPLE_KEXT_OVERRIDE;
-	virtual void     reload(void) APPLE_KEXT_OVERRIDE;
-	virtual uint32_t getGeneration(void) const APPLE_KEXT_OVERRIDE;
-	virtual uint32_t getVersion(void) const APPLE_KEXT_OVERRIDE;
-	virtual uint32_t getSystemUsed(void) const APPLE_KEXT_OVERRIDE;
-	virtual uint32_t getCommonUsed(void) const APPLE_KEXT_OVERRIDE;
-	virtual bool     getSystemPartitionActive(void) const APPLE_KEXT_OVERRIDE;
-	virtual IOReturn getVarDict(OSSharedPtr<OSDictionary> &varDictCopy) APPLE_KEXT_OVERRIDE;
-};
-
-static const char *
-get_bank_version_string(int version)
-{
-	switch (version) {
-	case kNVRAMVersion1:
-		return NVRAM_CHRP_APPLE_HEADER_NAME_V1;
-	case kNVRAMVersion2:
-		return NVRAM_CHRP_APPLE_HEADER_NAME_V2;
-	default:
-		return "Unknown";
-	}
-}
-
-static uint32_t
-adler32(const uint8_t *buffer, size_t length)
-{
-	uint32_t offset;
-	uint32_t adler, lowHalf, highHalf;
-
-	lowHalf = 1;
-	highHalf = 0;
-
-	for (offset = 0; offset < length; offset++) {
-		if ((offset % 5000) == 0) {
-			lowHalf  %= 65521L;
-			highHalf %= 65521L;
-		}
-
-		lowHalf += buffer[offset];
-		highHalf += lowHalf;
-	}
-
-	lowHalf  %= 65521L;
-	highHalf %= 65521L;
-
-	adler = (highHalf << 16) | lowHalf;
-
-	return adler;
-}
-
-static uint32_t
-nvram_get_adler(uint8_t *buf, int version)
-{
-	return ((struct apple_nvram_header *)buf)->adler;
-}
-
-static uint32_t
-adler32_with_version(const uint8_t *buf, size_t len, int version)
-{
-	size_t offset;
-
-	switch (version) {
-	case kNVRAMVersion1:
-	case kNVRAMVersion2:
-		offset = offsetof(struct apple_nvram_header, generation);
-		break;
-	default:
-		return 0;
-	}
-
-	return adler32(buf + offset, len - offset);
-}
-
-static uint8_t
-chrp_checksum(const struct chrp_nvram_header *hdr)
-{
-	uint16_t      sum;
-	const uint8_t *p;
-	const uint8_t *begin = (const uint8_t *)hdr + offsetof(struct chrp_nvram_header, len);
-	const uint8_t *end = (const uint8_t *)hdr + offsetof(struct chrp_nvram_header, data);
-
-	// checksum the header (minus the checksum itself)
-	sum = hdr->sig;
-	for (p = begin; p < end; p++) {
-		sum += *p;
-	}
-	while (sum > 0xff) {
-		sum = (sum & 0xff) + (sum >> 8);
-	}
-
-	return sum & 0xff;
-}
-
-static IOReturn
-nvram_validate_header_v1v2(const uint8_t * buf, uint32_t *generation, int version)
-{
-	IOReturn   result = kIOReturnError;
-	uint8_t    checksum;
-	const char *header_string = get_bank_version_string(version);
-	struct     chrp_nvram_header *chrp_header = (struct chrp_nvram_header *)buf;
-	uint32_t   local_gen = 0;
-
-	require(buf != nullptr, exit);
-
-	// <rdar://problem/73454488> Recovery Mode [Internal Build] 18D52-->18E141 [J307/308 Only]
-	// we can only compare the first "nvram" parts of the name as some devices have additional junk from
-	// a previous build likely copying past bounds of the "nvram" name in the const section
-	if (memcmp(header_string, chrp_header->name, strlen(header_string)) == 0) {
-		checksum = chrp_checksum(chrp_header);
-		if (checksum == chrp_header->cksum) {
-			result = kIOReturnSuccess;
-			local_gen = ((struct apple_nvram_header*)buf)->generation;
-
-			DEBUG_INFO("Found %s gen=%u\n", header_string, local_gen);
-
-			if (generation) {
-				*generation = local_gen;
-			}
-		} else {
-			DEBUG_INFO("invalid checksum in header, found %#02x, expected %#02x\n", chrp_header->cksum, checksum);
-		}
-	} else {
-		DEBUG_INFO("invalid bank for \"%s\", name = %#02x %#02x %#02x %#02x\n", header_string,
-		    chrp_header->name[0],
-		    chrp_header->name[1],
-		    chrp_header->name[2],
-		    chrp_header->name[3]);
-	}
-
-exit:
-	return result;
-}
-
-static void
-nvram_set_apple_header(uint8_t *buf, size_t len, uint32_t generation, int version)
-{
-	if (version == kNVRAMVersion1 ||
-	    version == kNVRAMVersion2) {
-		struct apple_nvram_header *apple_hdr = (struct apple_nvram_header *)buf;
-		generation += 1;
-		apple_hdr->generation = generation;
-		apple_hdr->adler = adler32_with_version(buf, len, version);
-	}
-}
-
-static NVRAMVersion
-validateNVRAMVersion(const uint8_t *buf, size_t len, uint32_t *generation)
-{
-	NVRAMVersion version = kNVRAMVersionUnknown;
-
-	if (nvram_validate_header_v1v2(buf, generation, kNVRAMVersion1) == kIOReturnSuccess) {
-		version = kNVRAMVersion1;
-		goto exit;
-	}
-
-	if (nvram_validate_header_v1v2(buf, generation, kNVRAMVersion2) == kIOReturnSuccess) {
-		version = kNVRAMVersion2;
-		goto exit;
-	}
-
-	DEBUG_INFO("Unable to determine version\n");
-
-exit:
-	DEBUG_INFO("version=%u\n", version);
-	return version;
-}
-
-IONVRAMCHRPHandler::~IONVRAMCHRPHandler()
-{
-}
-
-bool
-IONVRAMCHRPHandler::isValidImage(const uint8_t *image, IOByteCount length)
-{
-	return validateNVRAMVersion(image, length, nullptr) != kNVRAMVersionUnknown;
-}
-
-IONVRAMCHRPHandler*
-IONVRAMCHRPHandler::init(IODTNVRAM *provider, const uint8_t *image, IOByteCount length)
-{
-	bool propertiesOk;
-
-	IONVRAMCHRPHandler *handler = new IONVRAMCHRPHandler();
-
-	handler->_provider = provider;
-
-	handler->_variableLock = IORWLockAlloc();
-	require(handler->_variableLock != nullptr, exit);
-
-	handler->_controllerLock = IOLockAlloc();
-	require(handler->_controllerLock != nullptr, exit);
-
-	propertiesOk = handler->getNVRAMProperties();
-	require_action(propertiesOk, exit, DEBUG_ERROR("Unable to get NVRAM properties\n"));
-	require_action(length == handler->_bankSize, exit, DEBUG_ERROR("length 0x%llx != _bankSize 0x%x\n", length, handler->_bankSize));
-
-	if ((image != nullptr) && (length != 0)) {
-		if (handler->unserializeImage(image, length) != kIOReturnSuccess) {
-			DEBUG_ALWAYS("Unable to unserialize image, len=%#x\n", (unsigned int)length);
-		}
-	}
-
-	return handler;
-
-exit:
-	delete handler;
-
-	return nullptr;
-}
-
-IONVRAMCHRPHandler::IONVRAMCHRPHandler() :
-	_commonPartitionSize(0x800)
-{
-}
-
-IOReturn
-IONVRAMCHRPHandler::flush(const uuid_t guid, IONVRAMOperation op)
-{
-	IOReturn ret = kIOReturnSuccess;
-	bool     flushSystem;
-	bool     flushCommon;
-
-	flushSystem = getSystemPartitionActive() && (uuid_compare(guid, gAppleSystemVariableGuid) == 0);
-	flushCommon = uuid_compare(guid, gAppleNVRAMGuid) == 0;
-
-	DEBUG_INFO("flushSystem=%d, flushCommon=%d\n", flushSystem, flushCommon);
-
-	NVRAMWRITELOCK(_variableLock);
-	if (flushSystem || flushCommon) {
-		const OSSymbol                    *canonicalKey;
-		OSSharedPtr<OSDictionary>         dictCopy;
-		OSSharedPtr<OSCollectionIterator> iter;
-		uuid_string_t                     uuidString;
-
-		dictCopy = OSDictionary::withDictionary(_varDict.get());
-		iter = OSCollectionIterator::withCollection(dictCopy.get());
-		require_action(dictCopy && iter, exit, ret = kIOReturnNoMemory);
-
-		while ((canonicalKey = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
-			const char *varName;
-			uuid_t     varGuid;
-			bool       clear;
-
-			parseVariableName(canonicalKey->getCStringNoCopy(), &varGuid, &varName);
-
-			uuid_unparse(varGuid, uuidString);
-
-			clear = ((flushSystem && (uuid_compare(varGuid, gAppleSystemVariableGuid) == 0)) ||
-			    (flushCommon && (uuid_compare(varGuid, gAppleSystemVariableGuid) != 0))) &&
-			    verifyPermission(op, varGuid, varName, getSystemPartitionActive(), true);
-
-			if (clear) {
-				DEBUG_INFO("Clearing entry for %s:%s\n", uuidString, varName);
-				setVariableInternal(varGuid, varName, nullptr);
-			} else {
-				DEBUG_INFO("Keeping entry for %s:%s\n", uuidString, varName);
-			}
-		}
-	}
-
-exit:
-	NVRAMRWUNLOCK(_variableLock);
-	return ret;
-}
-
-IOReturn
-IONVRAMCHRPHandler::reloadInternal(void)
-{
-	uint32_t controllerBank;
-	uint32_t controllerGen;
-
-	NVRAMLOCKASSERTHELD(_controllerLock);
-
-	controllerBank = findCurrentBank(&controllerGen);
-
-	if (_currentBank != controllerBank) {
-		DEBUG_ERROR("_currentBank 0x%x != controllerBank 0x%x\n", _currentBank, controllerBank);
-	}
-
-	if (_generation != controllerGen) {
-		DEBUG_ERROR("_generation 0x%x != controllerGen 0x%x\n", _generation, controllerGen);
-	}
-
-	_currentBank = controllerBank;
-	_generation = controllerGen;
-
-	return kIOReturnSuccess;
-}
-
-void
-IONVRAMCHRPHandler::reload(void)
-{
-	_reload = true;
-
-	DEBUG_INFO("reload marked\n");
-}
-
-IOReturn
-IONVRAMCHRPHandler::unserializeImage(const uint8_t *image, IOByteCount length)
-{
-	IOReturn ret = kIOReturnInvalid;
-	uint32_t partitionOffset, partitionLength;
-	uint32_t currentLength, currentOffset = 0;
-	uint32_t hdr_adler, calculated_adler;
-
-	_commonPartitionOffset = 0xFFFFFFFF;
-	_systemPartitionOffset = 0xFFFFFFFF;
-
-	_version = validateNVRAMVersion(image, _bankSize, &_generation);
-	require(_version != kNVRAMVersionUnknown, exit);
-
-	if (_nvramImage) {
-		IOFreeData(_nvramImage, _bankSize);
-	}
-
-	_nvramImage = IONewData(uint8_t, length);
-	_bankSize = (uint32_t)length;
-	bcopy(image, _nvramImage, _bankSize);
-
-	hdr_adler = nvram_get_adler(_nvramImage, _version);
-	calculated_adler = adler32_with_version(_nvramImage, _bankSize, _version);
-
-	if (hdr_adler != calculated_adler) {
-		panic("header adler %#08X != calculated_adler %#08X\n", hdr_adler, calculated_adler);
-	}
-
-	// Look through the partitions to find the common and system partitions.
-	while (currentOffset < _bankSize) {
-		bool common_partition;
-		bool system_partition;
-		const chrp_nvram_header_t * header = (chrp_nvram_header_t *)(_nvramImage + currentOffset);
-		const uint8_t common_v1_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_COMMON_V1};
-		const uint8_t common_v2_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_COMMON_V2};
-		const uint8_t system_v1_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_SYSTEM_V1};
-		const uint8_t system_v2_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_SYSTEM_V2};
-
-		currentLength = header->len * NVRAM_CHRP_LENGTH_BLOCK_SIZE;
-
-		if (currentLength < sizeof(chrp_nvram_header_t)) {
-			break;
-		}
-
-		partitionOffset = currentOffset + sizeof(chrp_nvram_header_t);
-		partitionLength = currentLength - sizeof(chrp_nvram_header_t);
-
-		if ((partitionOffset + partitionLength) > _bankSize) {
-			break;
-		}
-
-		common_partition = (memcmp(header->name, common_v1_name, sizeof(header->name)) == 0) ||
-		    (memcmp(header->name, common_v2_name, sizeof(header->name)) == 0);
-		system_partition = (memcmp(header->name, system_v1_name, sizeof(header->name)) == 0) ||
-		    (memcmp(header->name, system_v2_name, sizeof(header->name)) == 0);
-
-		if (common_partition) {
-			_commonPartitionOffset = partitionOffset;
-			_commonPartitionSize = partitionLength;
-		} else if (system_partition) {
-			_systemPartitionOffset = partitionOffset;
-			_systemPartitionSize = partitionLength;
-		}
-		currentOffset += currentLength;
-	}
-
-	ret = kIOReturnSuccess;
-
-exit:
-	_varDict = OSDictionary::withCapacity(1);
-
-	DEBUG_ALWAYS("NVRAM : commonPartitionOffset - %#x, commonPartitionSize - %#x, systemPartitionOffset - %#x, systemPartitionSize - %#x\n",
-	    _commonPartitionOffset, _commonPartitionSize, _systemPartitionOffset, _systemPartitionSize);
-
-	return ret;
-}
-
-IOReturn
-IONVRAMCHRPHandler::unserializeVariables(void)
-{
-	IOReturn                    ret = kIOReturnSuccess;
-	uint32_t                    cnt, cntStart;
-	const uint8_t               *propName, *propData;
-	uint32_t                    propNameLength, propDataLength, regionIndex;
-	OSSharedPtr<const OSSymbol> propSymbol;
-	OSSharedPtr<OSObject>       propObject;
-	NVRAMRegionInfo             *currentRegion;
-	NVRAMRegionInfo             variableRegions[] = { { kIONVRAMPartitionCommon, _commonPartitionOffset, _commonPartitionSize},
-							  { kIONVRAMPartitionSystem, _systemPartitionOffset, _systemPartitionSize} };
-
-	DEBUG_INFO("...\n");
-
-	for (regionIndex = 0; regionIndex < ARRAY_SIZE(variableRegions); regionIndex++) {
-		currentRegion = &variableRegions[regionIndex];
-		const uint8_t * imageData = _nvramImage + currentRegion->offset;
-
-		if (currentRegion->size == 0) {
-			continue;
-		}
-
-		DEBUG_INFO("region = %d\n", currentRegion->type);
-		cnt = 0;
-		while (cnt < currentRegion->size) {
-			cntStart = cnt;
-			// Break if there is no name.
-			if (imageData[cnt] == '\0') {
-				break;
-			}
-
-			// Find the length of the name.
-			propName = imageData + cnt;
-			for (propNameLength = 0; (cnt + propNameLength) < currentRegion->size;
-			    propNameLength++) {
-				if (imageData[cnt + propNameLength] == '=') {
-					break;
-				}
-			}
-
-			// Break if the name goes past the end of the partition.
-			if ((cnt + propNameLength) >= currentRegion->size) {
-				break;
-			}
-			cnt += propNameLength + 1;
-
-			propData = imageData + cnt;
-			for (propDataLength = 0; (cnt + propDataLength) < currentRegion->size;
-			    propDataLength++) {
-				if (imageData[cnt + propDataLength] == '\0') {
-					break;
-				}
-			}
-
-			// Break if the data goes past the end of the partition.
-			if ((cnt + propDataLength) >= currentRegion->size) {
-				break;
-			}
-			cnt += propDataLength + 1;
-
-			if (convertPropToObject(propName, propNameLength, propData, propDataLength, propSymbol, propObject)) {
-				OSSharedPtr<const OSSymbol> canonicalKey;
-				const char                  *varName = propSymbol.get()->getCStringNoCopy();
-				uint32_t                    variableLength = cnt - cntStart;
-
-				DEBUG_INFO("adding %s, variableLength=%#x,dataLength=%#x\n", varName, variableLength, propDataLength);
-
-				if (currentRegion->type == kIONVRAMPartitionCommon) {
-					canonicalKey = keyWithGuidAndCString(gAppleNVRAMGuid, varName);
-				} else if (currentRegion->type == kIONVRAMPartitionSystem) {
-					canonicalKey = keyWithGuidAndCString(gAppleSystemVariableGuid, varName);
-				}
-
-				DEBUG_INFO("adding %s, dataLength=%u\n", varName, propDataLength);
-				_varDict->setObject(canonicalKey.get(), propObject.get());
-				if (_provider->_diags) {
-					_provider->_diags->logVariable(currentRegion->type,
-					    kIONVRAMOperationInit, varName,
-					    (void *)(uintptr_t)propDataLength,
-					    (void *)(uintptr_t)cntStart);
-				}
-
-				if (currentRegion->type == kIONVRAMPartitionSystem) {
-					_systemUsed += variableLength;
-				} else if (currentRegion->type == kIONVRAMPartitionCommon) {
-					_commonUsed += variableLength;
-				}
-			}
-		}
-	}
-
-	DEBUG_ALWAYS("_commonSize %#x, _systemSize %#x\n", _commonPartitionSize, _systemPartitionSize);
-
-	ret = handleEphDM();
-	verify_noerr_action(ret, panic("handleEphDM failed with ret=%08x", ret));
-
-	DEBUG_INFO("_commonUsed %#x, _systemUsed %#x\n", _commonUsed, _systemUsed);
-
-	if (_provider->_diags) {
-		OSSharedPtr<OSNumber> val = OSNumber::withNumber(getSystemUsed(), 32);
-		_provider->_diags->setProperty(kNVRAMSystemUsedKey, val.get());
-		DEBUG_INFO("%s=%u\n", kNVRAMSystemUsedKey, getSystemUsed());
-
-		val = OSNumber::withNumber(getCommonUsed(), 32);
-		_provider->_diags->setProperty(kNVRAMCommonUsedKey, val.get());
-		DEBUG_INFO("%s=%u\n", kNVRAMCommonUsedKey, getCommonUsed());
-	}
-
-	// Create the boot-args property if it is not in the dictionary.
-	if (_provider->getProperty(kIONVRAMBootArgsKey) == nullptr) {
-		propSymbol = OSSymbol::withCString(kIONVRAMBootArgsKey);
-		propObject = OSString::withCStringNoCopy("");
-
-		_provider->setProperty(propSymbol.get(), propObject.get());
-	}
-
-	_newData = true;
-
-	DEBUG_INFO("%s _varDict=%p\n", __FUNCTION__, _varDict ? _varDict.get() : nullptr);
-
-	return ret;
-}
-
-IOReturn
-IONVRAMCHRPHandler::serializeVariables(void)
-{
-	IOReturn                          ret;
-	bool                              ok = false;
-	uint32_t                          length, maxLength, regionIndex;
-	uint8_t                           *buffer, *tmpBuffer;
-	const OSSymbol                    *tmpSymbol;
-	OSObject                          *tmpObject;
-	OSSharedPtr<OSCollectionIterator> iter;
-	OSSharedPtr<OSNumber>             generation;
-	uint8_t                           *nvramImage;
-	NVRAMRegionInfo                   *currentRegion;
-	NVRAMRegionInfo                   variableRegions[] = { { kIONVRAMPartitionCommon, _commonPartitionOffset, _commonPartitionSize},
-								{ kIONVRAMPartitionSystem, _systemPartitionOffset, _systemPartitionSize} };
-	NVRAMLOCKASSERTHELD(_controllerLock);
-
-	require_action(_nvramController != nullptr, exit, (ret = kIOReturnNotReady, DEBUG_ERROR("No _nvramController\n")));
-	require_action(_newData == true, exit, (ret = kIOReturnSuccess, DEBUG_INFO("No _newData to sync\n")));
-	require_action(_bankSize != 0, exit, (ret = kIOReturnSuccess, DEBUG_INFO("No nvram size info\n")));
-	require_action(_nvramImage != nullptr, exit, (ret = kIOReturnSuccess, DEBUG_INFO("No nvram image info\n")));
-
-	nvramImage = IONewZeroData(uint8_t, _bankSize);
-	require_action(nvramImage != nullptr, exit, (ret = kIOReturnNoMemory, DEBUG_ERROR("Can't create NVRAM image copy\n")));
-
-	DEBUG_INFO("...\n");
-
-	bcopy(_nvramImage, nvramImage, _bankSize);
-
-	NVRAMREADLOCK(_variableLock);
-	for (regionIndex = 0; regionIndex < ARRAY_SIZE(variableRegions); regionIndex++) {
-		currentRegion = &variableRegions[regionIndex];
-
-		if (currentRegion->size == 0) {
-			continue;
-		}
-
-		DEBUG_INFO("region = %d\n", currentRegion->type);
-		buffer = tmpBuffer = nvramImage + currentRegion->offset;
-
-		bzero(buffer, currentRegion->size);
-
-		ok = true;
-		maxLength = currentRegion->size;
-
-		iter = OSCollectionIterator::withCollection(_varDict.get());
-		if (iter == nullptr) {
-			ok = false;
-		}
-
-		while (ok) {
-			uuid_t entryGuid;
-			const char *entryName;
-
-			tmpSymbol = OSDynamicCast(OSSymbol, iter->getNextObject());
-
-			if (tmpSymbol == nullptr) {
-				break;
-			}
-
-			DEBUG_INFO("_varDict entry %s\n", tmpSymbol->getCStringNoCopy());
-
-			parseVariableName(tmpSymbol, &entryGuid, &entryName);
-
-			if (getSystemPartitionActive()) {
-				if (currentRegion->type == kIONVRAMPartitionSystem) {
-					if (uuid_compare(entryGuid, gAppleSystemVariableGuid) != 0) {
-						DEBUG_INFO("Skipping %s because not system var\n", entryName);
-						continue;
-					}
-				} else if (currentRegion->type == kIONVRAMPartitionCommon) {
-					if (uuid_compare(entryGuid, gAppleSystemVariableGuid) == 0) {
-						DEBUG_INFO("Skipping %s for common region\n", entryName);
-						continue;
-					}
-				}
-			}
-
-			DEBUG_INFO("adding variable %s\n", entryName);
-
-			tmpObject = _varDict->getObject(tmpSymbol);
-
-			length = maxLength;
-			ok = convertObjectToProp(tmpBuffer, &length, entryName, tmpObject);
-			if (ok) {
-				tmpBuffer += length;
-				maxLength -= length;
-			}
-		}
-
-		if (!ok) {
-			ret = kIOReturnNoSpace;
-			IODeleteData(nvramImage, uint8_t, _bankSize);
-			break;
-		}
-
-		if (currentRegion->type == kIONVRAMPartitionSystem) {
-			_systemUsed = (uint32_t)(tmpBuffer - buffer);
-		} else if (currentRegion->type == kIONVRAMPartitionCommon) {
-			_commonUsed = (uint32_t)(tmpBuffer - buffer);
-		}
-	}
-	NVRAMRWUNLOCK(_variableLock);
-
-	DEBUG_INFO("ok=%d\n", ok);
-	require(ok, exit);
-
-	nvram_set_apple_header(nvramImage, _bankSize, ++_generation, _version);
-
-	_currentBank = (_currentBank + 1) % _bankCount;
-
-	ret = _nvramController->select(_currentBank);
-	DEBUG_IFERROR(ret, "_currentBank=%#x, select=%#x\n", _currentBank, ret);
-
-	ret = _nvramController->eraseBank();
-	DEBUG_IFERROR(ret, "eraseBank=%#x\n", ret);
-
-	ret = _nvramController->write(0, nvramImage, _bankSize);
-	DEBUG_IFERROR(ret, "write=%#x\n", ret);
-
-	_nvramController->sync();
-
-	if (_nvramImage) {
-		IODeleteData(_nvramImage, uint8_t, _bankSize);
-	}
-
-	_nvramImage = nvramImage;
-
-	_newData = false;
-
-exit:
-	return ret;
-}
-
-IOReturn
-IONVRAMCHRPHandler::setVariableInternal(const uuid_t varGuid, const char *variableName, OSObject *object)
-{
-	uint32_t                    newSize = 0;
-	uint32_t                    existingSize = 0;
-	bool                        remove = (object == nullptr);
-	OSObject                    *existing;
-	OSSharedPtr<const OSSymbol> canonicalKey;
-	bool                        systemVar;
-
-	// Anyone calling setVariableInternal should've already held the lock for write.
-	NVRAMRWLOCKASSERTEXCLUSIVE(_variableLock);
-
-	systemVar = (uuid_compare(varGuid, gAppleSystemVariableGuid) == 0);
-	canonicalKey = keyWithGuidAndCString(varGuid, variableName);
-
-	if ((existing = _varDict->getObject(canonicalKey.get()))) {
-		convertObjectToProp(nullptr, &existingSize, variableName, existing);
-	}
-
-	if (remove == false) {
-		convertObjectToProp(nullptr, &newSize, variableName, object);
-
-		DEBUG_INFO("setting %s, systemVar=%d, existingSize=%u, newSize=%u\n", canonicalKey.get()->getCStringNoCopy(), systemVar, existingSize, newSize);
-
-		if (systemVar) {
-			if ((newSize + _systemUsed - existingSize) > _systemPartitionSize) {
-				DEBUG_ERROR("No space left in system partition, need=%#x, _systemUsed=%#x, _systemPartitionSize=%#x\n",
-				    newSize, _systemUsed, _systemPartitionSize);
-				return kIOReturnNoSpace;
-			} else {
-				_systemUsed = _systemUsed + newSize - existingSize;
-			}
-		} else {
-			if ((newSize + _commonUsed - existingSize) > _commonPartitionSize) {
-				DEBUG_ERROR("No space left in common partition, need=%#x, _commonUsed=%#x, _commonPartitionSize=%#x\n",
-				    newSize, _commonUsed, _commonPartitionSize);
-				return kIOReturnNoSpace;
-			} else {
-				_commonUsed = _commonUsed + newSize - existingSize;
-			}
-		}
-
-		_varDict->setObject(canonicalKey.get(), object);
-
-		if (_provider->_diags) {
-			_provider->_diags->logVariable(getPartitionTypeForGUID(varGuid),
-			    kIONVRAMOperationWrite, variableName,
-			    (void *)(uintptr_t)newSize);
-		}
-	} else {
-		DEBUG_INFO("removing %s, systemVar=%d, existingSize=%u\n", canonicalKey.get()->getCStringNoCopy(), systemVar, existingSize);
-
-		if (systemVar) {
-			_systemUsed -= existingSize;
-		} else {
-			_commonUsed -= existingSize;
-		}
-
-		_varDict->removeObject(canonicalKey.get());
-
-		if (_provider->_diags) {
-			_provider->_diags->logVariable(getPartitionTypeForGUID(varGuid),
-			    kIONVRAMOperationDelete, variableName);
-		}
-	}
-
-	if (_provider->_diags) {
-		OSSharedPtr<OSNumber> val = OSNumber::withNumber(getSystemUsed(), 32);
-		_provider->_diags->setProperty(kNVRAMSystemUsedKey, val.get());
-		DEBUG_INFO("%s=%u\n", kNVRAMSystemUsedKey, getSystemUsed());
-
-		val = OSNumber::withNumber(getCommonUsed(), 32);
-		_provider->_diags->setProperty(kNVRAMCommonUsedKey, val.get());
-		DEBUG_INFO("%s=%u\n", kNVRAMCommonUsedKey, getCommonUsed());
-	}
-
-	_newData = true;
-
-	return kIOReturnSuccess;
-}
-
-IOReturn
-IONVRAMCHRPHandler::setVariable(const uuid_t varGuid, const char *variableName, OSObject *object)
-{
-	uuid_t destGuid;
-	IOReturn ret = kIOReturnError;
-
-	if (getSystemPartitionActive()) {
-		// System region case, if they're using the GUID directly or it's on the system allow list
-		// force it to use the System GUID
-		if ((uuid_compare(varGuid, gAppleSystemVariableGuid) == 0) || variableInAllowList(variableName)) {
-			uuid_copy(destGuid, gAppleSystemVariableGuid);
-		} else {
-			uuid_copy(destGuid, varGuid);
-		}
-	} else {
-		// No system region, store System GUID as Common GUID
-		if ((uuid_compare(varGuid, gAppleSystemVariableGuid) == 0) || variableInAllowList(variableName)) {
-			uuid_copy(destGuid, gAppleNVRAMGuid);
-		} else {
-			uuid_copy(destGuid, varGuid);
-		}
-	}
-	NVRAMWRITELOCK(_variableLock);
-	ret = setVariableInternal(destGuid, variableName, object);
-	NVRAMRWUNLOCK(_variableLock);
-
-	return ret;
-}
-
-uint32_t
-IONVRAMCHRPHandler::findCurrentBank(uint32_t *gen)
-{
-	struct apple_nvram_header storeHeader;
-	uint32_t                  maxGen = 0;
-	uint32_t                  currentBank = 0;
-
-	NVRAMLOCKASSERTHELD(_controllerLock);
-
-	for (unsigned int i = 0; i < _bankCount; i++) {
-		NVRAMVersion bankVer;
-		uint32_t bankGen = 0;
-
-		_nvramController->select(i);
-		_nvramController->read(0, (uint8_t *)&storeHeader, sizeof(storeHeader));
-		bankVer = validateNVRAMVersion((uint8_t *)&storeHeader, sizeof(storeHeader), &bankGen);
-
-		if ((bankVer != kNVRAMVersionUnknown) && (bankGen >= maxGen)) {
-			currentBank = i;
-			maxGen = bankGen;
-		}
-	}
-
-	DEBUG_ALWAYS("currentBank=%#x, gen=%#x\n", currentBank, maxGen);
-
-	*gen = maxGen;
-	return currentBank;
-}
-
-bool
-IONVRAMCHRPHandler::setController(IONVRAMController *controller)
-{
-	IOReturn ret;
-
-	NVRAMLOCK(_controllerLock);
-
-	if (_nvramController == NULL) {
-		_nvramController = controller;
-	}
-
-	DEBUG_INFO("Controller name: %s\n", _nvramController->getName());
-
-	ret = reloadInternal();
-	if (ret != kIOReturnSuccess) {
-		DEBUG_ERROR("reloadInternal failed, ret=0x%08x\n", ret);
-	}
-
-	NVRAMUNLOCK(_controllerLock);
-
-	return true;
-}
-
-IOReturn
-IONVRAMCHRPHandler::sync(void)
-{
-	IOReturn ret;
-
-	NVRAMLOCK(_controllerLock);
-
-	if (_reload) {
-		ret = reloadInternal();
-		require_noerr_action(ret, exit, DEBUG_ERROR("Reload failed, ret=%#x", ret));
-
-		_reload = false;
-	}
-
-	ret = serializeVariables();
-	require_noerr_action(ret, exit, DEBUG_ERROR("serializeVariables failed, ret=%#x", ret));
-
-exit:
-	NVRAMUNLOCK(_controllerLock);
-	return ret;
-}
-
-uint32_t
-IONVRAMCHRPHandler::getGeneration(void) const
-{
-	return _generation;
-}
-
-uint32_t
-IONVRAMCHRPHandler::getVersion(void) const
-{
-	return _version;
-}
-
-uint32_t
-IONVRAMCHRPHandler::getSystemUsed(void) const
-{
-	return _systemUsed;
-}
-
-uint32_t
-IONVRAMCHRPHandler::getCommonUsed(void) const
-{
-	return _commonUsed;
-}
-
-bool
-IONVRAMCHRPHandler::getSystemPartitionActive(void) const
-{
-	return _systemPartitionSize != 0;
-}
-
-OSSharedPtr<OSData>
-IONVRAMCHRPHandler::unescapeBytesToData(const uint8_t *bytes, uint32_t length)
-{
-	OSSharedPtr<OSData> data;
-	uint32_t            totalLength = 0;
-	uint32_t            offset, offset2;
-	uint8_t             byte;
-	bool                ok;
-
-	// Calculate the actual length of the data.
-	ok = true;
-	totalLength = 0;
-	for (offset = 0; offset < length;) {
-		byte = bytes[offset++];
-		if (byte == 0xFF) {
-			byte = bytes[offset++];
-			if (byte == 0x00) {
-				ok = false;
-				break;
-			}
-			offset2 = byte & 0x7F;
-		} else {
-			offset2 = 1;
-		}
-		totalLength += offset2;
-	}
-
-	if (ok) {
-		// Create an empty OSData of the correct size.
-		data = OSData::withCapacity(totalLength);
-		if (data != nullptr) {
-			for (offset = 0; offset < length;) {
-				byte = bytes[offset++];
-				if (byte == 0xFF) {
-					byte = bytes[offset++];
-					offset2 = byte & 0x7F;
-					byte = (byte & 0x80) ? 0xFF : 0x00;
-				} else {
-					offset2 = 1;
-				}
-				data->appendByte(byte, offset2);
-			}
-		}
-	}
-
-	return data;
-}
-
-OSSharedPtr<OSData>
-IONVRAMCHRPHandler::escapeDataToData(OSData * value)
-{
-	OSSharedPtr<OSData>         result;
-	OSBoundedPtr<const uint8_t> startPtr;
-	const uint8_t               *endPtr;
-	const uint8_t               *valueBytesPtr;
-	OSBoundedPtr<const uint8_t> wherePtr;
-	uint8_t                     byte;
-	bool                        ok = true;
-
-	valueBytesPtr = (const uint8_t *) value->getBytesNoCopy();
-	endPtr = valueBytesPtr + value->getLength();
-	wherePtr = OSBoundedPtr<const uint8_t>(valueBytesPtr, valueBytesPtr, endPtr);
-
-	result = OSData::withCapacity((unsigned int)(endPtr - wherePtr));
-	if (!result) {
-		return result;
-	}
-
-	while (wherePtr < endPtr) {
-		startPtr = wherePtr;
-		byte = *wherePtr++;
-		if ((byte == 0x00) || (byte == 0xFF)) {
-			for (;
-			    ((wherePtr - startPtr) < 0x7F) && (wherePtr < endPtr) && (byte == *wherePtr);
-			    wherePtr++) {
-			}
-			ok &= result->appendByte(0xff, 1);
-			byte = (byte & 0x80) | ((uint8_t)(wherePtr - startPtr));
-		}
-		ok &= result->appendByte(byte, 1);
-	}
-	ok &= result->appendByte(0, 1);
-
-	if (!ok) {
-		result.reset();
-	}
-
-	return result;
-}
-
-bool
-IONVRAMCHRPHandler::convertPropToObject(const uint8_t *propName, uint32_t propNameLength,
-    const uint8_t *propData, uint32_t propDataLength,
-    const OSSymbol **propSymbol,
-    OSObject **propObject)
-{
-	OSSharedPtr<const OSString> delimitedName;
-	OSSharedPtr<const OSSymbol> tmpSymbol;
-	OSSharedPtr<OSNumber>       tmpNumber;
-	OSSharedPtr<OSString>       tmpString;
-	OSSharedPtr<OSObject>       tmpObject = nullptr;
-
-	delimitedName = OSString::withCString((const char *)propName, propNameLength);
-	tmpSymbol = OSSymbol::withString(delimitedName.get());
-
-	if (tmpSymbol == nullptr) {
-		return false;
-	}
-
-	switch (getVariableType(tmpSymbol.get())) {
-	case kOFVariableTypeBoolean:
-		if (!strncmp("true", (const char *)propData, propDataLength)) {
-			tmpObject.reset(kOSBooleanTrue, OSRetain);
-		} else if (!strncmp("false", (const char *)propData, propDataLength)) {
-			tmpObject.reset(kOSBooleanFalse, OSRetain);
-		}
-		break;
-
-	case kOFVariableTypeNumber:
-		tmpNumber = OSNumber::withNumber(strtol((const char *)propData, nullptr, 0), 32);
-		if (tmpNumber != nullptr) {
-			tmpObject = tmpNumber;
-		}
-		break;
-
-	case kOFVariableTypeString:
-		tmpString = OSString::withCString((const char *)propData, propDataLength);
-		if (tmpString != nullptr) {
-			tmpObject = tmpString;
-		}
-		break;
-
-	case kOFVariableTypeData:
-		tmpObject = unescapeBytesToData(propData, propDataLength);
-		break;
-
-	default:
-		break;
-	}
-
-	if (tmpObject == nullptr) {
-		tmpSymbol.reset();
-		return false;
-	}
-
-	*propSymbol = tmpSymbol.detach();
-	*propObject = tmpObject.detach();
-
-	return true;
-}
-
-bool
-IONVRAMCHRPHandler::convertPropToObject(const uint8_t *propName, uint32_t propNameLength,
-    const uint8_t *propData, uint32_t propDataLength,
-    OSSharedPtr<const OSSymbol>& propSymbol,
-    OSSharedPtr<OSObject>& propObject)
-{
-	const OSSymbol* propSymbolRaw = nullptr;
-	OSObject* propObjectRaw       = nullptr;
-
-	bool ok = convertPropToObject(propName, propNameLength, propData, propDataLength,
-	    &propSymbolRaw, &propObjectRaw);
-
-	propSymbol.reset(propSymbolRaw, OSNoRetain);
-	propObject.reset(propObjectRaw, OSNoRetain);
-
-	return ok;
-}
-
-bool
-IONVRAMCHRPHandler::convertObjectToProp(uint8_t *buffer, uint32_t *length,
-    const OSSymbol *propSymbol, OSObject *propObject)
-{
-	return convertObjectToProp(buffer, length, propSymbol->getCStringNoCopy(), propObject);
-}
-
-bool
-IONVRAMCHRPHandler::convertObjectToProp(uint8_t *buffer, uint32_t *length,
-    const char *propName, OSObject *propObject)
-{
-	uint32_t             propNameLength, propDataLength, remaining, offset;
-	IONVRAMVariableType  propType;
-	OSBoolean            *tmpBoolean = nullptr;
-	OSNumber             *tmpNumber = nullptr;
-	OSString             *tmpString = nullptr;
-	OSSharedPtr<OSData>  tmpData;
-
-	propNameLength = (uint32_t)strlen(propName);
-	propType = getVariableType(propName);
-	offset = 0;
-	remaining = 0;
-
-	// Get the size of the data.
-	propDataLength = 0xFFFFFFFF;
-	switch (propType) {
-	case kOFVariableTypeBoolean:
-		tmpBoolean = OSDynamicCast(OSBoolean, propObject);
-		if (tmpBoolean != nullptr) {
-			propDataLength = 5;
-		}
-		break;
-
-	case kOFVariableTypeNumber:
-		tmpNumber = OSDynamicCast(OSNumber, propObject);
-		if (tmpNumber != nullptr) {
-			propDataLength = 10;
-		}
-		break;
-
-	case kOFVariableTypeString:
-		tmpString = OSDynamicCast(OSString, propObject);
-		if (tmpString != nullptr) {
-			propDataLength = tmpString->getLength();
-		}
-		break;
-
-	case kOFVariableTypeData:
-		tmpData.reset(OSDynamicCast(OSData, propObject), OSNoRetain);
-		if (tmpData != nullptr) {
-			tmpData = escapeDataToData(tmpData.detach());
-			// escapeDataToData() adds the NULL byte to the data
-			// subtract 1 here to keep offset consistent with the other cases
-			propDataLength = tmpData->getLength() - 1;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	// Make sure the propertySize is known and will fit.
-	if (propDataLength == 0xFFFFFFFF) {
-		return false;
-	}
-
-	if (buffer) {
-		// name + '=' + data + '\0'
-		if ((propNameLength + propDataLength + 2) > *length) {
-			return false;
-		}
-
-		remaining = *length;
-	}
-
-	*length = 0;
-
-	// Copy the property name equal sign.
-	offset += snprintf((char *)buffer, remaining, "%s=", propName);
-	if (buffer) {
-		if (remaining > offset) {
-			buffer += offset;
-			remaining = remaining - offset;
-		} else {
-			return false;
-		}
-	}
-
-	switch (propType) {
-	case kOFVariableTypeBoolean:
-		if (tmpBoolean->getValue()) {
-			offset += strlcpy((char *)buffer, "true", remaining);
-		} else {
-			offset += strlcpy((char *)buffer, "false", remaining);
-		}
-		break;
-
-	case kOFVariableTypeNumber:
-	{
-		uint32_t tmpValue = tmpNumber->unsigned32BitValue();
-		if (tmpValue == 0xFFFFFFFF) {
-			offset += strlcpy((char *)buffer, "-1", remaining);
-		} else if (tmpValue < 1000) {
-			offset += snprintf((char *)buffer, remaining, "%d", (uint32_t)tmpValue);
-		} else {
-			offset += snprintf((char *)buffer, remaining, "%#x", (uint32_t)tmpValue);
-		}
-	}
-	break;
-
-	case kOFVariableTypeString:
-		offset += strlcpy((char *)buffer, tmpString->getCStringNoCopy(), remaining);
-		break;
-
-	case kOFVariableTypeData:
-		if (buffer) {
-			bcopy(tmpData->getBytesNoCopy(), buffer, propDataLength);
-		}
-		tmpData.reset();
-		offset += propDataLength;
-		break;
-
-	default:
-		break;
-	}
-
-	*length = offset + 1;
-
-	return true;
-}
-
-IOReturn
-IONVRAMCHRPHandler::getVarDict(OSSharedPtr<OSDictionary> &varDictCopy)
-{
-	IOReturn ret = kIOReturnNotFound;
-
-	NVRAMREADLOCK(_variableLock);
-	if (_varDict) {
-		varDictCopy = OSDictionary::withDictionary(_varDict.get());
-		if (varDictCopy) {
-			if (OSDictionary::withCapacity(varDictCopy->getCount()) != nullptr) {
-				ret = kIOReturnSuccess;
-			}
-		}
-	}
-	NVRAMRWUNLOCK(_variableLock);
-
-	return ret;
-}