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