]> git.saurik.com Git - apple/system_cmds.git/blame - nvram.tproj/nvram.c
system_cmds-643.1.1.tar.gz
[apple/system_cmds.git] / nvram.tproj / nvram.c
CommitLineData
1815bff5 1/*
fc6d9e4b 2 * Copyright (c) 2000-2012 Apple Computer, Inc. All rights reserved.
1815bff5
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
2fc1e207
A
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1815bff5
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2fc1e207
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
1815bff5
A
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
83f6dbe8 23cc -o nvram nvram.c -framework CoreFoundation -framework IOKit -Wall
1815bff5
A
24*/
25
26#include <stdio.h>
27#include <IOKit/IOKitLib.h>
83f6dbe8 28#include <IOKit/IOKitKeys.h>
1815bff5 29#include <CoreFoundation/CoreFoundation.h>
ef8ad44b
A
30#include <err.h>
31#include <mach/mach_error.h>
1815bff5
A
32
33// Prototypes
1815bff5
A
34static void UsageMessage(char *message);
35static void ParseFile(char *fileName);
34d340d7 36static void ParseXMLFile(char *fileName);
1815bff5
A
37static void SetOrGetOFVariable(char *str);
38static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef,
39 CFTypeRef *valueRef);
40static kern_return_t SetOFVariable(char *name, char *value);
83f6dbe8 41static void DeleteOFVariable(char *name);
1815bff5
A
42static void PrintOFVariables(void);
43static void PrintOFVariable(const void *key,const void *value,void *context);
34d340d7
A
44static void SetOFVariableFromFile(const void *key, const void *value, void *context);
45static void ClearOFVariables(void);
46static void ClearOFVariable(const void *key,const void *value,void *context);
1815bff5
A
47static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value);
48
8459d725
A
49static void NVRamSyncNow(char *name);
50
1815bff5
A
51// Global Variables
52static char *gToolName;
53static io_registry_entry_t gOptionsRef;
34d340d7 54static bool gUseXML;
1815bff5
A
55
56
57int main(int argc, char **argv)
58{
59 long cnt;
60 char *str, errorMessage[256];
61 kern_return_t result;
62 mach_port_t masterPort;
63
64 // Get the name of the command.
65 gToolName = strrchr(argv[0], '/');
66 if (gToolName != 0) gToolName++;
67 else gToolName = argv[0];
68
69 result = IOMasterPort(bootstrap_port, &masterPort);
70 if (result != KERN_SUCCESS) {
ef8ad44b
A
71 errx(1, "Error getting the IOMaster port: %s",
72 mach_error_string(result));
1815bff5
A
73 }
74
75 gOptionsRef = IORegistryEntryFromPath(masterPort, "IODeviceTree:/options");
76 if (gOptionsRef == 0) {
ef8ad44b 77 errx(1, "nvram is not supported on this system");
1815bff5
A
78 }
79
80 for (cnt = 1; cnt < argc; cnt++) {
81 str = argv[cnt];
82 if (str[0] == '-' && str[1] != 0) {
83 // Parse the options.
84 for (str += 1 ; *str; str++) {
85 switch (*str) {
86 case 'p' :
87 PrintOFVariables();
88 break;
34d340d7
A
89
90 case 'x' :
91 gUseXML = true;
92 break;
93
1815bff5
A
94 case 'f':
95 cnt++;
96 if (cnt < argc && *argv[cnt] != '-') {
97 ParseFile(argv[cnt]);
98 } else {
99 UsageMessage("missing filename");
100 }
101 break;
102
83f6dbe8
A
103 case 'd':
104 cnt++;
105 if (cnt < argc && *argv[cnt] != '-') {
106 DeleteOFVariable(argv[cnt]);
107 } else {
108 UsageMessage("missing name");
109 }
110 break;
111
34d340d7
A
112 case 'c':
113 ClearOFVariables();
114 break;
115
1815bff5
A
116 default:
117 strcpy(errorMessage, "no such option as --");
118 errorMessage[strlen(errorMessage)-1] = *str;
119 UsageMessage(errorMessage);
120 }
121 }
122 } else {
4c00c0ae 123 // Other arguments will be firmware variable requests.
1815bff5
A
124 SetOrGetOFVariable(str);
125 }
126 }
127
128 IOObjectRelease(gOptionsRef);
129
130 return 0;
131}
132
1815bff5
A
133// UsageMessage(message)
134//
135// Print the usage information and exit.
136//
137static void UsageMessage(char *message)
138{
ef8ad44b 139 warnx("(usage: %s)", message);
1815bff5 140
fc6d9e4b 141 printf("%s [-x] [-p] [-f filename] [-d name] [-c] name[=value] ...\n", gToolName);
34d340d7
A
142 printf("\t-x use XML format for printing or reading variables\n");
143 printf("\t (must appear before -p or -f)\n");
4c00c0ae
A
144 printf("\t-p print all firmware variables\n");
145 printf("\t-f set firmware variables from a text file\n");
83f6dbe8 146 printf("\t-d delete the named variable\n");
34d340d7 147 printf("\t-c delete all variables\n");
1815bff5
A
148 printf("\tname=value set named variable\n");
149 printf("\tname print variable\n");
150 printf("Note that arguments and options are executed in order.\n");
151
152 exit(1);
153}
154
155
156// States for ParseFile.
157enum {
158 kFirstColumn = 0,
159 kScanComment,
160 kFindName,
161 kCollectName,
162 kFindValue,
163 kCollectValue,
164 kContinueValue,
165 kSetenv,
166
167 kMaxStringSize = 0x800,
168 kMaxNameSize = 0x100
169};
170
171
172// ParseFile(fileName)
173//
174// Open and parse the specified file.
175//
176static void ParseFile(char *fileName)
177{
178 long state, tc, ni = 0, vi = 0;
179 char name[kMaxNameSize];
180 char value[kMaxStringSize];
181 FILE *patches;
ef8ad44b 182 kern_return_t kret;
34d340d7
A
183
184 if (gUseXML) {
185 ParseXMLFile(fileName);
186 return;
187 }
1815bff5
A
188
189 patches = fopen(fileName, "r");
190 if (patches == 0) {
ef8ad44b 191 err(1, "Couldn't open patch file - '%s'", fileName);
1815bff5
A
192 }
193
194 state = kFirstColumn;
195 while ((tc = getc(patches)) != EOF) {
34d340d7 196 if(ni==(kMaxNameSize-1))
ef8ad44b 197 errx(1, "Name exceeded max length of %d", kMaxNameSize);
34d340d7 198 if(vi==(kMaxStringSize-1))
ef8ad44b 199 errx(1, "Value exceeded max length of %d", kMaxStringSize);
1815bff5
A
200 switch (state) {
201 case kFirstColumn :
202 ni = 0;
203 vi = 0;
204 if (tc == '#') {
205 state = kScanComment;
206 } else if (tc == '\n') {
207 // state stays kFirstColumn.
208 } else if (isspace(tc)) {
209 state = kFindName;
210 } else {
211 state = kCollectName;
212 name[ni++] = tc;
213 }
214 break;
215
216 case kScanComment :
217 if (tc == '\n') {
218 state = kFirstColumn;
219 } else {
220 // state stays kScanComment.
221 }
222 break;
223
224 case kFindName :
225 if (tc == '\n') {
226 state = kFirstColumn;
227 } else if (isspace(tc)) {
228 // state stays kFindName.
229 } else {
230 state = kCollectName;
231 name[ni++] = tc;
232 }
233 break;
234
235 case kCollectName :
236 if (tc == '\n') {
237 name[ni] = 0;
ef8ad44b 238 warnx("Name must be followed by white space - '%s'", name);
1815bff5
A
239 state = kFirstColumn;
240 } else if (isspace(tc)) {
241 state = kFindValue;
242 } else {
243 name[ni++] = tc;
244 // state staus kCollectName.
245 }
246 break;
247
248 case kFindValue :
249 case kContinueValue :
250 if (tc == '\n') {
251 state = kSetenv;
252 } else if (isspace(tc)) {
253 // state stays kFindValue or kContinueValue.
254 } else {
255 state = kCollectValue;
256 value[vi++] = tc;
257 }
258 break;
259
260 case kCollectValue :
261 if (tc == '\n') {
262 if (value[vi-1] == '\\') {
263 value[vi-1] = '\r';
264 state = kContinueValue;
265 } else {
266 state = kSetenv;
267 }
268 } else {
269 // state stays kCollectValue.
270 value[vi++] = tc;
271 }
272 break;
273 }
274
275 if (state == kSetenv) {
276 name[ni] = 0;
277 value[vi] = 0;
ef8ad44b
A
278 if ((kret = SetOFVariable(name, value)) != KERN_SUCCESS) {
279 errx(1, "Error setting variable - '%s': %s", name,
280 mach_error_string(kret));
1815bff5
A
281 }
282 state = kFirstColumn;
283 }
284 }
285
286 if (state != kFirstColumn) {
ef8ad44b 287 errx(1, "Last line ended abruptly");
1815bff5
A
288 }
289}
290
291
34d340d7
A
292// ParseXMLFile(fileName)
293//
294// Open and parse the specified file in XML format,
295// and set variables appropriately.
296//
297static void ParseXMLFile(char *fileName)
298{
299 CFPropertyListRef plist;
300 CFURLRef fileURL = NULL;
301 CFStringRef filePath = NULL;
302 CFStringRef errorString = NULL;
303 CFDataRef data = NULL;
304 SInt32 errorCode = 0;
305
306 filePath = CFStringCreateWithCString(kCFAllocatorDefault, fileName, kCFStringEncodingUTF8);
307 if (filePath == NULL) {
ef8ad44b 308 errx(1, "Could not create file path string");
34d340d7
A
309 }
310
311 // Create a URL that specifies the file we will create to
312 // hold the XML data.
313 fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
314 filePath,
315 kCFURLPOSIXPathStyle,
316 false /* not a directory */ );
317 if (fileURL == NULL) {
ef8ad44b 318 errx(1, "Could not create file path URL");
34d340d7
A
319 }
320
321 CFRelease(filePath);
322
323 if (! CFURLCreateDataAndPropertiesFromResource(
324 kCFAllocatorDefault,
325 fileURL,
326 &data,
327 NULL,
328 NULL,
329 &errorCode) || data == NULL ) {
8459d725 330 errx(1, "Error reading XML file (%d)", (int)errorCode);
34d340d7
A
331 }
332
333 CFRelease(fileURL);
334
335 plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
336 data,
337 kCFPropertyListImmutable,
338 &errorString);
339
340 CFRelease(data);
341
342 if (plist == NULL) {
ef8ad44b 343 errx(1, "Error parsing XML file");
34d340d7
A
344 }
345
346 if (errorString != NULL) {
ef8ad44b 347 errx(1, "Error parsing XML file: %s", CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8));
34d340d7
A
348 }
349
350 CFDictionaryApplyFunction(plist, &SetOFVariableFromFile, 0);
351
352 CFRelease(plist);
353}
354
1815bff5
A
355// SetOrGetOFVariable(str)
356//
2fc1e207 357// Parse the input string, then set or get the specified
4c00c0ae 358// firmware variable.
1815bff5
A
359//
360static void SetOrGetOFVariable(char *str)
361{
362 long set = 0;
363 char *name;
364 char *value;
365 CFStringRef nameRef;
366 CFTypeRef valueRef;
367 kern_return_t result;
368
369 // OF variable name is first.
370 name = str;
371
372 // Find the equal sign for set
373 while (*str) {
374 if (*str == '=') {
375 set = 1;
376 *str++ = '\0';
377 break;
378 }
379 str++;
380 }
381
382 if (set == 1) {
383 // On sets, the OF variable's value follows the equal sign.
384 value = str;
385
386 result = SetOFVariable(name, value);
8459d725 387 NVRamSyncNow(name); /* Try syncing the new data to device, best effort! */
1815bff5 388 if (result != KERN_SUCCESS) {
ef8ad44b
A
389 errx(1, "Error setting variable - '%s': %s", name,
390 mach_error_string(result));
1815bff5
A
391 }
392 } else {
393 result = GetOFVariable(name, &nameRef, &valueRef);
394 if (result != KERN_SUCCESS) {
ef8ad44b
A
395 errx(1, "Error getting variable - '%s': %s", name,
396 mach_error_string(result));
1815bff5
A
397 }
398
399 PrintOFVariable(nameRef, valueRef, 0);
400 CFRelease(nameRef);
401 CFRelease(valueRef);
402 }
403}
404
405
406// GetOFVariable(name, nameRef, valueRef)
407//
4c00c0ae 408// Get the named firmware variable.
1815bff5
A
409// Return it and it's symbol in valueRef and nameRef.
410//
411static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef,
412 CFTypeRef *valueRef)
413{
414 *nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name,
2fc1e207 415 kCFStringEncodingUTF8);
1815bff5 416 if (*nameRef == 0) {
ef8ad44b 417 errx(1, "Error creating CFString for key %s", name);
1815bff5
A
418 }
419
420 *valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, *nameRef, 0, 0);
ef8ad44b 421 if (*valueRef == 0) return kIOReturnNotFound;
1815bff5
A
422
423 return KERN_SUCCESS;
424}
425
426
427// SetOFVariable(name, value)
428//
4c00c0ae 429// Set or create an firmware variable with name and value.
1815bff5
A
430//
431static kern_return_t SetOFVariable(char *name, char *value)
432{
433 CFStringRef nameRef;
434 CFTypeRef valueRef;
435 CFTypeID typeID;
ef8ad44b 436 kern_return_t result = KERN_SUCCESS;
1815bff5
A
437
438 nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name,
2fc1e207 439 kCFStringEncodingUTF8);
1815bff5 440 if (nameRef == 0) {
ef8ad44b 441 errx(1, "Error creating CFString for key %s", name);
1815bff5
A
442 }
443
444 valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, nameRef, 0, 0);
445 if (valueRef) {
446 typeID = CFGetTypeID(valueRef);
447 CFRelease(valueRef);
20e66415
A
448
449 valueRef = ConvertValueToCFTypeRef(typeID, value);
450 if (valueRef == 0) {
ef8ad44b 451 errx(1, "Error creating CFTypeRef for value %s", value);
20e66415
A
452 } result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef);
453 } else {
454 while (1) {
455 // In the default case, try data, string, number, then boolean.
456
457 valueRef = ConvertValueToCFTypeRef(CFDataGetTypeID(), value);
458 if (valueRef != 0) {
459 result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef);
460 if (result == KERN_SUCCESS) break;
461 }
462
463 valueRef = ConvertValueToCFTypeRef(CFStringGetTypeID(), value);
464 if (valueRef != 0) {
465 result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef);
466 if (result == KERN_SUCCESS) break;
467 }
468
469 valueRef = ConvertValueToCFTypeRef(CFNumberGetTypeID(), value);
470 if (valueRef != 0) {
471 result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef);
472 if (result == KERN_SUCCESS) break;
473 }
474
475 valueRef = ConvertValueToCFTypeRef(CFBooleanGetTypeID(), value);
476 if (valueRef != 0) {
477 result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef);
478 if (result == KERN_SUCCESS) break;
479 }
480
20e66415
A
481 break;
482 }
1815bff5
A
483 }
484
1815bff5
A
485 CFRelease(nameRef);
486
487 return result;
488}
489
490
83f6dbe8
A
491// DeleteOFVariable(name)
492//
4c00c0ae 493// Delete the named firmware variable.
83f6dbe8
A
494//
495//
496static void DeleteOFVariable(char *name)
497{
498 SetOFVariable(kIONVRAMDeletePropertyKey, name);
499}
500
8459d725
A
501static void NVRamSyncNow(char *name)
502{
503 SetOFVariable(kIONVRAMSyncNowPropertyKey, name);
504}
83f6dbe8 505
1815bff5
A
506// PrintOFVariables()
507//
4c00c0ae 508// Print all of the firmware variables.
1815bff5
A
509//
510static void PrintOFVariables()
511{
512 kern_return_t result;
513 CFMutableDictionaryRef dict;
514
515 result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0);
516 if (result != KERN_SUCCESS) {
ef8ad44b 517 errx(1, "Error getting the firmware variables: %s", mach_error_string(result));
1815bff5 518 }
34d340d7
A
519
520 if (gUseXML) {
521 CFDataRef data;
522
523 data = CFPropertyListCreateXMLData( kCFAllocatorDefault, dict );
524 if (data == NULL) {
ef8ad44b 525 errx(1, "Error converting variables to xml");
34d340d7
A
526 }
527
528 fwrite(CFDataGetBytePtr(data), sizeof(UInt8), CFDataGetLength(data), stdout);
529
530 CFRelease(data);
531
532 } else {
533
534 CFDictionaryApplyFunction(dict, &PrintOFVariable, 0);
535
536 }
1815bff5
A
537
538 CFRelease(dict);
539}
540
1815bff5
A
541// PrintOFVariable(key, value, context)
542//
4c00c0ae 543// Print the given firmware variable.
1815bff5
A
544//
545static void PrintOFVariable(const void *key, const void *value, void *context)
546{
547 long cnt, cnt2;
2fc1e207
A
548 CFIndex nameLen;
549 char *nameBuffer = 0;
1815bff5
A
550 const char *nameString;
551 char numberBuffer[10];
b51d5b5f
A
552 const uint8_t *dataPtr;
553 uint8_t dataChar;
1815bff5 554 char *dataBuffer = 0;
2fc1e207
A
555 CFIndex valueLen;
556 char *valueBuffer = 0;
b51d5b5f
A
557 const char *valueString = 0;
558 uint32_t number, length;
1815bff5
A
559 CFTypeID typeID;
560
561 // Get the OF variable's name.
2fc1e207
A
562 nameLen = CFStringGetLength(key) + 1;
563 nameBuffer = malloc(nameLen);
564 if( nameBuffer && CFStringGetCString(key, nameBuffer, nameLen, kCFStringEncodingUTF8) )
565 nameString = nameBuffer;
566 else {
ef8ad44b 567 warnx("Unable to convert property name to C string");
2fc1e207
A
568 nameString = "<UNPRINTABLE>";
569 }
1815bff5
A
570
571 // Get the OF variable's type.
572 typeID = CFGetTypeID(value);
573
2fc1e207 574 if (typeID == CFBooleanGetTypeID()) {
1815bff5
A
575 if (CFBooleanGetValue(value)) valueString = "true";
576 else valueString = "false";
577 } else if (typeID == CFNumberGetTypeID()) {
578 CFNumberGetValue(value, kCFNumberSInt32Type, &number);
579 if (number == 0xFFFFFFFF) sprintf(numberBuffer, "-1");
580 else if (number < 1000) sprintf(numberBuffer, "%d", number);
581 else sprintf(numberBuffer, "0x%x", number);
582 valueString = numberBuffer;
583 } else if (typeID == CFStringGetTypeID()) {
2fc1e207
A
584 valueLen = CFStringGetLength(value) + 1;
585 valueBuffer = malloc(valueLen + 1);
586 if ( valueBuffer && CFStringGetCString(value, valueBuffer, valueLen, kCFStringEncodingUTF8) )
587 valueString = valueBuffer;
588 else {
ef8ad44b 589 warnx("Unable to convert value to C string");
2fc1e207
A
590 valueString = "<UNPRINTABLE>";
591 }
1815bff5
A
592 } else if (typeID == CFDataGetTypeID()) {
593 length = CFDataGetLength(value);
594 if (length == 0) valueString = "";
595 else {
596 dataBuffer = malloc(length * 3 + 1);
597 if (dataBuffer != 0) {
598 dataPtr = CFDataGetBytePtr(value);
599 for (cnt = cnt2 = 0; cnt < length; cnt++) {
600 dataChar = dataPtr[cnt];
1a7e3f61
A
601 if (isprint(dataChar) && dataChar != '%') {
602 dataBuffer[cnt2++] = dataChar;
603 } else {
1815bff5
A
604 sprintf(dataBuffer + cnt2, "%%%02x", dataChar);
605 cnt2 += 3;
606 }
607 }
608 dataBuffer[cnt2] = '\0';
609 valueString = dataBuffer;
610 }
611 }
2fc1e207
A
612 } else {
613 valueString="<INVALID>";
614 }
1815bff5
A
615
616 if ((nameString != 0) && (valueString != 0))
617 printf("%s\t%s\n", nameString, valueString);
618
619 if (dataBuffer != 0) free(dataBuffer);
2fc1e207
A
620 if (nameBuffer != 0) free(nameBuffer);
621 if (valueBuffer != 0) free(valueBuffer);
1815bff5
A
622}
623
34d340d7
A
624// ClearOFVariables()
625//
626// Deletes all OF variables
627//
628static void ClearOFVariables(void)
629{
630 kern_return_t result;
631 CFMutableDictionaryRef dict;
632
633 result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0);
634 if (result != KERN_SUCCESS) {
ef8ad44b 635 errx(1, "Error getting the firmware variables: %s", mach_error_string(result));
34d340d7
A
636 }
637 CFDictionaryApplyFunction(dict, &ClearOFVariable, 0);
638
639 CFRelease(dict);
640}
641
642static void ClearOFVariable(const void *key, const void *value, void *context)
643{
644 kern_return_t result;
645 result = IORegistryEntrySetCFProperty(gOptionsRef,
646 CFSTR(kIONVRAMDeletePropertyKey), key);
647 if (result != KERN_SUCCESS) {
ef8ad44b 648 errx(1, "Error clearing firmware variables: %s", mach_error_string(result));
34d340d7
A
649 }
650}
1815bff5
A
651
652// ConvertValueToCFTypeRef(typeID, value)
653//
654// Convert the value into a CFType given the typeID.
655//
656static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value)
657{
658 CFTypeRef valueRef = 0;
659 long cnt, cnt2, length;
660 unsigned long number, tmp;
661
662 if (typeID == CFBooleanGetTypeID()) {
663 if (!strcmp("true", value)) valueRef = kCFBooleanTrue;
664 else if (!strcmp("false", value)) valueRef = kCFBooleanFalse;
665 } else if (typeID == CFNumberGetTypeID()) {
666 number = strtol(value, 0, 0);
667 valueRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
668 &number);
669 } else if (typeID == CFStringGetTypeID()) {
670 valueRef = CFStringCreateWithCString(kCFAllocatorDefault, value,
2fc1e207 671 kCFStringEncodingUTF8);
1815bff5
A
672 } else if (typeID == CFDataGetTypeID()) {
673 length = strlen(value);
674 for (cnt = cnt2 = 0; cnt < length; cnt++, cnt2++) {
675 if (value[cnt] == '%') {
676 if (!ishexnumber(value[cnt + 1]) ||
677 !ishexnumber(value[cnt + 2])) return 0;
678 number = toupper(value[++cnt]) - '0';
679 if (number > 9) number -= 7;
680 tmp = toupper(value[++cnt]) - '0';
681 if (tmp > 9) tmp -= 7;
682 number = (number << 4) + tmp;
683 value[cnt2] = number;
684 } else value[cnt2] = value[cnt];
685 }
34d340d7 686 valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)value,
1815bff5
A
687 cnt2, kCFAllocatorDefault);
688 } else return 0;
689
690 return valueRef;
691}
09fd88e4 692
34d340d7
A
693static void SetOFVariableFromFile(const void *key, const void *value, void *context)
694{
695 kern_return_t result;
696
697 result = IORegistryEntrySetCFProperty(gOptionsRef, key, value);
698 if ( result != KERN_SUCCESS ) {
699 int nameLen;
700 char *nameBuffer;
701 char *nameString;
702
703 // Get the variable's name.
704 nameLen = CFStringGetLength(key) + 1;
705 nameBuffer = malloc(nameLen);
706 if( nameBuffer && CFStringGetCString(key, nameBuffer, nameLen, kCFStringEncodingUTF8) )
707 nameString = nameBuffer;
708 else {
ef8ad44b 709 warnx("Unable to convert property name to C string");
34d340d7
A
710 nameString = "<UNPRINTABLE>";
711 }
ef8ad44b
A
712 errx(1, "Error setting variable - '%s': %s", nameString,
713 mach_error_string(result));
34d340d7
A
714 }
715}