xref: /xnu-12377.41.6/iokit/Kernel/IONVRAMCHRPHandler.cpp (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1*bbb1b6f9SApple OSS Distributions /*
2*bbb1b6f9SApple OSS Distributions  * Copyright (c) 2021-2022 Apple Inc. All rights reserved.
3*bbb1b6f9SApple OSS Distributions  *
4*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*bbb1b6f9SApple OSS Distributions  *
6*bbb1b6f9SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*bbb1b6f9SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*bbb1b6f9SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*bbb1b6f9SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*bbb1b6f9SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*bbb1b6f9SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*bbb1b6f9SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*bbb1b6f9SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*bbb1b6f9SApple OSS Distributions  *
15*bbb1b6f9SApple OSS Distributions  * Please obtain a copy of the License at
16*bbb1b6f9SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*bbb1b6f9SApple OSS Distributions  *
18*bbb1b6f9SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*bbb1b6f9SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*bbb1b6f9SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*bbb1b6f9SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*bbb1b6f9SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*bbb1b6f9SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*bbb1b6f9SApple OSS Distributions  * limitations under the License.
25*bbb1b6f9SApple OSS Distributions  *
26*bbb1b6f9SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*bbb1b6f9SApple OSS Distributions  */
28*bbb1b6f9SApple OSS Distributions 
29*bbb1b6f9SApple OSS Distributions #include <libkern/c++/OSBoundedPtr.h>
30*bbb1b6f9SApple OSS Distributions 
31*bbb1b6f9SApple OSS Distributions #define NVRAM_CHRP_APPLE_HEADER_NAME_V1  "nvram"
32*bbb1b6f9SApple OSS Distributions #define NVRAM_CHRP_APPLE_HEADER_NAME_V2  "2nvram"
33*bbb1b6f9SApple OSS Distributions 
34*bbb1b6f9SApple OSS Distributions #define NVRAM_CHRP_PARTITION_NAME_COMMON_V1   "common"
35*bbb1b6f9SApple OSS Distributions #define NVRAM_CHRP_PARTITION_NAME_SYSTEM_V1   "system"
36*bbb1b6f9SApple OSS Distributions #define NVRAM_CHRP_PARTITION_NAME_COMMON_V2   "2common"
37*bbb1b6f9SApple OSS Distributions #define NVRAM_CHRP_PARTITION_NAME_SYSTEM_V2   "2system"
38*bbb1b6f9SApple OSS Distributions 
39*bbb1b6f9SApple OSS Distributions #define NVRAM_CHRP_LENGTH_BLOCK_SIZE 0x10 // CHRP length field is in 16 byte blocks
40*bbb1b6f9SApple OSS Distributions 
41*bbb1b6f9SApple OSS Distributions typedef struct chrp_nvram_header { //16 bytes
42*bbb1b6f9SApple OSS Distributions 	uint8_t  sig;
43*bbb1b6f9SApple OSS Distributions 	uint8_t  cksum; // checksum on sig, len, and name
44*bbb1b6f9SApple OSS Distributions 	uint16_t len;   // total length of the partition in 16 byte blocks starting with the signature
45*bbb1b6f9SApple OSS Distributions 	// and ending with the last byte of data area, ie len includes its own header size
46*bbb1b6f9SApple OSS Distributions 	char     name[12];
47*bbb1b6f9SApple OSS Distributions 	uint8_t  data[0];
48*bbb1b6f9SApple OSS Distributions } chrp_nvram_header_t;
49*bbb1b6f9SApple OSS Distributions 
50*bbb1b6f9SApple OSS Distributions typedef struct apple_nvram_header {  // 16 + 16 bytes
51*bbb1b6f9SApple OSS Distributions 	struct   chrp_nvram_header chrp;
52*bbb1b6f9SApple OSS Distributions 	uint32_t adler;
53*bbb1b6f9SApple OSS Distributions 	uint32_t generation;
54*bbb1b6f9SApple OSS Distributions 	uint8_t  padding[8];
55*bbb1b6f9SApple OSS Distributions } apple_nvram_header_t;
56*bbb1b6f9SApple OSS Distributions 
57*bbb1b6f9SApple OSS Distributions typedef struct {
58*bbb1b6f9SApple OSS Distributions 	NVRAMPartitionType type;
59*bbb1b6f9SApple OSS Distributions 	uint32_t           offset;
60*bbb1b6f9SApple OSS Distributions 	uint32_t           size;
61*bbb1b6f9SApple OSS Distributions } NVRAMRegionInfo;
62*bbb1b6f9SApple OSS Distributions 
63*bbb1b6f9SApple OSS Distributions class IONVRAMCHRPHandler : public IODTNVRAMFormatHandler, IOTypedOperatorsMixin<IONVRAMCHRPHandler>
64*bbb1b6f9SApple OSS Distributions {
65*bbb1b6f9SApple OSS Distributions private:
66*bbb1b6f9SApple OSS Distributions 	bool              _newData;
67*bbb1b6f9SApple OSS Distributions 	bool              _reload;
68*bbb1b6f9SApple OSS Distributions 	IONVRAMController *_nvramController;
69*bbb1b6f9SApple OSS Distributions 	IODTNVRAM         *_provider;
70*bbb1b6f9SApple OSS Distributions 	NVRAMVersion      _version;
71*bbb1b6f9SApple OSS Distributions 	uint32_t          _generation;
72*bbb1b6f9SApple OSS Distributions 
73*bbb1b6f9SApple OSS Distributions 	uint8_t           *_nvramImage;
74*bbb1b6f9SApple OSS Distributions 
75*bbb1b6f9SApple OSS Distributions 	uint32_t          _commonPartitionOffset;
76*bbb1b6f9SApple OSS Distributions 	uint32_t          _commonPartitionSize;
77*bbb1b6f9SApple OSS Distributions 
78*bbb1b6f9SApple OSS Distributions 	uint32_t          _systemPartitionOffset;
79*bbb1b6f9SApple OSS Distributions 	uint32_t          _systemPartitionSize;
80*bbb1b6f9SApple OSS Distributions 
81*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSDictionary> _varDict;
82*bbb1b6f9SApple OSS Distributions 
83*bbb1b6f9SApple OSS Distributions 	uint32_t          _commonUsed;
84*bbb1b6f9SApple OSS Distributions 	uint32_t          _systemUsed;
85*bbb1b6f9SApple OSS Distributions 
86*bbb1b6f9SApple OSS Distributions 	IORWLock          *_variableLock;
87*bbb1b6f9SApple OSS Distributions 	IOLock            *_controllerLock;
88*bbb1b6f9SApple OSS Distributions 
89*bbb1b6f9SApple OSS Distributions 	uint32_t findCurrentBank(uint32_t *gen);
90*bbb1b6f9SApple OSS Distributions 	IOReturn unserializeImage(const uint8_t *image, IOByteCount length);
91*bbb1b6f9SApple OSS Distributions 	IOReturn serializeVariables(void);
92*bbb1b6f9SApple OSS Distributions 
93*bbb1b6f9SApple OSS Distributions 	IOReturn reloadInternal(void);
94*bbb1b6f9SApple OSS Distributions 	IOReturn setVariableInternal(const uuid_t varGuid, const char *variableName, OSObject *object);
95*bbb1b6f9SApple OSS Distributions 
96*bbb1b6f9SApple OSS Distributions 	static OSSharedPtr<OSData> unescapeBytesToData(const uint8_t *bytes, uint32_t length);
97*bbb1b6f9SApple OSS Distributions 	static OSSharedPtr<OSData> escapeDataToData(OSData * value);
98*bbb1b6f9SApple OSS Distributions 
99*bbb1b6f9SApple OSS Distributions 	static bool convertPropToObject(const uint8_t *propName, uint32_t propNameLength, const uint8_t *propData, uint32_t propDataLength,
100*bbb1b6f9SApple OSS Distributions 	    LIBKERN_RETURNS_RETAINED const OSSymbol **propSymbol, LIBKERN_RETURNS_RETAINED OSObject **propObject);
101*bbb1b6f9SApple OSS Distributions 	static bool convertPropToObject(const uint8_t *propName, uint32_t propNameLength, const uint8_t *propData, uint32_t propDataLength,
102*bbb1b6f9SApple OSS Distributions 	    OSSharedPtr<const OSSymbol>& propSymbol, OSSharedPtr<OSObject>& propObject);
103*bbb1b6f9SApple OSS Distributions 	static bool convertObjectToProp(uint8_t *buffer, uint32_t *length, const OSSymbol *propSymbol, OSObject *propObject);
104*bbb1b6f9SApple OSS Distributions 	static bool convertObjectToProp(uint8_t *buffer, uint32_t *length, const char *propSymbol, OSObject *propObject);
105*bbb1b6f9SApple OSS Distributions 
106*bbb1b6f9SApple OSS Distributions public:
107*bbb1b6f9SApple OSS Distributions 	virtual
108*bbb1b6f9SApple OSS Distributions 	~IONVRAMCHRPHandler() APPLE_KEXT_OVERRIDE;
109*bbb1b6f9SApple OSS Distributions 	IONVRAMCHRPHandler();
110*bbb1b6f9SApple OSS Distributions 	static bool isValidImage(const uint8_t *image, IOByteCount length);
111*bbb1b6f9SApple OSS Distributions 	static  IONVRAMCHRPHandler *init(IODTNVRAM *provider, const uint8_t *image, IOByteCount length);
112*bbb1b6f9SApple OSS Distributions 
113*bbb1b6f9SApple OSS Distributions 	virtual IOReturn unserializeVariables(void) APPLE_KEXT_OVERRIDE;
114*bbb1b6f9SApple OSS Distributions 	virtual IOReturn setVariable(const uuid_t varGuid, const char *variableName, OSObject *object) APPLE_KEXT_OVERRIDE;
115*bbb1b6f9SApple OSS Distributions 	virtual bool     setController(IONVRAMController *controller) APPLE_KEXT_OVERRIDE;
116*bbb1b6f9SApple OSS Distributions 	virtual IOReturn sync(void) APPLE_KEXT_OVERRIDE;
117*bbb1b6f9SApple OSS Distributions 	virtual IOReturn flush(const uuid_t guid, IONVRAMOperation op) APPLE_KEXT_OVERRIDE;
118*bbb1b6f9SApple OSS Distributions 	virtual void     reload(void) APPLE_KEXT_OVERRIDE;
119*bbb1b6f9SApple OSS Distributions 	virtual uint32_t getGeneration(void) const APPLE_KEXT_OVERRIDE;
120*bbb1b6f9SApple OSS Distributions 	virtual uint32_t getVersion(void) const APPLE_KEXT_OVERRIDE;
121*bbb1b6f9SApple OSS Distributions 	virtual uint32_t getSystemUsed(void) const APPLE_KEXT_OVERRIDE;
122*bbb1b6f9SApple OSS Distributions 	virtual uint32_t getCommonUsed(void) const APPLE_KEXT_OVERRIDE;
123*bbb1b6f9SApple OSS Distributions 	virtual bool     getSystemPartitionActive(void) const APPLE_KEXT_OVERRIDE;
124*bbb1b6f9SApple OSS Distributions 	virtual IOReturn getVarDict(OSSharedPtr<OSDictionary> &varDictCopy) APPLE_KEXT_OVERRIDE;
125*bbb1b6f9SApple OSS Distributions };
126*bbb1b6f9SApple OSS Distributions 
127*bbb1b6f9SApple OSS Distributions static const char *
get_bank_version_string(int version)128*bbb1b6f9SApple OSS Distributions get_bank_version_string(int version)
129*bbb1b6f9SApple OSS Distributions {
130*bbb1b6f9SApple OSS Distributions 	switch (version) {
131*bbb1b6f9SApple OSS Distributions 	case kNVRAMVersion1:
132*bbb1b6f9SApple OSS Distributions 		return NVRAM_CHRP_APPLE_HEADER_NAME_V1;
133*bbb1b6f9SApple OSS Distributions 	case kNVRAMVersion2:
134*bbb1b6f9SApple OSS Distributions 		return NVRAM_CHRP_APPLE_HEADER_NAME_V2;
135*bbb1b6f9SApple OSS Distributions 	default:
136*bbb1b6f9SApple OSS Distributions 		return "Unknown";
137*bbb1b6f9SApple OSS Distributions 	}
138*bbb1b6f9SApple OSS Distributions }
139*bbb1b6f9SApple OSS Distributions 
140*bbb1b6f9SApple OSS Distributions static uint32_t
adler32(const uint8_t * buffer,size_t length)141*bbb1b6f9SApple OSS Distributions adler32(const uint8_t *buffer, size_t length)
142*bbb1b6f9SApple OSS Distributions {
143*bbb1b6f9SApple OSS Distributions 	uint32_t offset;
144*bbb1b6f9SApple OSS Distributions 	uint32_t adler, lowHalf, highHalf;
145*bbb1b6f9SApple OSS Distributions 
146*bbb1b6f9SApple OSS Distributions 	lowHalf = 1;
147*bbb1b6f9SApple OSS Distributions 	highHalf = 0;
148*bbb1b6f9SApple OSS Distributions 
149*bbb1b6f9SApple OSS Distributions 	for (offset = 0; offset < length; offset++) {
150*bbb1b6f9SApple OSS Distributions 		if ((offset % 5000) == 0) {
151*bbb1b6f9SApple OSS Distributions 			lowHalf  %= 65521L;
152*bbb1b6f9SApple OSS Distributions 			highHalf %= 65521L;
153*bbb1b6f9SApple OSS Distributions 		}
154*bbb1b6f9SApple OSS Distributions 
155*bbb1b6f9SApple OSS Distributions 		lowHalf += buffer[offset];
156*bbb1b6f9SApple OSS Distributions 		highHalf += lowHalf;
157*bbb1b6f9SApple OSS Distributions 	}
158*bbb1b6f9SApple OSS Distributions 
159*bbb1b6f9SApple OSS Distributions 	lowHalf  %= 65521L;
160*bbb1b6f9SApple OSS Distributions 	highHalf %= 65521L;
161*bbb1b6f9SApple OSS Distributions 
162*bbb1b6f9SApple OSS Distributions 	adler = (highHalf << 16) | lowHalf;
163*bbb1b6f9SApple OSS Distributions 
164*bbb1b6f9SApple OSS Distributions 	return adler;
165*bbb1b6f9SApple OSS Distributions }
166*bbb1b6f9SApple OSS Distributions 
167*bbb1b6f9SApple OSS Distributions static uint32_t
nvram_get_adler(uint8_t * buf,int version)168*bbb1b6f9SApple OSS Distributions nvram_get_adler(uint8_t *buf, int version)
169*bbb1b6f9SApple OSS Distributions {
170*bbb1b6f9SApple OSS Distributions 	return ((struct apple_nvram_header *)buf)->adler;
171*bbb1b6f9SApple OSS Distributions }
172*bbb1b6f9SApple OSS Distributions 
173*bbb1b6f9SApple OSS Distributions static uint32_t
adler32_with_version(const uint8_t * buf,size_t len,int version)174*bbb1b6f9SApple OSS Distributions adler32_with_version(const uint8_t *buf, size_t len, int version)
175*bbb1b6f9SApple OSS Distributions {
176*bbb1b6f9SApple OSS Distributions 	size_t offset;
177*bbb1b6f9SApple OSS Distributions 
178*bbb1b6f9SApple OSS Distributions 	switch (version) {
179*bbb1b6f9SApple OSS Distributions 	case kNVRAMVersion1:
180*bbb1b6f9SApple OSS Distributions 	case kNVRAMVersion2:
181*bbb1b6f9SApple OSS Distributions 		offset = offsetof(struct apple_nvram_header, generation);
182*bbb1b6f9SApple OSS Distributions 		break;
183*bbb1b6f9SApple OSS Distributions 	default:
184*bbb1b6f9SApple OSS Distributions 		return 0;
185*bbb1b6f9SApple OSS Distributions 	}
186*bbb1b6f9SApple OSS Distributions 
187*bbb1b6f9SApple OSS Distributions 	return adler32(buf + offset, len - offset);
188*bbb1b6f9SApple OSS Distributions }
189*bbb1b6f9SApple OSS Distributions 
190*bbb1b6f9SApple OSS Distributions static uint8_t
chrp_checksum(const struct chrp_nvram_header * hdr)191*bbb1b6f9SApple OSS Distributions chrp_checksum(const struct chrp_nvram_header *hdr)
192*bbb1b6f9SApple OSS Distributions {
193*bbb1b6f9SApple OSS Distributions 	uint16_t      sum;
194*bbb1b6f9SApple OSS Distributions 	const uint8_t *p;
195*bbb1b6f9SApple OSS Distributions 	const uint8_t *begin = (const uint8_t *)hdr + offsetof(struct chrp_nvram_header, len);
196*bbb1b6f9SApple OSS Distributions 	const uint8_t *end = (const uint8_t *)hdr + offsetof(struct chrp_nvram_header, data);
197*bbb1b6f9SApple OSS Distributions 
198*bbb1b6f9SApple OSS Distributions 	// checksum the header (minus the checksum itself)
199*bbb1b6f9SApple OSS Distributions 	sum = hdr->sig;
200*bbb1b6f9SApple OSS Distributions 	for (p = begin; p < end; p++) {
201*bbb1b6f9SApple OSS Distributions 		sum += *p;
202*bbb1b6f9SApple OSS Distributions 	}
203*bbb1b6f9SApple OSS Distributions 	while (sum > 0xff) {
204*bbb1b6f9SApple OSS Distributions 		sum = (sum & 0xff) + (sum >> 8);
205*bbb1b6f9SApple OSS Distributions 	}
206*bbb1b6f9SApple OSS Distributions 
207*bbb1b6f9SApple OSS Distributions 	return sum & 0xff;
208*bbb1b6f9SApple OSS Distributions }
209*bbb1b6f9SApple OSS Distributions 
210*bbb1b6f9SApple OSS Distributions static IOReturn
nvram_validate_header_v1v2(const uint8_t * buf,uint32_t * generation,int version)211*bbb1b6f9SApple OSS Distributions nvram_validate_header_v1v2(const uint8_t * buf, uint32_t *generation, int version)
212*bbb1b6f9SApple OSS Distributions {
213*bbb1b6f9SApple OSS Distributions 	IOReturn   result = kIOReturnError;
214*bbb1b6f9SApple OSS Distributions 	uint8_t    checksum;
215*bbb1b6f9SApple OSS Distributions 	const char *header_string = get_bank_version_string(version);
216*bbb1b6f9SApple OSS Distributions 	struct     chrp_nvram_header *chrp_header = (struct chrp_nvram_header *)buf;
217*bbb1b6f9SApple OSS Distributions 	uint32_t   local_gen = 0;
218*bbb1b6f9SApple OSS Distributions 
219*bbb1b6f9SApple OSS Distributions 	require(buf != nullptr, exit);
220*bbb1b6f9SApple OSS Distributions 
221*bbb1b6f9SApple OSS Distributions 	// <rdar://problem/73454488> Recovery Mode [Internal Build] 18D52-->18E141 [J307/308 Only]
222*bbb1b6f9SApple OSS Distributions 	// we can only compare the first "nvram" parts of the name as some devices have additional junk from
223*bbb1b6f9SApple OSS Distributions 	// a previous build likely copying past bounds of the "nvram" name in the const section
224*bbb1b6f9SApple OSS Distributions 	if (memcmp(header_string, chrp_header->name, strlen(header_string)) == 0) {
225*bbb1b6f9SApple OSS Distributions 		checksum = chrp_checksum(chrp_header);
226*bbb1b6f9SApple OSS Distributions 		if (checksum == chrp_header->cksum) {
227*bbb1b6f9SApple OSS Distributions 			result = kIOReturnSuccess;
228*bbb1b6f9SApple OSS Distributions 			local_gen = ((struct apple_nvram_header*)buf)->generation;
229*bbb1b6f9SApple OSS Distributions 
230*bbb1b6f9SApple OSS Distributions 			DEBUG_INFO("Found %s gen=%u\n", header_string, local_gen);
231*bbb1b6f9SApple OSS Distributions 
232*bbb1b6f9SApple OSS Distributions 			if (generation) {
233*bbb1b6f9SApple OSS Distributions 				*generation = local_gen;
234*bbb1b6f9SApple OSS Distributions 			}
235*bbb1b6f9SApple OSS Distributions 		} else {
236*bbb1b6f9SApple OSS Distributions 			DEBUG_INFO("invalid checksum in header, found %#02x, expected %#02x\n", chrp_header->cksum, checksum);
237*bbb1b6f9SApple OSS Distributions 		}
238*bbb1b6f9SApple OSS Distributions 	} else {
239*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("invalid bank for \"%s\", name = %#02x %#02x %#02x %#02x\n", header_string,
240*bbb1b6f9SApple OSS Distributions 		    chrp_header->name[0],
241*bbb1b6f9SApple OSS Distributions 		    chrp_header->name[1],
242*bbb1b6f9SApple OSS Distributions 		    chrp_header->name[2],
243*bbb1b6f9SApple OSS Distributions 		    chrp_header->name[3]);
244*bbb1b6f9SApple OSS Distributions 	}
245*bbb1b6f9SApple OSS Distributions 
246*bbb1b6f9SApple OSS Distributions exit:
247*bbb1b6f9SApple OSS Distributions 	return result;
248*bbb1b6f9SApple OSS Distributions }
249*bbb1b6f9SApple OSS Distributions 
250*bbb1b6f9SApple OSS Distributions static void
nvram_set_apple_header(uint8_t * buf,size_t len,uint32_t generation,int version)251*bbb1b6f9SApple OSS Distributions nvram_set_apple_header(uint8_t *buf, size_t len, uint32_t generation, int version)
252*bbb1b6f9SApple OSS Distributions {
253*bbb1b6f9SApple OSS Distributions 	if (version == kNVRAMVersion1 ||
254*bbb1b6f9SApple OSS Distributions 	    version == kNVRAMVersion2) {
255*bbb1b6f9SApple OSS Distributions 		struct apple_nvram_header *apple_hdr = (struct apple_nvram_header *)buf;
256*bbb1b6f9SApple OSS Distributions 		generation += 1;
257*bbb1b6f9SApple OSS Distributions 		apple_hdr->generation = generation;
258*bbb1b6f9SApple OSS Distributions 		apple_hdr->adler = adler32_with_version(buf, len, version);
259*bbb1b6f9SApple OSS Distributions 	}
260*bbb1b6f9SApple OSS Distributions }
261*bbb1b6f9SApple OSS Distributions 
262*bbb1b6f9SApple OSS Distributions static NVRAMVersion
validateNVRAMVersion(const uint8_t * buf,size_t len,uint32_t * generation)263*bbb1b6f9SApple OSS Distributions validateNVRAMVersion(const uint8_t *buf, size_t len, uint32_t *generation)
264*bbb1b6f9SApple OSS Distributions {
265*bbb1b6f9SApple OSS Distributions 	NVRAMVersion version = kNVRAMVersionUnknown;
266*bbb1b6f9SApple OSS Distributions 
267*bbb1b6f9SApple OSS Distributions 	if (nvram_validate_header_v1v2(buf, generation, kNVRAMVersion1) == kIOReturnSuccess) {
268*bbb1b6f9SApple OSS Distributions 		version = kNVRAMVersion1;
269*bbb1b6f9SApple OSS Distributions 		goto exit;
270*bbb1b6f9SApple OSS Distributions 	}
271*bbb1b6f9SApple OSS Distributions 
272*bbb1b6f9SApple OSS Distributions 	if (nvram_validate_header_v1v2(buf, generation, kNVRAMVersion2) == kIOReturnSuccess) {
273*bbb1b6f9SApple OSS Distributions 		version = kNVRAMVersion2;
274*bbb1b6f9SApple OSS Distributions 		goto exit;
275*bbb1b6f9SApple OSS Distributions 	}
276*bbb1b6f9SApple OSS Distributions 
277*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("Unable to determine version\n");
278*bbb1b6f9SApple OSS Distributions 
279*bbb1b6f9SApple OSS Distributions exit:
280*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("version=%u\n", version);
281*bbb1b6f9SApple OSS Distributions 	return version;
282*bbb1b6f9SApple OSS Distributions }
283*bbb1b6f9SApple OSS Distributions 
~IONVRAMCHRPHandler()284*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::~IONVRAMCHRPHandler()
285*bbb1b6f9SApple OSS Distributions {
286*bbb1b6f9SApple OSS Distributions }
287*bbb1b6f9SApple OSS Distributions 
288*bbb1b6f9SApple OSS Distributions bool
isValidImage(const uint8_t * image,IOByteCount length)289*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::isValidImage(const uint8_t *image, IOByteCount length)
290*bbb1b6f9SApple OSS Distributions {
291*bbb1b6f9SApple OSS Distributions 	return validateNVRAMVersion(image, length, nullptr) != kNVRAMVersionUnknown;
292*bbb1b6f9SApple OSS Distributions }
293*bbb1b6f9SApple OSS Distributions 
294*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler*
init(IODTNVRAM * provider,const uint8_t * image,IOByteCount length)295*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::init(IODTNVRAM *provider, const uint8_t *image, IOByteCount length)
296*bbb1b6f9SApple OSS Distributions {
297*bbb1b6f9SApple OSS Distributions 	bool propertiesOk;
298*bbb1b6f9SApple OSS Distributions 
299*bbb1b6f9SApple OSS Distributions 	IONVRAMCHRPHandler *handler = new IONVRAMCHRPHandler();
300*bbb1b6f9SApple OSS Distributions 
301*bbb1b6f9SApple OSS Distributions 	handler->_provider = provider;
302*bbb1b6f9SApple OSS Distributions 
303*bbb1b6f9SApple OSS Distributions 	handler->_variableLock = IORWLockAlloc();
304*bbb1b6f9SApple OSS Distributions 	require(handler->_variableLock != nullptr, exit);
305*bbb1b6f9SApple OSS Distributions 
306*bbb1b6f9SApple OSS Distributions 	handler->_controllerLock = IOLockAlloc();
307*bbb1b6f9SApple OSS Distributions 	require(handler->_controllerLock != nullptr, exit);
308*bbb1b6f9SApple OSS Distributions 
309*bbb1b6f9SApple OSS Distributions 	propertiesOk = handler->getNVRAMProperties();
310*bbb1b6f9SApple OSS Distributions 	require_action(propertiesOk, exit, DEBUG_ERROR("Unable to get NVRAM properties\n"));
311*bbb1b6f9SApple OSS Distributions 	require_action(length == handler->_bankSize, exit, DEBUG_ERROR("length 0x%llx != _bankSize 0x%x\n", length, handler->_bankSize));
312*bbb1b6f9SApple OSS Distributions 
313*bbb1b6f9SApple OSS Distributions 	if ((image != nullptr) && (length != 0)) {
314*bbb1b6f9SApple OSS Distributions 		if (handler->unserializeImage(image, length) != kIOReturnSuccess) {
315*bbb1b6f9SApple OSS Distributions 			DEBUG_ALWAYS("Unable to unserialize image, len=%#x\n", (unsigned int)length);
316*bbb1b6f9SApple OSS Distributions 		}
317*bbb1b6f9SApple OSS Distributions 	}
318*bbb1b6f9SApple OSS Distributions 
319*bbb1b6f9SApple OSS Distributions 	return handler;
320*bbb1b6f9SApple OSS Distributions 
321*bbb1b6f9SApple OSS Distributions exit:
322*bbb1b6f9SApple OSS Distributions 	delete handler;
323*bbb1b6f9SApple OSS Distributions 
324*bbb1b6f9SApple OSS Distributions 	return nullptr;
325*bbb1b6f9SApple OSS Distributions }
326*bbb1b6f9SApple OSS Distributions 
IONVRAMCHRPHandler()327*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::IONVRAMCHRPHandler() :
328*bbb1b6f9SApple OSS Distributions 	_commonPartitionSize(0x800)
329*bbb1b6f9SApple OSS Distributions {
330*bbb1b6f9SApple OSS Distributions }
331*bbb1b6f9SApple OSS Distributions 
332*bbb1b6f9SApple OSS Distributions IOReturn
flush(const uuid_t guid,IONVRAMOperation op)333*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::flush(const uuid_t guid, IONVRAMOperation op)
334*bbb1b6f9SApple OSS Distributions {
335*bbb1b6f9SApple OSS Distributions 	IOReturn ret = kIOReturnSuccess;
336*bbb1b6f9SApple OSS Distributions 	bool     flushSystem;
337*bbb1b6f9SApple OSS Distributions 	bool     flushCommon;
338*bbb1b6f9SApple OSS Distributions 
339*bbb1b6f9SApple OSS Distributions 	flushSystem = getSystemPartitionActive() && (uuid_compare(guid, gAppleSystemVariableGuid) == 0);
340*bbb1b6f9SApple OSS Distributions 	flushCommon = uuid_compare(guid, gAppleNVRAMGuid) == 0;
341*bbb1b6f9SApple OSS Distributions 
342*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("flushSystem=%d, flushCommon=%d\n", flushSystem, flushCommon);
343*bbb1b6f9SApple OSS Distributions 
344*bbb1b6f9SApple OSS Distributions 	NVRAMWRITELOCK(_variableLock);
345*bbb1b6f9SApple OSS Distributions 	if (flushSystem || flushCommon) {
346*bbb1b6f9SApple OSS Distributions 		const OSSymbol                    *canonicalKey;
347*bbb1b6f9SApple OSS Distributions 		OSSharedPtr<OSDictionary>         dictCopy;
348*bbb1b6f9SApple OSS Distributions 		OSSharedPtr<OSCollectionIterator> iter;
349*bbb1b6f9SApple OSS Distributions 		uuid_string_t                     uuidString;
350*bbb1b6f9SApple OSS Distributions 
351*bbb1b6f9SApple OSS Distributions 		dictCopy = OSDictionary::withDictionary(_varDict.get());
352*bbb1b6f9SApple OSS Distributions 		iter = OSCollectionIterator::withCollection(dictCopy.get());
353*bbb1b6f9SApple OSS Distributions 		require_action(dictCopy && iter, exit, ret = kIOReturnNoMemory);
354*bbb1b6f9SApple OSS Distributions 
355*bbb1b6f9SApple OSS Distributions 		while ((canonicalKey = OSDynamicCast(OSSymbol, iter->getNextObject()))) {
356*bbb1b6f9SApple OSS Distributions 			const char *varName;
357*bbb1b6f9SApple OSS Distributions 			uuid_t     varGuid;
358*bbb1b6f9SApple OSS Distributions 			bool       clear;
359*bbb1b6f9SApple OSS Distributions 
360*bbb1b6f9SApple OSS Distributions 			parseVariableName(canonicalKey->getCStringNoCopy(), &varGuid, &varName);
361*bbb1b6f9SApple OSS Distributions 
362*bbb1b6f9SApple OSS Distributions 			uuid_unparse(varGuid, uuidString);
363*bbb1b6f9SApple OSS Distributions 
364*bbb1b6f9SApple OSS Distributions 			clear = ((flushSystem && (uuid_compare(varGuid, gAppleSystemVariableGuid) == 0)) ||
365*bbb1b6f9SApple OSS Distributions 			    (flushCommon && (uuid_compare(varGuid, gAppleSystemVariableGuid) != 0))) &&
366*bbb1b6f9SApple OSS Distributions 			    verifyPermission(op, varGuid, varName, getSystemPartitionActive(), true);
367*bbb1b6f9SApple OSS Distributions 
368*bbb1b6f9SApple OSS Distributions 			if (clear) {
369*bbb1b6f9SApple OSS Distributions 				DEBUG_INFO("Clearing entry for %s:%s\n", uuidString, varName);
370*bbb1b6f9SApple OSS Distributions 				setVariableInternal(varGuid, varName, nullptr);
371*bbb1b6f9SApple OSS Distributions 			} else {
372*bbb1b6f9SApple OSS Distributions 				DEBUG_INFO("Keeping entry for %s:%s\n", uuidString, varName);
373*bbb1b6f9SApple OSS Distributions 			}
374*bbb1b6f9SApple OSS Distributions 		}
375*bbb1b6f9SApple OSS Distributions 	}
376*bbb1b6f9SApple OSS Distributions 
377*bbb1b6f9SApple OSS Distributions exit:
378*bbb1b6f9SApple OSS Distributions 	NVRAMRWUNLOCK(_variableLock);
379*bbb1b6f9SApple OSS Distributions 	return ret;
380*bbb1b6f9SApple OSS Distributions }
381*bbb1b6f9SApple OSS Distributions 
382*bbb1b6f9SApple OSS Distributions IOReturn
reloadInternal(void)383*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::reloadInternal(void)
384*bbb1b6f9SApple OSS Distributions {
385*bbb1b6f9SApple OSS Distributions 	uint32_t controllerBank;
386*bbb1b6f9SApple OSS Distributions 	uint32_t controllerGen;
387*bbb1b6f9SApple OSS Distributions 
388*bbb1b6f9SApple OSS Distributions 	NVRAMLOCKASSERTHELD(_controllerLock);
389*bbb1b6f9SApple OSS Distributions 
390*bbb1b6f9SApple OSS Distributions 	controllerBank = findCurrentBank(&controllerGen);
391*bbb1b6f9SApple OSS Distributions 
392*bbb1b6f9SApple OSS Distributions 	if (_currentBank != controllerBank) {
393*bbb1b6f9SApple OSS Distributions 		DEBUG_ERROR("_currentBank 0x%x != controllerBank 0x%x\n", _currentBank, controllerBank);
394*bbb1b6f9SApple OSS Distributions 	}
395*bbb1b6f9SApple OSS Distributions 
396*bbb1b6f9SApple OSS Distributions 	if (_generation != controllerGen) {
397*bbb1b6f9SApple OSS Distributions 		DEBUG_ERROR("_generation 0x%x != controllerGen 0x%x\n", _generation, controllerGen);
398*bbb1b6f9SApple OSS Distributions 	}
399*bbb1b6f9SApple OSS Distributions 
400*bbb1b6f9SApple OSS Distributions 	_currentBank = controllerBank;
401*bbb1b6f9SApple OSS Distributions 	_generation = controllerGen;
402*bbb1b6f9SApple OSS Distributions 
403*bbb1b6f9SApple OSS Distributions 	return kIOReturnSuccess;
404*bbb1b6f9SApple OSS Distributions }
405*bbb1b6f9SApple OSS Distributions 
406*bbb1b6f9SApple OSS Distributions void
reload(void)407*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::reload(void)
408*bbb1b6f9SApple OSS Distributions {
409*bbb1b6f9SApple OSS Distributions 	_reload = true;
410*bbb1b6f9SApple OSS Distributions 
411*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("reload marked\n");
412*bbb1b6f9SApple OSS Distributions }
413*bbb1b6f9SApple OSS Distributions 
414*bbb1b6f9SApple OSS Distributions IOReturn
unserializeImage(const uint8_t * image,IOByteCount length)415*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::unserializeImage(const uint8_t *image, IOByteCount length)
416*bbb1b6f9SApple OSS Distributions {
417*bbb1b6f9SApple OSS Distributions 	IOReturn ret = kIOReturnInvalid;
418*bbb1b6f9SApple OSS Distributions 	uint32_t partitionOffset, partitionLength;
419*bbb1b6f9SApple OSS Distributions 	uint32_t currentLength, currentOffset = 0;
420*bbb1b6f9SApple OSS Distributions 	uint32_t hdr_adler, calculated_adler;
421*bbb1b6f9SApple OSS Distributions 
422*bbb1b6f9SApple OSS Distributions 	_commonPartitionOffset = 0xFFFFFFFF;
423*bbb1b6f9SApple OSS Distributions 	_systemPartitionOffset = 0xFFFFFFFF;
424*bbb1b6f9SApple OSS Distributions 
425*bbb1b6f9SApple OSS Distributions 	_version = validateNVRAMVersion(image, _bankSize, &_generation);
426*bbb1b6f9SApple OSS Distributions 	require(_version != kNVRAMVersionUnknown, exit);
427*bbb1b6f9SApple OSS Distributions 
428*bbb1b6f9SApple OSS Distributions 	if (_nvramImage) {
429*bbb1b6f9SApple OSS Distributions 		IOFreeData(_nvramImage, _bankSize);
430*bbb1b6f9SApple OSS Distributions 	}
431*bbb1b6f9SApple OSS Distributions 
432*bbb1b6f9SApple OSS Distributions 	_nvramImage = IONewData(uint8_t, length);
433*bbb1b6f9SApple OSS Distributions 	_bankSize = (uint32_t)length;
434*bbb1b6f9SApple OSS Distributions 	bcopy(image, _nvramImage, _bankSize);
435*bbb1b6f9SApple OSS Distributions 
436*bbb1b6f9SApple OSS Distributions 	hdr_adler = nvram_get_adler(_nvramImage, _version);
437*bbb1b6f9SApple OSS Distributions 	calculated_adler = adler32_with_version(_nvramImage, _bankSize, _version);
438*bbb1b6f9SApple OSS Distributions 
439*bbb1b6f9SApple OSS Distributions 	if (hdr_adler != calculated_adler) {
440*bbb1b6f9SApple OSS Distributions 		panic("header adler %#08X != calculated_adler %#08X\n", hdr_adler, calculated_adler);
441*bbb1b6f9SApple OSS Distributions 	}
442*bbb1b6f9SApple OSS Distributions 
443*bbb1b6f9SApple OSS Distributions 	// Look through the partitions to find the common and system partitions.
444*bbb1b6f9SApple OSS Distributions 	while (currentOffset < _bankSize) {
445*bbb1b6f9SApple OSS Distributions 		bool common_partition;
446*bbb1b6f9SApple OSS Distributions 		bool system_partition;
447*bbb1b6f9SApple OSS Distributions 		const chrp_nvram_header_t * header = (chrp_nvram_header_t *)(_nvramImage + currentOffset);
448*bbb1b6f9SApple OSS Distributions 		const uint8_t common_v1_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_COMMON_V1};
449*bbb1b6f9SApple OSS Distributions 		const uint8_t common_v2_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_COMMON_V2};
450*bbb1b6f9SApple OSS Distributions 		const uint8_t system_v1_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_SYSTEM_V1};
451*bbb1b6f9SApple OSS Distributions 		const uint8_t system_v2_name[sizeof(header->name)] = {NVRAM_CHRP_PARTITION_NAME_SYSTEM_V2};
452*bbb1b6f9SApple OSS Distributions 
453*bbb1b6f9SApple OSS Distributions 		currentLength = header->len * NVRAM_CHRP_LENGTH_BLOCK_SIZE;
454*bbb1b6f9SApple OSS Distributions 
455*bbb1b6f9SApple OSS Distributions 		if (currentLength < sizeof(chrp_nvram_header_t)) {
456*bbb1b6f9SApple OSS Distributions 			break;
457*bbb1b6f9SApple OSS Distributions 		}
458*bbb1b6f9SApple OSS Distributions 
459*bbb1b6f9SApple OSS Distributions 		partitionOffset = currentOffset + sizeof(chrp_nvram_header_t);
460*bbb1b6f9SApple OSS Distributions 		partitionLength = currentLength - sizeof(chrp_nvram_header_t);
461*bbb1b6f9SApple OSS Distributions 
462*bbb1b6f9SApple OSS Distributions 		if ((partitionOffset + partitionLength) > _bankSize) {
463*bbb1b6f9SApple OSS Distributions 			break;
464*bbb1b6f9SApple OSS Distributions 		}
465*bbb1b6f9SApple OSS Distributions 
466*bbb1b6f9SApple OSS Distributions 		common_partition = (memcmp(header->name, common_v1_name, sizeof(header->name)) == 0) ||
467*bbb1b6f9SApple OSS Distributions 		    (memcmp(header->name, common_v2_name, sizeof(header->name)) == 0);
468*bbb1b6f9SApple OSS Distributions 		system_partition = (memcmp(header->name, system_v1_name, sizeof(header->name)) == 0) ||
469*bbb1b6f9SApple OSS Distributions 		    (memcmp(header->name, system_v2_name, sizeof(header->name)) == 0);
470*bbb1b6f9SApple OSS Distributions 
471*bbb1b6f9SApple OSS Distributions 		if (common_partition) {
472*bbb1b6f9SApple OSS Distributions 			_commonPartitionOffset = partitionOffset;
473*bbb1b6f9SApple OSS Distributions 			_commonPartitionSize = partitionLength;
474*bbb1b6f9SApple OSS Distributions 		} else if (system_partition) {
475*bbb1b6f9SApple OSS Distributions 			_systemPartitionOffset = partitionOffset;
476*bbb1b6f9SApple OSS Distributions 			_systemPartitionSize = partitionLength;
477*bbb1b6f9SApple OSS Distributions 		}
478*bbb1b6f9SApple OSS Distributions 		currentOffset += currentLength;
479*bbb1b6f9SApple OSS Distributions 	}
480*bbb1b6f9SApple OSS Distributions 
481*bbb1b6f9SApple OSS Distributions 	ret = kIOReturnSuccess;
482*bbb1b6f9SApple OSS Distributions 
483*bbb1b6f9SApple OSS Distributions exit:
484*bbb1b6f9SApple OSS Distributions 	_varDict = OSDictionary::withCapacity(1);
485*bbb1b6f9SApple OSS Distributions 
486*bbb1b6f9SApple OSS Distributions 	DEBUG_ALWAYS("NVRAM : commonPartitionOffset - %#x, commonPartitionSize - %#x, systemPartitionOffset - %#x, systemPartitionSize - %#x\n",
487*bbb1b6f9SApple OSS Distributions 	    _commonPartitionOffset, _commonPartitionSize, _systemPartitionOffset, _systemPartitionSize);
488*bbb1b6f9SApple OSS Distributions 
489*bbb1b6f9SApple OSS Distributions 	return ret;
490*bbb1b6f9SApple OSS Distributions }
491*bbb1b6f9SApple OSS Distributions 
492*bbb1b6f9SApple OSS Distributions IOReturn
unserializeVariables(void)493*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::unserializeVariables(void)
494*bbb1b6f9SApple OSS Distributions {
495*bbb1b6f9SApple OSS Distributions 	IOReturn                    ret = kIOReturnSuccess;
496*bbb1b6f9SApple OSS Distributions 	uint32_t                    cnt, cntStart;
497*bbb1b6f9SApple OSS Distributions 	const uint8_t               *propName, *propData;
498*bbb1b6f9SApple OSS Distributions 	uint32_t                    propNameLength, propDataLength, regionIndex;
499*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<const OSSymbol> propSymbol;
500*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSObject>       propObject;
501*bbb1b6f9SApple OSS Distributions 	NVRAMRegionInfo             *currentRegion;
502*bbb1b6f9SApple OSS Distributions 	NVRAMRegionInfo             variableRegions[] = { { kIONVRAMPartitionCommon, _commonPartitionOffset, _commonPartitionSize},
503*bbb1b6f9SApple OSS Distributions 							  { kIONVRAMPartitionSystem, _systemPartitionOffset, _systemPartitionSize} };
504*bbb1b6f9SApple OSS Distributions 
505*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("...\n");
506*bbb1b6f9SApple OSS Distributions 
507*bbb1b6f9SApple OSS Distributions 	for (regionIndex = 0; regionIndex < ARRAY_SIZE(variableRegions); regionIndex++) {
508*bbb1b6f9SApple OSS Distributions 		currentRegion = &variableRegions[regionIndex];
509*bbb1b6f9SApple OSS Distributions 		const uint8_t * imageData = _nvramImage + currentRegion->offset;
510*bbb1b6f9SApple OSS Distributions 
511*bbb1b6f9SApple OSS Distributions 		if (currentRegion->size == 0) {
512*bbb1b6f9SApple OSS Distributions 			continue;
513*bbb1b6f9SApple OSS Distributions 		}
514*bbb1b6f9SApple OSS Distributions 
515*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("region = %d\n", currentRegion->type);
516*bbb1b6f9SApple OSS Distributions 		cnt = 0;
517*bbb1b6f9SApple OSS Distributions 		while (cnt < currentRegion->size) {
518*bbb1b6f9SApple OSS Distributions 			cntStart = cnt;
519*bbb1b6f9SApple OSS Distributions 			// Break if there is no name.
520*bbb1b6f9SApple OSS Distributions 			if (imageData[cnt] == '\0') {
521*bbb1b6f9SApple OSS Distributions 				break;
522*bbb1b6f9SApple OSS Distributions 			}
523*bbb1b6f9SApple OSS Distributions 
524*bbb1b6f9SApple OSS Distributions 			// Find the length of the name.
525*bbb1b6f9SApple OSS Distributions 			propName = imageData + cnt;
526*bbb1b6f9SApple OSS Distributions 			for (propNameLength = 0; (cnt + propNameLength) < currentRegion->size;
527*bbb1b6f9SApple OSS Distributions 			    propNameLength++) {
528*bbb1b6f9SApple OSS Distributions 				if (imageData[cnt + propNameLength] == '=') {
529*bbb1b6f9SApple OSS Distributions 					break;
530*bbb1b6f9SApple OSS Distributions 				}
531*bbb1b6f9SApple OSS Distributions 			}
532*bbb1b6f9SApple OSS Distributions 
533*bbb1b6f9SApple OSS Distributions 			// Break if the name goes past the end of the partition.
534*bbb1b6f9SApple OSS Distributions 			if ((cnt + propNameLength) >= currentRegion->size) {
535*bbb1b6f9SApple OSS Distributions 				break;
536*bbb1b6f9SApple OSS Distributions 			}
537*bbb1b6f9SApple OSS Distributions 			cnt += propNameLength + 1;
538*bbb1b6f9SApple OSS Distributions 
539*bbb1b6f9SApple OSS Distributions 			propData = imageData + cnt;
540*bbb1b6f9SApple OSS Distributions 			for (propDataLength = 0; (cnt + propDataLength) < currentRegion->size;
541*bbb1b6f9SApple OSS Distributions 			    propDataLength++) {
542*bbb1b6f9SApple OSS Distributions 				if (imageData[cnt + propDataLength] == '\0') {
543*bbb1b6f9SApple OSS Distributions 					break;
544*bbb1b6f9SApple OSS Distributions 				}
545*bbb1b6f9SApple OSS Distributions 			}
546*bbb1b6f9SApple OSS Distributions 
547*bbb1b6f9SApple OSS Distributions 			// Break if the data goes past the end of the partition.
548*bbb1b6f9SApple OSS Distributions 			if ((cnt + propDataLength) >= currentRegion->size) {
549*bbb1b6f9SApple OSS Distributions 				break;
550*bbb1b6f9SApple OSS Distributions 			}
551*bbb1b6f9SApple OSS Distributions 			cnt += propDataLength + 1;
552*bbb1b6f9SApple OSS Distributions 
553*bbb1b6f9SApple OSS Distributions 			if (convertPropToObject(propName, propNameLength, propData, propDataLength, propSymbol, propObject)) {
554*bbb1b6f9SApple OSS Distributions 				OSSharedPtr<const OSSymbol> canonicalKey;
555*bbb1b6f9SApple OSS Distributions 				const char                  *varName = propSymbol.get()->getCStringNoCopy();
556*bbb1b6f9SApple OSS Distributions 				uint32_t                    variableLength = cnt - cntStart;
557*bbb1b6f9SApple OSS Distributions 
558*bbb1b6f9SApple OSS Distributions 				DEBUG_INFO("adding %s, variableLength=%#x,dataLength=%#x\n", varName, variableLength, propDataLength);
559*bbb1b6f9SApple OSS Distributions 
560*bbb1b6f9SApple OSS Distributions 				if (currentRegion->type == kIONVRAMPartitionCommon) {
561*bbb1b6f9SApple OSS Distributions 					canonicalKey = keyWithGuidAndCString(gAppleNVRAMGuid, varName);
562*bbb1b6f9SApple OSS Distributions 				} else if (currentRegion->type == kIONVRAMPartitionSystem) {
563*bbb1b6f9SApple OSS Distributions 					canonicalKey = keyWithGuidAndCString(gAppleSystemVariableGuid, varName);
564*bbb1b6f9SApple OSS Distributions 				}
565*bbb1b6f9SApple OSS Distributions 
566*bbb1b6f9SApple OSS Distributions 				DEBUG_INFO("adding %s, dataLength=%u\n", varName, propDataLength);
567*bbb1b6f9SApple OSS Distributions 				_varDict->setObject(canonicalKey.get(), propObject.get());
568*bbb1b6f9SApple OSS Distributions 				if (_provider->_diags) {
569*bbb1b6f9SApple OSS Distributions 					_provider->_diags->logVariable(currentRegion->type,
570*bbb1b6f9SApple OSS Distributions 					    kIONVRAMOperationInit, varName,
571*bbb1b6f9SApple OSS Distributions 					    (void *)(uintptr_t)(cnt - cntStart));
572*bbb1b6f9SApple OSS Distributions 				}
573*bbb1b6f9SApple OSS Distributions 
574*bbb1b6f9SApple OSS Distributions 				if (currentRegion->type == kIONVRAMPartitionSystem) {
575*bbb1b6f9SApple OSS Distributions 					_systemUsed += variableLength;
576*bbb1b6f9SApple OSS Distributions 				} else if (currentRegion->type == kIONVRAMPartitionCommon) {
577*bbb1b6f9SApple OSS Distributions 					_commonUsed += variableLength;
578*bbb1b6f9SApple OSS Distributions 				}
579*bbb1b6f9SApple OSS Distributions 			}
580*bbb1b6f9SApple OSS Distributions 		}
581*bbb1b6f9SApple OSS Distributions 	}
582*bbb1b6f9SApple OSS Distributions 
583*bbb1b6f9SApple OSS Distributions 	DEBUG_ALWAYS("_commonSize %#x, _systemSize %#x\n", _commonPartitionSize, _systemPartitionSize);
584*bbb1b6f9SApple OSS Distributions 
585*bbb1b6f9SApple OSS Distributions 	ret = handleEphDM();
586*bbb1b6f9SApple OSS Distributions 	verify_noerr_action(ret, panic("handleEphDM failed with ret=%08x", ret));
587*bbb1b6f9SApple OSS Distributions 
588*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("_commonUsed %#x, _systemUsed %#x\n", _commonUsed, _systemUsed);
589*bbb1b6f9SApple OSS Distributions 
590*bbb1b6f9SApple OSS Distributions 	if (_provider->_diags) {
591*bbb1b6f9SApple OSS Distributions 		OSSharedPtr<OSNumber> val = OSNumber::withNumber(getSystemUsed(), 32);
592*bbb1b6f9SApple OSS Distributions 		_provider->_diags->setProperty(kNVRAMSystemUsedKey, val.get());
593*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("%s=%u\n", kNVRAMSystemUsedKey, getSystemUsed());
594*bbb1b6f9SApple OSS Distributions 
595*bbb1b6f9SApple OSS Distributions 		val = OSNumber::withNumber(getCommonUsed(), 32);
596*bbb1b6f9SApple OSS Distributions 		_provider->_diags->setProperty(kNVRAMCommonUsedKey, val.get());
597*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("%s=%u\n", kNVRAMCommonUsedKey, getCommonUsed());
598*bbb1b6f9SApple OSS Distributions 	}
599*bbb1b6f9SApple OSS Distributions 
600*bbb1b6f9SApple OSS Distributions 	// Create the boot-args property if it is not in the dictionary.
601*bbb1b6f9SApple OSS Distributions 	if (_provider->getProperty(kIONVRAMBootArgsKey) == nullptr) {
602*bbb1b6f9SApple OSS Distributions 		propSymbol = OSSymbol::withCString(kIONVRAMBootArgsKey);
603*bbb1b6f9SApple OSS Distributions 		propObject = OSString::withCStringNoCopy("");
604*bbb1b6f9SApple OSS Distributions 
605*bbb1b6f9SApple OSS Distributions 		_provider->setProperty(propSymbol.get(), propObject.get());
606*bbb1b6f9SApple OSS Distributions 	}
607*bbb1b6f9SApple OSS Distributions 
608*bbb1b6f9SApple OSS Distributions 	_newData = true;
609*bbb1b6f9SApple OSS Distributions 
610*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("%s _varDict=%p\n", __FUNCTION__, _varDict ? _varDict.get() : nullptr);
611*bbb1b6f9SApple OSS Distributions 
612*bbb1b6f9SApple OSS Distributions 	return ret;
613*bbb1b6f9SApple OSS Distributions }
614*bbb1b6f9SApple OSS Distributions 
615*bbb1b6f9SApple OSS Distributions IOReturn
serializeVariables(void)616*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::serializeVariables(void)
617*bbb1b6f9SApple OSS Distributions {
618*bbb1b6f9SApple OSS Distributions 	IOReturn                          ret;
619*bbb1b6f9SApple OSS Distributions 	bool                              ok = false;
620*bbb1b6f9SApple OSS Distributions 	uint32_t                          length, maxLength, regionIndex;
621*bbb1b6f9SApple OSS Distributions 	uint8_t                           *buffer, *tmpBuffer;
622*bbb1b6f9SApple OSS Distributions 	const OSSymbol                    *tmpSymbol;
623*bbb1b6f9SApple OSS Distributions 	OSObject                          *tmpObject;
624*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSCollectionIterator> iter;
625*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSNumber>             generation;
626*bbb1b6f9SApple OSS Distributions 	uint8_t                           *nvramImage;
627*bbb1b6f9SApple OSS Distributions 	NVRAMRegionInfo                   *currentRegion;
628*bbb1b6f9SApple OSS Distributions 	NVRAMRegionInfo                   variableRegions[] = { { kIONVRAMPartitionCommon, _commonPartitionOffset, _commonPartitionSize},
629*bbb1b6f9SApple OSS Distributions 								{ kIONVRAMPartitionSystem, _systemPartitionOffset, _systemPartitionSize} };
630*bbb1b6f9SApple OSS Distributions 	NVRAMLOCKASSERTHELD(_controllerLock);
631*bbb1b6f9SApple OSS Distributions 
632*bbb1b6f9SApple OSS Distributions 	require_action(_nvramController != nullptr, exit, (ret = kIOReturnNotReady, DEBUG_ERROR("No _nvramController\n")));
633*bbb1b6f9SApple OSS Distributions 	require_action(_newData == true, exit, (ret = kIOReturnSuccess, DEBUG_INFO("No _newData to sync\n")));
634*bbb1b6f9SApple OSS Distributions 	require_action(_bankSize != 0, exit, (ret = kIOReturnSuccess, DEBUG_INFO("No nvram size info\n")));
635*bbb1b6f9SApple OSS Distributions 	require_action(_nvramImage != nullptr, exit, (ret = kIOReturnSuccess, DEBUG_INFO("No nvram image info\n")));
636*bbb1b6f9SApple OSS Distributions 
637*bbb1b6f9SApple OSS Distributions 	nvramImage = IONewZeroData(uint8_t, _bankSize);
638*bbb1b6f9SApple OSS Distributions 	require_action(nvramImage != nullptr, exit, (ret = kIOReturnNoMemory, DEBUG_ERROR("Can't create NVRAM image copy\n")));
639*bbb1b6f9SApple OSS Distributions 
640*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("...\n");
641*bbb1b6f9SApple OSS Distributions 
642*bbb1b6f9SApple OSS Distributions 	bcopy(_nvramImage, nvramImage, _bankSize);
643*bbb1b6f9SApple OSS Distributions 
644*bbb1b6f9SApple OSS Distributions 	NVRAMREADLOCK(_variableLock);
645*bbb1b6f9SApple OSS Distributions 	for (regionIndex = 0; regionIndex < ARRAY_SIZE(variableRegions); regionIndex++) {
646*bbb1b6f9SApple OSS Distributions 		currentRegion = &variableRegions[regionIndex];
647*bbb1b6f9SApple OSS Distributions 
648*bbb1b6f9SApple OSS Distributions 		if (currentRegion->size == 0) {
649*bbb1b6f9SApple OSS Distributions 			continue;
650*bbb1b6f9SApple OSS Distributions 		}
651*bbb1b6f9SApple OSS Distributions 
652*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("region = %d\n", currentRegion->type);
653*bbb1b6f9SApple OSS Distributions 		buffer = tmpBuffer = nvramImage + currentRegion->offset;
654*bbb1b6f9SApple OSS Distributions 
655*bbb1b6f9SApple OSS Distributions 		bzero(buffer, currentRegion->size);
656*bbb1b6f9SApple OSS Distributions 
657*bbb1b6f9SApple OSS Distributions 		ok = true;
658*bbb1b6f9SApple OSS Distributions 		maxLength = currentRegion->size;
659*bbb1b6f9SApple OSS Distributions 
660*bbb1b6f9SApple OSS Distributions 		iter = OSCollectionIterator::withCollection(_varDict.get());
661*bbb1b6f9SApple OSS Distributions 		if (iter == nullptr) {
662*bbb1b6f9SApple OSS Distributions 			ok = false;
663*bbb1b6f9SApple OSS Distributions 		}
664*bbb1b6f9SApple OSS Distributions 
665*bbb1b6f9SApple OSS Distributions 		while (ok) {
666*bbb1b6f9SApple OSS Distributions 			uuid_t entryGuid;
667*bbb1b6f9SApple OSS Distributions 			const char *entryName;
668*bbb1b6f9SApple OSS Distributions 
669*bbb1b6f9SApple OSS Distributions 			tmpSymbol = OSDynamicCast(OSSymbol, iter->getNextObject());
670*bbb1b6f9SApple OSS Distributions 
671*bbb1b6f9SApple OSS Distributions 			if (tmpSymbol == nullptr) {
672*bbb1b6f9SApple OSS Distributions 				break;
673*bbb1b6f9SApple OSS Distributions 			}
674*bbb1b6f9SApple OSS Distributions 
675*bbb1b6f9SApple OSS Distributions 			DEBUG_INFO("_varDict entry %s\n", tmpSymbol->getCStringNoCopy());
676*bbb1b6f9SApple OSS Distributions 
677*bbb1b6f9SApple OSS Distributions 			parseVariableName(tmpSymbol, &entryGuid, &entryName);
678*bbb1b6f9SApple OSS Distributions 
679*bbb1b6f9SApple OSS Distributions 			if (getSystemPartitionActive()) {
680*bbb1b6f9SApple OSS Distributions 				if (currentRegion->type == kIONVRAMPartitionSystem) {
681*bbb1b6f9SApple OSS Distributions 					if (uuid_compare(entryGuid, gAppleSystemVariableGuid) != 0) {
682*bbb1b6f9SApple OSS Distributions 						DEBUG_INFO("Skipping %s because not system var\n", entryName);
683*bbb1b6f9SApple OSS Distributions 						continue;
684*bbb1b6f9SApple OSS Distributions 					}
685*bbb1b6f9SApple OSS Distributions 				} else if (currentRegion->type == kIONVRAMPartitionCommon) {
686*bbb1b6f9SApple OSS Distributions 					if (uuid_compare(entryGuid, gAppleSystemVariableGuid) == 0) {
687*bbb1b6f9SApple OSS Distributions 						DEBUG_INFO("Skipping %s for common region\n", entryName);
688*bbb1b6f9SApple OSS Distributions 						continue;
689*bbb1b6f9SApple OSS Distributions 					}
690*bbb1b6f9SApple OSS Distributions 				}
691*bbb1b6f9SApple OSS Distributions 			}
692*bbb1b6f9SApple OSS Distributions 
693*bbb1b6f9SApple OSS Distributions 			DEBUG_INFO("adding variable %s\n", entryName);
694*bbb1b6f9SApple OSS Distributions 
695*bbb1b6f9SApple OSS Distributions 			tmpObject = _varDict->getObject(tmpSymbol);
696*bbb1b6f9SApple OSS Distributions 
697*bbb1b6f9SApple OSS Distributions 			length = maxLength;
698*bbb1b6f9SApple OSS Distributions 			ok = convertObjectToProp(tmpBuffer, &length, entryName, tmpObject);
699*bbb1b6f9SApple OSS Distributions 			if (ok) {
700*bbb1b6f9SApple OSS Distributions 				tmpBuffer += length;
701*bbb1b6f9SApple OSS Distributions 				maxLength -= length;
702*bbb1b6f9SApple OSS Distributions 			}
703*bbb1b6f9SApple OSS Distributions 		}
704*bbb1b6f9SApple OSS Distributions 
705*bbb1b6f9SApple OSS Distributions 		if (!ok) {
706*bbb1b6f9SApple OSS Distributions 			ret = kIOReturnNoSpace;
707*bbb1b6f9SApple OSS Distributions 			IODeleteData(nvramImage, uint8_t, _bankSize);
708*bbb1b6f9SApple OSS Distributions 			break;
709*bbb1b6f9SApple OSS Distributions 		}
710*bbb1b6f9SApple OSS Distributions 
711*bbb1b6f9SApple OSS Distributions 		if (currentRegion->type == kIONVRAMPartitionSystem) {
712*bbb1b6f9SApple OSS Distributions 			_systemUsed = (uint32_t)(tmpBuffer - buffer);
713*bbb1b6f9SApple OSS Distributions 		} else if (currentRegion->type == kIONVRAMPartitionCommon) {
714*bbb1b6f9SApple OSS Distributions 			_commonUsed = (uint32_t)(tmpBuffer - buffer);
715*bbb1b6f9SApple OSS Distributions 		}
716*bbb1b6f9SApple OSS Distributions 	}
717*bbb1b6f9SApple OSS Distributions 	NVRAMRWUNLOCK(_variableLock);
718*bbb1b6f9SApple OSS Distributions 
719*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("ok=%d\n", ok);
720*bbb1b6f9SApple OSS Distributions 	require(ok, exit);
721*bbb1b6f9SApple OSS Distributions 
722*bbb1b6f9SApple OSS Distributions 	nvram_set_apple_header(nvramImage, _bankSize, ++_generation, _version);
723*bbb1b6f9SApple OSS Distributions 
724*bbb1b6f9SApple OSS Distributions 	_currentBank = (_currentBank + 1) % _bankCount;
725*bbb1b6f9SApple OSS Distributions 
726*bbb1b6f9SApple OSS Distributions 	ret = _nvramController->select(_currentBank);
727*bbb1b6f9SApple OSS Distributions 	DEBUG_IFERROR(ret, "_currentBank=%#x, select=%#x\n", _currentBank, ret);
728*bbb1b6f9SApple OSS Distributions 
729*bbb1b6f9SApple OSS Distributions 	ret = _nvramController->eraseBank();
730*bbb1b6f9SApple OSS Distributions 	DEBUG_IFERROR(ret, "eraseBank=%#x\n", ret);
731*bbb1b6f9SApple OSS Distributions 
732*bbb1b6f9SApple OSS Distributions 	ret = _nvramController->write(0, nvramImage, _bankSize);
733*bbb1b6f9SApple OSS Distributions 	DEBUG_IFERROR(ret, "write=%#x\n", ret);
734*bbb1b6f9SApple OSS Distributions 
735*bbb1b6f9SApple OSS Distributions 	_nvramController->sync();
736*bbb1b6f9SApple OSS Distributions 
737*bbb1b6f9SApple OSS Distributions 	if (_nvramImage) {
738*bbb1b6f9SApple OSS Distributions 		IODeleteData(_nvramImage, uint8_t, _bankSize);
739*bbb1b6f9SApple OSS Distributions 	}
740*bbb1b6f9SApple OSS Distributions 
741*bbb1b6f9SApple OSS Distributions 	_nvramImage = nvramImage;
742*bbb1b6f9SApple OSS Distributions 
743*bbb1b6f9SApple OSS Distributions 	_newData = false;
744*bbb1b6f9SApple OSS Distributions 
745*bbb1b6f9SApple OSS Distributions exit:
746*bbb1b6f9SApple OSS Distributions 	return ret;
747*bbb1b6f9SApple OSS Distributions }
748*bbb1b6f9SApple OSS Distributions 
749*bbb1b6f9SApple OSS Distributions IOReturn
setVariableInternal(const uuid_t varGuid,const char * variableName,OSObject * object)750*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::setVariableInternal(const uuid_t varGuid, const char *variableName, OSObject *object)
751*bbb1b6f9SApple OSS Distributions {
752*bbb1b6f9SApple OSS Distributions 	uint32_t                    newSize = 0;
753*bbb1b6f9SApple OSS Distributions 	uint32_t                    existingSize = 0;
754*bbb1b6f9SApple OSS Distributions 	bool                        remove = (object == nullptr);
755*bbb1b6f9SApple OSS Distributions 	OSObject                    *existing;
756*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<const OSSymbol> canonicalKey;
757*bbb1b6f9SApple OSS Distributions 	bool                        systemVar;
758*bbb1b6f9SApple OSS Distributions 
759*bbb1b6f9SApple OSS Distributions 	// Anyone calling setVariableInternal should've already held the lock for write.
760*bbb1b6f9SApple OSS Distributions 	NVRAMRWLOCKASSERTEXCLUSIVE(_variableLock);
761*bbb1b6f9SApple OSS Distributions 
762*bbb1b6f9SApple OSS Distributions 	systemVar = (uuid_compare(varGuid, gAppleSystemVariableGuid) == 0);
763*bbb1b6f9SApple OSS Distributions 	canonicalKey = keyWithGuidAndCString(varGuid, variableName);
764*bbb1b6f9SApple OSS Distributions 
765*bbb1b6f9SApple OSS Distributions 	if ((existing = _varDict->getObject(canonicalKey.get()))) {
766*bbb1b6f9SApple OSS Distributions 		convertObjectToProp(nullptr, &existingSize, variableName, existing);
767*bbb1b6f9SApple OSS Distributions 	}
768*bbb1b6f9SApple OSS Distributions 
769*bbb1b6f9SApple OSS Distributions 	if (remove == false) {
770*bbb1b6f9SApple OSS Distributions 		convertObjectToProp(nullptr, &newSize, variableName, object);
771*bbb1b6f9SApple OSS Distributions 
772*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("setting %s, systemVar=%d, existingSize=%u, newSize=%u\n", canonicalKey.get()->getCStringNoCopy(), systemVar, existingSize, newSize);
773*bbb1b6f9SApple OSS Distributions 
774*bbb1b6f9SApple OSS Distributions 		if (systemVar) {
775*bbb1b6f9SApple OSS Distributions 			if ((newSize + _systemUsed - existingSize) > _systemPartitionSize) {
776*bbb1b6f9SApple OSS Distributions 				DEBUG_ERROR("No space left in system partition, need=%#x, _systemUsed=%#x, _systemPartitionSize=%#x\n",
777*bbb1b6f9SApple OSS Distributions 				    newSize, _systemUsed, _systemPartitionSize);
778*bbb1b6f9SApple OSS Distributions 				return kIOReturnNoSpace;
779*bbb1b6f9SApple OSS Distributions 			} else {
780*bbb1b6f9SApple OSS Distributions 				_systemUsed = _systemUsed + newSize - existingSize;
781*bbb1b6f9SApple OSS Distributions 			}
782*bbb1b6f9SApple OSS Distributions 		} else {
783*bbb1b6f9SApple OSS Distributions 			if ((newSize + _commonUsed - existingSize) > _commonPartitionSize) {
784*bbb1b6f9SApple OSS Distributions 				DEBUG_ERROR("No space left in common partition, need=%#x, _commonUsed=%#x, _commonPartitionSize=%#x\n",
785*bbb1b6f9SApple OSS Distributions 				    newSize, _commonUsed, _commonPartitionSize);
786*bbb1b6f9SApple OSS Distributions 				return kIOReturnNoSpace;
787*bbb1b6f9SApple OSS Distributions 			} else {
788*bbb1b6f9SApple OSS Distributions 				_commonUsed = _commonUsed + newSize - existingSize;
789*bbb1b6f9SApple OSS Distributions 			}
790*bbb1b6f9SApple OSS Distributions 		}
791*bbb1b6f9SApple OSS Distributions 
792*bbb1b6f9SApple OSS Distributions 		_varDict->setObject(canonicalKey.get(), object);
793*bbb1b6f9SApple OSS Distributions 
794*bbb1b6f9SApple OSS Distributions 		if (_provider->_diags) {
795*bbb1b6f9SApple OSS Distributions 			_provider->_diags->logVariable(getPartitionTypeForGUID(varGuid),
796*bbb1b6f9SApple OSS Distributions 			    kIONVRAMOperationWrite, variableName,
797*bbb1b6f9SApple OSS Distributions 			    (void *)(uintptr_t)newSize);
798*bbb1b6f9SApple OSS Distributions 		}
799*bbb1b6f9SApple OSS Distributions 	} else {
800*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("removing %s, systemVar=%d, existingSize=%u\n", canonicalKey.get()->getCStringNoCopy(), systemVar, existingSize);
801*bbb1b6f9SApple OSS Distributions 
802*bbb1b6f9SApple OSS Distributions 		if (systemVar) {
803*bbb1b6f9SApple OSS Distributions 			_systemUsed -= existingSize;
804*bbb1b6f9SApple OSS Distributions 		} else {
805*bbb1b6f9SApple OSS Distributions 			_commonUsed -= existingSize;
806*bbb1b6f9SApple OSS Distributions 		}
807*bbb1b6f9SApple OSS Distributions 
808*bbb1b6f9SApple OSS Distributions 		_varDict->removeObject(canonicalKey.get());
809*bbb1b6f9SApple OSS Distributions 
810*bbb1b6f9SApple OSS Distributions 		if (_provider->_diags) {
811*bbb1b6f9SApple OSS Distributions 			_provider->_diags->logVariable(getPartitionTypeForGUID(varGuid),
812*bbb1b6f9SApple OSS Distributions 			    kIONVRAMOperationDelete, variableName,
813*bbb1b6f9SApple OSS Distributions 			    nullptr);
814*bbb1b6f9SApple OSS Distributions 		}
815*bbb1b6f9SApple OSS Distributions 	}
816*bbb1b6f9SApple OSS Distributions 
817*bbb1b6f9SApple OSS Distributions 	if (_provider->_diags) {
818*bbb1b6f9SApple OSS Distributions 		OSSharedPtr<OSNumber> val = OSNumber::withNumber(getSystemUsed(), 32);
819*bbb1b6f9SApple OSS Distributions 		_provider->_diags->setProperty(kNVRAMSystemUsedKey, val.get());
820*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("%s=%u\n", kNVRAMSystemUsedKey, getSystemUsed());
821*bbb1b6f9SApple OSS Distributions 
822*bbb1b6f9SApple OSS Distributions 		val = OSNumber::withNumber(getCommonUsed(), 32);
823*bbb1b6f9SApple OSS Distributions 		_provider->_diags->setProperty(kNVRAMCommonUsedKey, val.get());
824*bbb1b6f9SApple OSS Distributions 		DEBUG_INFO("%s=%u\n", kNVRAMCommonUsedKey, getCommonUsed());
825*bbb1b6f9SApple OSS Distributions 	}
826*bbb1b6f9SApple OSS Distributions 
827*bbb1b6f9SApple OSS Distributions 	_newData = true;
828*bbb1b6f9SApple OSS Distributions 
829*bbb1b6f9SApple OSS Distributions 	return kIOReturnSuccess;
830*bbb1b6f9SApple OSS Distributions }
831*bbb1b6f9SApple OSS Distributions 
832*bbb1b6f9SApple OSS Distributions IOReturn
setVariable(const uuid_t varGuid,const char * variableName,OSObject * object)833*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::setVariable(const uuid_t varGuid, const char *variableName, OSObject *object)
834*bbb1b6f9SApple OSS Distributions {
835*bbb1b6f9SApple OSS Distributions 	uuid_t destGuid;
836*bbb1b6f9SApple OSS Distributions 	IOReturn ret = kIOReturnError;
837*bbb1b6f9SApple OSS Distributions 
838*bbb1b6f9SApple OSS Distributions 	if (getSystemPartitionActive()) {
839*bbb1b6f9SApple OSS Distributions 		// System region case, if they're using the GUID directly or it's on the system allow list
840*bbb1b6f9SApple OSS Distributions 		// force it to use the System GUID
841*bbb1b6f9SApple OSS Distributions 		if ((uuid_compare(varGuid, gAppleSystemVariableGuid) == 0) || variableInAllowList(variableName)) {
842*bbb1b6f9SApple OSS Distributions 			uuid_copy(destGuid, gAppleSystemVariableGuid);
843*bbb1b6f9SApple OSS Distributions 		} else {
844*bbb1b6f9SApple OSS Distributions 			uuid_copy(destGuid, varGuid);
845*bbb1b6f9SApple OSS Distributions 		}
846*bbb1b6f9SApple OSS Distributions 	} else {
847*bbb1b6f9SApple OSS Distributions 		// No system region, store System GUID as Common GUID
848*bbb1b6f9SApple OSS Distributions 		if ((uuid_compare(varGuid, gAppleSystemVariableGuid) == 0) || variableInAllowList(variableName)) {
849*bbb1b6f9SApple OSS Distributions 			uuid_copy(destGuid, gAppleNVRAMGuid);
850*bbb1b6f9SApple OSS Distributions 		} else {
851*bbb1b6f9SApple OSS Distributions 			uuid_copy(destGuid, varGuid);
852*bbb1b6f9SApple OSS Distributions 		}
853*bbb1b6f9SApple OSS Distributions 	}
854*bbb1b6f9SApple OSS Distributions 	NVRAMWRITELOCK(_variableLock);
855*bbb1b6f9SApple OSS Distributions 	ret = setVariableInternal(destGuid, variableName, object);
856*bbb1b6f9SApple OSS Distributions 	NVRAMRWUNLOCK(_variableLock);
857*bbb1b6f9SApple OSS Distributions 
858*bbb1b6f9SApple OSS Distributions 	return ret;
859*bbb1b6f9SApple OSS Distributions }
860*bbb1b6f9SApple OSS Distributions 
861*bbb1b6f9SApple OSS Distributions uint32_t
findCurrentBank(uint32_t * gen)862*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::findCurrentBank(uint32_t *gen)
863*bbb1b6f9SApple OSS Distributions {
864*bbb1b6f9SApple OSS Distributions 	struct apple_nvram_header storeHeader;
865*bbb1b6f9SApple OSS Distributions 	uint32_t                  maxGen = 0;
866*bbb1b6f9SApple OSS Distributions 	uint32_t                  currentBank = 0;
867*bbb1b6f9SApple OSS Distributions 
868*bbb1b6f9SApple OSS Distributions 	NVRAMLOCKASSERTHELD(_controllerLock);
869*bbb1b6f9SApple OSS Distributions 
870*bbb1b6f9SApple OSS Distributions 	for (unsigned int i = 0; i < _bankCount; i++) {
871*bbb1b6f9SApple OSS Distributions 		NVRAMVersion bankVer;
872*bbb1b6f9SApple OSS Distributions 		uint32_t bankGen = 0;
873*bbb1b6f9SApple OSS Distributions 
874*bbb1b6f9SApple OSS Distributions 		_nvramController->select(i);
875*bbb1b6f9SApple OSS Distributions 		_nvramController->read(0, (uint8_t *)&storeHeader, sizeof(storeHeader));
876*bbb1b6f9SApple OSS Distributions 		bankVer = validateNVRAMVersion((uint8_t *)&storeHeader, sizeof(storeHeader), &bankGen);
877*bbb1b6f9SApple OSS Distributions 
878*bbb1b6f9SApple OSS Distributions 		if ((bankVer != kNVRAMVersionUnknown) && (bankGen >= maxGen)) {
879*bbb1b6f9SApple OSS Distributions 			currentBank = i;
880*bbb1b6f9SApple OSS Distributions 			maxGen = bankGen;
881*bbb1b6f9SApple OSS Distributions 		}
882*bbb1b6f9SApple OSS Distributions 	}
883*bbb1b6f9SApple OSS Distributions 
884*bbb1b6f9SApple OSS Distributions 	DEBUG_ALWAYS("currentBank=%#x, gen=%#x\n", currentBank, maxGen);
885*bbb1b6f9SApple OSS Distributions 
886*bbb1b6f9SApple OSS Distributions 	*gen = maxGen;
887*bbb1b6f9SApple OSS Distributions 	return currentBank;
888*bbb1b6f9SApple OSS Distributions }
889*bbb1b6f9SApple OSS Distributions 
890*bbb1b6f9SApple OSS Distributions bool
setController(IONVRAMController * controller)891*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::setController(IONVRAMController *controller)
892*bbb1b6f9SApple OSS Distributions {
893*bbb1b6f9SApple OSS Distributions 	IOReturn ret;
894*bbb1b6f9SApple OSS Distributions 
895*bbb1b6f9SApple OSS Distributions 	NVRAMLOCK(_controllerLock);
896*bbb1b6f9SApple OSS Distributions 
897*bbb1b6f9SApple OSS Distributions 	if (_nvramController == NULL) {
898*bbb1b6f9SApple OSS Distributions 		_nvramController = controller;
899*bbb1b6f9SApple OSS Distributions 	}
900*bbb1b6f9SApple OSS Distributions 
901*bbb1b6f9SApple OSS Distributions 	DEBUG_INFO("Controller name: %s\n", _nvramController->getName());
902*bbb1b6f9SApple OSS Distributions 
903*bbb1b6f9SApple OSS Distributions 	ret = reloadInternal();
904*bbb1b6f9SApple OSS Distributions 	if (ret != kIOReturnSuccess) {
905*bbb1b6f9SApple OSS Distributions 		DEBUG_ERROR("reloadInternal failed, ret=0x%08x\n", ret);
906*bbb1b6f9SApple OSS Distributions 	}
907*bbb1b6f9SApple OSS Distributions 
908*bbb1b6f9SApple OSS Distributions 	NVRAMUNLOCK(_controllerLock);
909*bbb1b6f9SApple OSS Distributions 
910*bbb1b6f9SApple OSS Distributions 	return true;
911*bbb1b6f9SApple OSS Distributions }
912*bbb1b6f9SApple OSS Distributions 
913*bbb1b6f9SApple OSS Distributions IOReturn
sync(void)914*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::sync(void)
915*bbb1b6f9SApple OSS Distributions {
916*bbb1b6f9SApple OSS Distributions 	IOReturn ret;
917*bbb1b6f9SApple OSS Distributions 
918*bbb1b6f9SApple OSS Distributions 	NVRAMLOCK(_controllerLock);
919*bbb1b6f9SApple OSS Distributions 
920*bbb1b6f9SApple OSS Distributions 	if (_reload) {
921*bbb1b6f9SApple OSS Distributions 		ret = reloadInternal();
922*bbb1b6f9SApple OSS Distributions 		require_noerr_action(ret, exit, DEBUG_ERROR("Reload failed, ret=%#x", ret));
923*bbb1b6f9SApple OSS Distributions 
924*bbb1b6f9SApple OSS Distributions 		_reload = false;
925*bbb1b6f9SApple OSS Distributions 	}
926*bbb1b6f9SApple OSS Distributions 
927*bbb1b6f9SApple OSS Distributions 	ret = serializeVariables();
928*bbb1b6f9SApple OSS Distributions 	require_noerr_action(ret, exit, DEBUG_ERROR("serializeVariables failed, ret=%#x", ret));
929*bbb1b6f9SApple OSS Distributions 
930*bbb1b6f9SApple OSS Distributions exit:
931*bbb1b6f9SApple OSS Distributions 	NVRAMUNLOCK(_controllerLock);
932*bbb1b6f9SApple OSS Distributions 	return ret;
933*bbb1b6f9SApple OSS Distributions }
934*bbb1b6f9SApple OSS Distributions 
935*bbb1b6f9SApple OSS Distributions uint32_t
getGeneration(void) const936*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::getGeneration(void) const
937*bbb1b6f9SApple OSS Distributions {
938*bbb1b6f9SApple OSS Distributions 	return _generation;
939*bbb1b6f9SApple OSS Distributions }
940*bbb1b6f9SApple OSS Distributions 
941*bbb1b6f9SApple OSS Distributions uint32_t
getVersion(void) const942*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::getVersion(void) const
943*bbb1b6f9SApple OSS Distributions {
944*bbb1b6f9SApple OSS Distributions 	return _version;
945*bbb1b6f9SApple OSS Distributions }
946*bbb1b6f9SApple OSS Distributions 
947*bbb1b6f9SApple OSS Distributions uint32_t
getSystemUsed(void) const948*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::getSystemUsed(void) const
949*bbb1b6f9SApple OSS Distributions {
950*bbb1b6f9SApple OSS Distributions 	return _systemUsed;
951*bbb1b6f9SApple OSS Distributions }
952*bbb1b6f9SApple OSS Distributions 
953*bbb1b6f9SApple OSS Distributions uint32_t
getCommonUsed(void) const954*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::getCommonUsed(void) const
955*bbb1b6f9SApple OSS Distributions {
956*bbb1b6f9SApple OSS Distributions 	return _commonUsed;
957*bbb1b6f9SApple OSS Distributions }
958*bbb1b6f9SApple OSS Distributions 
959*bbb1b6f9SApple OSS Distributions bool
getSystemPartitionActive(void) const960*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::getSystemPartitionActive(void) const
961*bbb1b6f9SApple OSS Distributions {
962*bbb1b6f9SApple OSS Distributions 	return _systemPartitionSize != 0;
963*bbb1b6f9SApple OSS Distributions }
964*bbb1b6f9SApple OSS Distributions 
965*bbb1b6f9SApple OSS Distributions OSSharedPtr<OSData>
unescapeBytesToData(const uint8_t * bytes,uint32_t length)966*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::unescapeBytesToData(const uint8_t *bytes, uint32_t length)
967*bbb1b6f9SApple OSS Distributions {
968*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSData> data;
969*bbb1b6f9SApple OSS Distributions 	uint32_t            totalLength = 0;
970*bbb1b6f9SApple OSS Distributions 	uint32_t            offset, offset2;
971*bbb1b6f9SApple OSS Distributions 	uint8_t             byte;
972*bbb1b6f9SApple OSS Distributions 	bool                ok;
973*bbb1b6f9SApple OSS Distributions 
974*bbb1b6f9SApple OSS Distributions 	// Calculate the actual length of the data.
975*bbb1b6f9SApple OSS Distributions 	ok = true;
976*bbb1b6f9SApple OSS Distributions 	totalLength = 0;
977*bbb1b6f9SApple OSS Distributions 	for (offset = 0; offset < length;) {
978*bbb1b6f9SApple OSS Distributions 		byte = bytes[offset++];
979*bbb1b6f9SApple OSS Distributions 		if (byte == 0xFF) {
980*bbb1b6f9SApple OSS Distributions 			byte = bytes[offset++];
981*bbb1b6f9SApple OSS Distributions 			if (byte == 0x00) {
982*bbb1b6f9SApple OSS Distributions 				ok = false;
983*bbb1b6f9SApple OSS Distributions 				break;
984*bbb1b6f9SApple OSS Distributions 			}
985*bbb1b6f9SApple OSS Distributions 			offset2 = byte & 0x7F;
986*bbb1b6f9SApple OSS Distributions 		} else {
987*bbb1b6f9SApple OSS Distributions 			offset2 = 1;
988*bbb1b6f9SApple OSS Distributions 		}
989*bbb1b6f9SApple OSS Distributions 		totalLength += offset2;
990*bbb1b6f9SApple OSS Distributions 	}
991*bbb1b6f9SApple OSS Distributions 
992*bbb1b6f9SApple OSS Distributions 	if (ok) {
993*bbb1b6f9SApple OSS Distributions 		// Create an empty OSData of the correct size.
994*bbb1b6f9SApple OSS Distributions 		data = OSData::withCapacity(totalLength);
995*bbb1b6f9SApple OSS Distributions 		if (data != nullptr) {
996*bbb1b6f9SApple OSS Distributions 			for (offset = 0; offset < length;) {
997*bbb1b6f9SApple OSS Distributions 				byte = bytes[offset++];
998*bbb1b6f9SApple OSS Distributions 				if (byte == 0xFF) {
999*bbb1b6f9SApple OSS Distributions 					byte = bytes[offset++];
1000*bbb1b6f9SApple OSS Distributions 					offset2 = byte & 0x7F;
1001*bbb1b6f9SApple OSS Distributions 					byte = (byte & 0x80) ? 0xFF : 0x00;
1002*bbb1b6f9SApple OSS Distributions 				} else {
1003*bbb1b6f9SApple OSS Distributions 					offset2 = 1;
1004*bbb1b6f9SApple OSS Distributions 				}
1005*bbb1b6f9SApple OSS Distributions 				data->appendByte(byte, offset2);
1006*bbb1b6f9SApple OSS Distributions 			}
1007*bbb1b6f9SApple OSS Distributions 		}
1008*bbb1b6f9SApple OSS Distributions 	}
1009*bbb1b6f9SApple OSS Distributions 
1010*bbb1b6f9SApple OSS Distributions 	return data;
1011*bbb1b6f9SApple OSS Distributions }
1012*bbb1b6f9SApple OSS Distributions 
1013*bbb1b6f9SApple OSS Distributions OSSharedPtr<OSData>
escapeDataToData(OSData * value)1014*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::escapeDataToData(OSData * value)
1015*bbb1b6f9SApple OSS Distributions {
1016*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSData>         result;
1017*bbb1b6f9SApple OSS Distributions 	OSBoundedPtr<const uint8_t> startPtr;
1018*bbb1b6f9SApple OSS Distributions 	const uint8_t               *endPtr;
1019*bbb1b6f9SApple OSS Distributions 	const uint8_t               *valueBytesPtr;
1020*bbb1b6f9SApple OSS Distributions 	OSBoundedPtr<const uint8_t> wherePtr;
1021*bbb1b6f9SApple OSS Distributions 	uint8_t                     byte;
1022*bbb1b6f9SApple OSS Distributions 	bool                        ok = true;
1023*bbb1b6f9SApple OSS Distributions 
1024*bbb1b6f9SApple OSS Distributions 	valueBytesPtr = (const uint8_t *) value->getBytesNoCopy();
1025*bbb1b6f9SApple OSS Distributions 	endPtr = valueBytesPtr + value->getLength();
1026*bbb1b6f9SApple OSS Distributions 	wherePtr = OSBoundedPtr<const uint8_t>(valueBytesPtr, valueBytesPtr, endPtr);
1027*bbb1b6f9SApple OSS Distributions 
1028*bbb1b6f9SApple OSS Distributions 	result = OSData::withCapacity((unsigned int)(endPtr - wherePtr));
1029*bbb1b6f9SApple OSS Distributions 	if (!result) {
1030*bbb1b6f9SApple OSS Distributions 		return result;
1031*bbb1b6f9SApple OSS Distributions 	}
1032*bbb1b6f9SApple OSS Distributions 
1033*bbb1b6f9SApple OSS Distributions 	while (wherePtr < endPtr) {
1034*bbb1b6f9SApple OSS Distributions 		startPtr = wherePtr;
1035*bbb1b6f9SApple OSS Distributions 		byte = *wherePtr++;
1036*bbb1b6f9SApple OSS Distributions 		if ((byte == 0x00) || (byte == 0xFF)) {
1037*bbb1b6f9SApple OSS Distributions 			for (;
1038*bbb1b6f9SApple OSS Distributions 			    ((wherePtr - startPtr) < 0x7F) && (wherePtr < endPtr) && (byte == *wherePtr);
1039*bbb1b6f9SApple OSS Distributions 			    wherePtr++) {
1040*bbb1b6f9SApple OSS Distributions 			}
1041*bbb1b6f9SApple OSS Distributions 			ok &= result->appendByte(0xff, 1);
1042*bbb1b6f9SApple OSS Distributions 			byte = (byte & 0x80) | ((uint8_t)(wherePtr - startPtr));
1043*bbb1b6f9SApple OSS Distributions 		}
1044*bbb1b6f9SApple OSS Distributions 		ok &= result->appendByte(byte, 1);
1045*bbb1b6f9SApple OSS Distributions 	}
1046*bbb1b6f9SApple OSS Distributions 	ok &= result->appendByte(0, 1);
1047*bbb1b6f9SApple OSS Distributions 
1048*bbb1b6f9SApple OSS Distributions 	if (!ok) {
1049*bbb1b6f9SApple OSS Distributions 		result.reset();
1050*bbb1b6f9SApple OSS Distributions 	}
1051*bbb1b6f9SApple OSS Distributions 
1052*bbb1b6f9SApple OSS Distributions 	return result;
1053*bbb1b6f9SApple OSS Distributions }
1054*bbb1b6f9SApple OSS Distributions 
1055*bbb1b6f9SApple OSS Distributions bool
convertPropToObject(const uint8_t * propName,uint32_t propNameLength,const uint8_t * propData,uint32_t propDataLength,const OSSymbol ** propSymbol,OSObject ** propObject)1056*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::convertPropToObject(const uint8_t *propName, uint32_t propNameLength,
1057*bbb1b6f9SApple OSS Distributions     const uint8_t *propData, uint32_t propDataLength,
1058*bbb1b6f9SApple OSS Distributions     const OSSymbol **propSymbol,
1059*bbb1b6f9SApple OSS Distributions     OSObject **propObject)
1060*bbb1b6f9SApple OSS Distributions {
1061*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<const OSString> delimitedName;
1062*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<const OSSymbol> tmpSymbol;
1063*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSNumber>       tmpNumber;
1064*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSString>       tmpString;
1065*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSObject>       tmpObject = nullptr;
1066*bbb1b6f9SApple OSS Distributions 
1067*bbb1b6f9SApple OSS Distributions 	delimitedName = OSString::withCString((const char *)propName, propNameLength);
1068*bbb1b6f9SApple OSS Distributions 	tmpSymbol = OSSymbol::withString(delimitedName.get());
1069*bbb1b6f9SApple OSS Distributions 
1070*bbb1b6f9SApple OSS Distributions 	if (tmpSymbol == nullptr) {
1071*bbb1b6f9SApple OSS Distributions 		return false;
1072*bbb1b6f9SApple OSS Distributions 	}
1073*bbb1b6f9SApple OSS Distributions 
1074*bbb1b6f9SApple OSS Distributions 	switch (getVariableType(tmpSymbol.get())) {
1075*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeBoolean:
1076*bbb1b6f9SApple OSS Distributions 		if (!strncmp("true", (const char *)propData, propDataLength)) {
1077*bbb1b6f9SApple OSS Distributions 			tmpObject.reset(kOSBooleanTrue, OSRetain);
1078*bbb1b6f9SApple OSS Distributions 		} else if (!strncmp("false", (const char *)propData, propDataLength)) {
1079*bbb1b6f9SApple OSS Distributions 			tmpObject.reset(kOSBooleanFalse, OSRetain);
1080*bbb1b6f9SApple OSS Distributions 		}
1081*bbb1b6f9SApple OSS Distributions 		break;
1082*bbb1b6f9SApple OSS Distributions 
1083*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeNumber:
1084*bbb1b6f9SApple OSS Distributions 		tmpNumber = OSNumber::withNumber(strtol((const char *)propData, nullptr, 0), 32);
1085*bbb1b6f9SApple OSS Distributions 		if (tmpNumber != nullptr) {
1086*bbb1b6f9SApple OSS Distributions 			tmpObject = tmpNumber;
1087*bbb1b6f9SApple OSS Distributions 		}
1088*bbb1b6f9SApple OSS Distributions 		break;
1089*bbb1b6f9SApple OSS Distributions 
1090*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeString:
1091*bbb1b6f9SApple OSS Distributions 		tmpString = OSString::withCString((const char *)propData, propDataLength);
1092*bbb1b6f9SApple OSS Distributions 		if (tmpString != nullptr) {
1093*bbb1b6f9SApple OSS Distributions 			tmpObject = tmpString;
1094*bbb1b6f9SApple OSS Distributions 		}
1095*bbb1b6f9SApple OSS Distributions 		break;
1096*bbb1b6f9SApple OSS Distributions 
1097*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeData:
1098*bbb1b6f9SApple OSS Distributions 		tmpObject = unescapeBytesToData(propData, propDataLength);
1099*bbb1b6f9SApple OSS Distributions 		break;
1100*bbb1b6f9SApple OSS Distributions 
1101*bbb1b6f9SApple OSS Distributions 	default:
1102*bbb1b6f9SApple OSS Distributions 		break;
1103*bbb1b6f9SApple OSS Distributions 	}
1104*bbb1b6f9SApple OSS Distributions 
1105*bbb1b6f9SApple OSS Distributions 	if (tmpObject == nullptr) {
1106*bbb1b6f9SApple OSS Distributions 		tmpSymbol.reset();
1107*bbb1b6f9SApple OSS Distributions 		return false;
1108*bbb1b6f9SApple OSS Distributions 	}
1109*bbb1b6f9SApple OSS Distributions 
1110*bbb1b6f9SApple OSS Distributions 	*propSymbol = tmpSymbol.detach();
1111*bbb1b6f9SApple OSS Distributions 	*propObject = tmpObject.detach();
1112*bbb1b6f9SApple OSS Distributions 
1113*bbb1b6f9SApple OSS Distributions 	return true;
1114*bbb1b6f9SApple OSS Distributions }
1115*bbb1b6f9SApple OSS Distributions 
1116*bbb1b6f9SApple OSS Distributions bool
convertPropToObject(const uint8_t * propName,uint32_t propNameLength,const uint8_t * propData,uint32_t propDataLength,OSSharedPtr<const OSSymbol> & propSymbol,OSSharedPtr<OSObject> & propObject)1117*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::convertPropToObject(const uint8_t *propName, uint32_t propNameLength,
1118*bbb1b6f9SApple OSS Distributions     const uint8_t *propData, uint32_t propDataLength,
1119*bbb1b6f9SApple OSS Distributions     OSSharedPtr<const OSSymbol>& propSymbol,
1120*bbb1b6f9SApple OSS Distributions     OSSharedPtr<OSObject>& propObject)
1121*bbb1b6f9SApple OSS Distributions {
1122*bbb1b6f9SApple OSS Distributions 	const OSSymbol* propSymbolRaw = nullptr;
1123*bbb1b6f9SApple OSS Distributions 	OSObject* propObjectRaw       = nullptr;
1124*bbb1b6f9SApple OSS Distributions 
1125*bbb1b6f9SApple OSS Distributions 	bool ok = convertPropToObject(propName, propNameLength, propData, propDataLength,
1126*bbb1b6f9SApple OSS Distributions 	    &propSymbolRaw, &propObjectRaw);
1127*bbb1b6f9SApple OSS Distributions 
1128*bbb1b6f9SApple OSS Distributions 	propSymbol.reset(propSymbolRaw, OSNoRetain);
1129*bbb1b6f9SApple OSS Distributions 	propObject.reset(propObjectRaw, OSNoRetain);
1130*bbb1b6f9SApple OSS Distributions 
1131*bbb1b6f9SApple OSS Distributions 	return ok;
1132*bbb1b6f9SApple OSS Distributions }
1133*bbb1b6f9SApple OSS Distributions 
1134*bbb1b6f9SApple OSS Distributions bool
convertObjectToProp(uint8_t * buffer,uint32_t * length,const OSSymbol * propSymbol,OSObject * propObject)1135*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::convertObjectToProp(uint8_t *buffer, uint32_t *length,
1136*bbb1b6f9SApple OSS Distributions     const OSSymbol *propSymbol, OSObject *propObject)
1137*bbb1b6f9SApple OSS Distributions {
1138*bbb1b6f9SApple OSS Distributions 	return convertObjectToProp(buffer, length, propSymbol->getCStringNoCopy(), propObject);
1139*bbb1b6f9SApple OSS Distributions }
1140*bbb1b6f9SApple OSS Distributions 
1141*bbb1b6f9SApple OSS Distributions bool
convertObjectToProp(uint8_t * buffer,uint32_t * length,const char * propName,OSObject * propObject)1142*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::convertObjectToProp(uint8_t *buffer, uint32_t *length,
1143*bbb1b6f9SApple OSS Distributions     const char *propName, OSObject *propObject)
1144*bbb1b6f9SApple OSS Distributions {
1145*bbb1b6f9SApple OSS Distributions 	uint32_t             propNameLength, propDataLength, remaining, offset;
1146*bbb1b6f9SApple OSS Distributions 	IONVRAMVariableType  propType;
1147*bbb1b6f9SApple OSS Distributions 	OSBoolean            *tmpBoolean = nullptr;
1148*bbb1b6f9SApple OSS Distributions 	OSNumber             *tmpNumber = nullptr;
1149*bbb1b6f9SApple OSS Distributions 	OSString             *tmpString = nullptr;
1150*bbb1b6f9SApple OSS Distributions 	OSSharedPtr<OSData>  tmpData;
1151*bbb1b6f9SApple OSS Distributions 
1152*bbb1b6f9SApple OSS Distributions 	propNameLength = (uint32_t)strlen(propName);
1153*bbb1b6f9SApple OSS Distributions 	propType = getVariableType(propName);
1154*bbb1b6f9SApple OSS Distributions 	offset = 0;
1155*bbb1b6f9SApple OSS Distributions 	remaining = 0;
1156*bbb1b6f9SApple OSS Distributions 
1157*bbb1b6f9SApple OSS Distributions 	// Get the size of the data.
1158*bbb1b6f9SApple OSS Distributions 	propDataLength = 0xFFFFFFFF;
1159*bbb1b6f9SApple OSS Distributions 	switch (propType) {
1160*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeBoolean:
1161*bbb1b6f9SApple OSS Distributions 		tmpBoolean = OSDynamicCast(OSBoolean, propObject);
1162*bbb1b6f9SApple OSS Distributions 		if (tmpBoolean != nullptr) {
1163*bbb1b6f9SApple OSS Distributions 			propDataLength = 5;
1164*bbb1b6f9SApple OSS Distributions 		}
1165*bbb1b6f9SApple OSS Distributions 		break;
1166*bbb1b6f9SApple OSS Distributions 
1167*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeNumber:
1168*bbb1b6f9SApple OSS Distributions 		tmpNumber = OSDynamicCast(OSNumber, propObject);
1169*bbb1b6f9SApple OSS Distributions 		if (tmpNumber != nullptr) {
1170*bbb1b6f9SApple OSS Distributions 			propDataLength = 10;
1171*bbb1b6f9SApple OSS Distributions 		}
1172*bbb1b6f9SApple OSS Distributions 		break;
1173*bbb1b6f9SApple OSS Distributions 
1174*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeString:
1175*bbb1b6f9SApple OSS Distributions 		tmpString = OSDynamicCast(OSString, propObject);
1176*bbb1b6f9SApple OSS Distributions 		if (tmpString != nullptr) {
1177*bbb1b6f9SApple OSS Distributions 			propDataLength = tmpString->getLength();
1178*bbb1b6f9SApple OSS Distributions 		}
1179*bbb1b6f9SApple OSS Distributions 		break;
1180*bbb1b6f9SApple OSS Distributions 
1181*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeData:
1182*bbb1b6f9SApple OSS Distributions 		tmpData.reset(OSDynamicCast(OSData, propObject), OSNoRetain);
1183*bbb1b6f9SApple OSS Distributions 		if (tmpData != nullptr) {
1184*bbb1b6f9SApple OSS Distributions 			tmpData = escapeDataToData(tmpData.detach());
1185*bbb1b6f9SApple OSS Distributions 			// escapeDataToData() adds the NULL byte to the data
1186*bbb1b6f9SApple OSS Distributions 			// subtract 1 here to keep offset consistent with the other cases
1187*bbb1b6f9SApple OSS Distributions 			propDataLength = tmpData->getLength() - 1;
1188*bbb1b6f9SApple OSS Distributions 		}
1189*bbb1b6f9SApple OSS Distributions 		break;
1190*bbb1b6f9SApple OSS Distributions 
1191*bbb1b6f9SApple OSS Distributions 	default:
1192*bbb1b6f9SApple OSS Distributions 		break;
1193*bbb1b6f9SApple OSS Distributions 	}
1194*bbb1b6f9SApple OSS Distributions 
1195*bbb1b6f9SApple OSS Distributions 	// Make sure the propertySize is known and will fit.
1196*bbb1b6f9SApple OSS Distributions 	if (propDataLength == 0xFFFFFFFF) {
1197*bbb1b6f9SApple OSS Distributions 		return false;
1198*bbb1b6f9SApple OSS Distributions 	}
1199*bbb1b6f9SApple OSS Distributions 
1200*bbb1b6f9SApple OSS Distributions 	if (buffer) {
1201*bbb1b6f9SApple OSS Distributions 		// name + '=' + data + '\0'
1202*bbb1b6f9SApple OSS Distributions 		if ((propNameLength + propDataLength + 2) > *length) {
1203*bbb1b6f9SApple OSS Distributions 			return false;
1204*bbb1b6f9SApple OSS Distributions 		}
1205*bbb1b6f9SApple OSS Distributions 
1206*bbb1b6f9SApple OSS Distributions 		remaining = *length;
1207*bbb1b6f9SApple OSS Distributions 	}
1208*bbb1b6f9SApple OSS Distributions 
1209*bbb1b6f9SApple OSS Distributions 	*length = 0;
1210*bbb1b6f9SApple OSS Distributions 
1211*bbb1b6f9SApple OSS Distributions 	// Copy the property name equal sign.
1212*bbb1b6f9SApple OSS Distributions 	offset += snprintf((char *)buffer, remaining, "%s=", propName);
1213*bbb1b6f9SApple OSS Distributions 	if (buffer) {
1214*bbb1b6f9SApple OSS Distributions 		if (remaining > offset) {
1215*bbb1b6f9SApple OSS Distributions 			buffer += offset;
1216*bbb1b6f9SApple OSS Distributions 			remaining = remaining - offset;
1217*bbb1b6f9SApple OSS Distributions 		} else {
1218*bbb1b6f9SApple OSS Distributions 			return false;
1219*bbb1b6f9SApple OSS Distributions 		}
1220*bbb1b6f9SApple OSS Distributions 	}
1221*bbb1b6f9SApple OSS Distributions 
1222*bbb1b6f9SApple OSS Distributions 	switch (propType) {
1223*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeBoolean:
1224*bbb1b6f9SApple OSS Distributions 		if (tmpBoolean->getValue()) {
1225*bbb1b6f9SApple OSS Distributions 			offset += strlcpy((char *)buffer, "true", remaining);
1226*bbb1b6f9SApple OSS Distributions 		} else {
1227*bbb1b6f9SApple OSS Distributions 			offset += strlcpy((char *)buffer, "false", remaining);
1228*bbb1b6f9SApple OSS Distributions 		}
1229*bbb1b6f9SApple OSS Distributions 		break;
1230*bbb1b6f9SApple OSS Distributions 
1231*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeNumber:
1232*bbb1b6f9SApple OSS Distributions 	{
1233*bbb1b6f9SApple OSS Distributions 		uint32_t tmpValue = tmpNumber->unsigned32BitValue();
1234*bbb1b6f9SApple OSS Distributions 		if (tmpValue == 0xFFFFFFFF) {
1235*bbb1b6f9SApple OSS Distributions 			offset += strlcpy((char *)buffer, "-1", remaining);
1236*bbb1b6f9SApple OSS Distributions 		} else if (tmpValue < 1000) {
1237*bbb1b6f9SApple OSS Distributions 			offset += snprintf((char *)buffer, remaining, "%d", (uint32_t)tmpValue);
1238*bbb1b6f9SApple OSS Distributions 		} else {
1239*bbb1b6f9SApple OSS Distributions 			offset += snprintf((char *)buffer, remaining, "%#x", (uint32_t)tmpValue);
1240*bbb1b6f9SApple OSS Distributions 		}
1241*bbb1b6f9SApple OSS Distributions 	}
1242*bbb1b6f9SApple OSS Distributions 	break;
1243*bbb1b6f9SApple OSS Distributions 
1244*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeString:
1245*bbb1b6f9SApple OSS Distributions 		offset += strlcpy((char *)buffer, tmpString->getCStringNoCopy(), remaining);
1246*bbb1b6f9SApple OSS Distributions 		break;
1247*bbb1b6f9SApple OSS Distributions 
1248*bbb1b6f9SApple OSS Distributions 	case kOFVariableTypeData:
1249*bbb1b6f9SApple OSS Distributions 		if (buffer) {
1250*bbb1b6f9SApple OSS Distributions 			bcopy(tmpData->getBytesNoCopy(), buffer, propDataLength);
1251*bbb1b6f9SApple OSS Distributions 		}
1252*bbb1b6f9SApple OSS Distributions 		tmpData.reset();
1253*bbb1b6f9SApple OSS Distributions 		offset += propDataLength;
1254*bbb1b6f9SApple OSS Distributions 		break;
1255*bbb1b6f9SApple OSS Distributions 
1256*bbb1b6f9SApple OSS Distributions 	default:
1257*bbb1b6f9SApple OSS Distributions 		break;
1258*bbb1b6f9SApple OSS Distributions 	}
1259*bbb1b6f9SApple OSS Distributions 
1260*bbb1b6f9SApple OSS Distributions 	*length = offset + 1;
1261*bbb1b6f9SApple OSS Distributions 
1262*bbb1b6f9SApple OSS Distributions 	return true;
1263*bbb1b6f9SApple OSS Distributions }
1264*bbb1b6f9SApple OSS Distributions 
1265*bbb1b6f9SApple OSS Distributions IOReturn
getVarDict(OSSharedPtr<OSDictionary> & varDictCopy)1266*bbb1b6f9SApple OSS Distributions IONVRAMCHRPHandler::getVarDict(OSSharedPtr<OSDictionary> &varDictCopy)
1267*bbb1b6f9SApple OSS Distributions {
1268*bbb1b6f9SApple OSS Distributions 	IOReturn ret = kIOReturnNotFound;
1269*bbb1b6f9SApple OSS Distributions 
1270*bbb1b6f9SApple OSS Distributions 	NVRAMREADLOCK(_variableLock);
1271*bbb1b6f9SApple OSS Distributions 	if (_varDict) {
1272*bbb1b6f9SApple OSS Distributions 		varDictCopy = OSDictionary::withDictionary(_varDict.get());
1273*bbb1b6f9SApple OSS Distributions 		if (varDictCopy) {
1274*bbb1b6f9SApple OSS Distributions 			if (OSDictionary::withCapacity(varDictCopy->getCount()) != nullptr) {
1275*bbb1b6f9SApple OSS Distributions 				ret = kIOReturnSuccess;
1276*bbb1b6f9SApple OSS Distributions 			}
1277*bbb1b6f9SApple OSS Distributions 		}
1278*bbb1b6f9SApple OSS Distributions 	}
1279*bbb1b6f9SApple OSS Distributions 	NVRAMRWUNLOCK(_variableLock);
1280*bbb1b6f9SApple OSS Distributions 
1281*bbb1b6f9SApple OSS Distributions 	return ret;
1282*bbb1b6f9SApple OSS Distributions }
1283