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