2 * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 cc -o nvram nvram.c -framework CoreFoundation -framework IOKit -Wall
27 #include <IOKit/IOKitLib.h>
28 #include <IOKit/IOKitKeys.h>
29 #include <IOKit/IOKitKeysPrivate.h>
30 #include <CoreFoundation/CoreFoundation.h>
32 #include <mach/mach_error.h>
36 static void UsageMessage(const char *message
);
37 static void ParseFile(const char *fileName
);
38 static void ParseXMLFile(const char *fileName
);
39 static void SetOrGetOFVariable(char *str
);
40 static kern_return_t
GetOFVariable(const char *name
, CFStringRef
*nameRef
,
42 static kern_return_t
SetOFVariable(const char *name
, const char *value
);
43 static void DeleteOFVariable(const char *name
);
44 static void PrintOFVariables(void);
45 static void PrintOFVariable(const void *key
,const void *value
,void *context
);
46 static void SetOFVariableFromFile(const void *key
, const void *value
, void *context
);
47 static void ClearOFVariables(void);
48 static void ClearOFVariable(const void *key
,const void *value
,void *context
);
49 static CFTypeRef
ConvertValueToCFTypeRef(CFTypeID typeID
, const char *value
);
51 static void NVRamSyncNow(void);
54 static io_registry_entry_t gOptionsRef
;
55 static io_registry_entry_t gSystemOptionsRef
;
56 static io_registry_entry_t gSelectedOptionsRef
;
58 static bool gUseForceSync
;
60 #if TARGET_OS_BRIDGE /* Stuff for nvram bridge -> intel */
62 #include <libMacEFIManager/MacEFIHostInterfaceAPI.h>
64 static kern_return_t
LinkMacNVRAMSymbols(void);
65 static kern_return_t
GetMacOFVariable(char *name
, char **value
);
66 static kern_return_t
SetMacOFVariable(char *name
, char *value
);
67 static kern_return_t
DeleteMacOFVariable(char *name
);
69 static bool gBridgeToIntel
;
70 static void *gDL_handle
;
71 static void *gNvramInterface
;
73 static void (*hostInterfaceInitialize_fptr
)(void);
74 static void *(*createNvramHostInterface_fptr
)(const char *handle
);
75 static kern_return_t (*destroyNvramHostInterface_fptr
)(void *interface
);
76 static kern_return_t (*getNVRAMVariable_fptr
)(void *interface
, char *name
, char **buffer
, uint32_t *size
);
77 static kern_return_t (*setNVRAMVariable_fptr
)(void *interface
, char *name
, char *buffer
);
78 static kern_return_t (*deleteNVRAMVariable_fptr
)(void *interface
, char *name
);
79 static void (*hostInterfaceDeinitialize_fptr
)(void); /* may not need? */
81 #endif /* TARGET_OS_BRIDGE */
83 int main(int argc
, char **argv
)
86 char *str
, errorMessage
[256];
88 mach_port_t masterPort
;
91 result
= IOMasterPort(bootstrap_port
, &masterPort
);
92 if (result
!= KERN_SUCCESS
) {
93 errx(1, "Error getting the IOMaster port: %s",
94 mach_error_string(result
));
97 gOptionsRef
= IORegistryEntryFromPath(masterPort
, "IODeviceTree:/options");
98 if (gOptionsRef
== 0) {
99 errx(1, "nvram is not supported on this system");
102 gSystemOptionsRef
= IORegistryEntryFromPath(masterPort
, "IOService:/options/options-system");
104 gSelectedOptionsRef
= gOptionsRef
;
106 for (cnt
= 1; cnt
< argc
; cnt
++) {
108 if (str
[0] == '-' && str
[1] != 0) {
109 // Parse the options.
110 for (str
+= 1 ; *str
; str
++) {
114 if (gBridgeToIntel
) {
115 fprintf(stderr
, "-p not supported for Mac NVRAM store.\n");
128 if (gBridgeToIntel
) {
129 fprintf(stderr
, "-f not supported for Mac NVRAM store.\n");
134 if (cnt
< argc
&& *argv
[cnt
] != '-') {
135 ParseFile(argv
[cnt
]);
137 UsageMessage("missing filename");
143 if (cnt
< argc
&& *argv
[cnt
] != '-') {
145 if (gBridgeToIntel
) {
146 if ((result
= DeleteMacOFVariable(argv
[cnt
])) != KERN_SUCCESS
) {
147 errx(1, "Error deleting variable - '%s': %s (0x%08x)", argv
[cnt
],
148 mach_error_string(result
), result
);
154 DeleteOFVariable(argv
[cnt
]);
157 UsageMessage("missing name");
163 if (gBridgeToIntel
) {
164 fprintf(stderr
, "-c not supported for Mac NVRAM store.\n");
171 // -s option is unadvertised -- advises the kernel more forcibly to
172 // commit the variable to nonvolatile storage
173 gUseForceSync
= true;
177 // used to set nvram variables on the Intel side
178 // from the ARM side (Bridge -> Mac)
179 fprintf(stdout
, "Using Mac NVRAM store.\n");
181 LinkMacNVRAMSymbols();
182 gBridgeToIntel
= true;
187 // -z option is unadvertised -- attempts to use the options-system node
188 // to write to the system NVRAM region if available
189 if (gSystemOptionsRef
) {
190 fprintf(stderr
, "Selecting options-system node.\n");
191 gSelectedOptionsRef
= gSystemOptionsRef
;
193 fprintf(stderr
, "No options-system node, using options.\n");
198 strcpy(errorMessage
, "no such option as --");
199 errorMessage
[strlen(errorMessage
)-1] = *str
;
200 UsageMessage(errorMessage
);
204 // Other arguments will be firmware variable requests.
206 SetOrGetOFVariable(str
);
211 if (argcount
== 0 && gUseForceSync
== true) {
215 IOObjectRelease(gOptionsRef
);
217 if (gSystemOptionsRef
) {
218 IOObjectRelease(gSystemOptionsRef
);
224 // UsageMessage(message)
226 // Print the usage information and exit.
228 static void UsageMessage(const char *message
)
230 warnx("(usage: %s)", message
);
232 printf("nvram [-x] [-p] [-f filename] [-d name] [-c] name[=value] ...\n");
233 printf("\t-x use XML format for printing or reading variables\n");
234 printf("\t (must appear before -p or -f)\n");
235 printf("\t-p print all firmware variables\n");
236 printf("\t-f set firmware variables from a text file\n");
237 printf("\t-d delete the named variable\n");
238 printf("\t-c delete all variables\n");
240 printf("\t-m set nvram variables on macOS from bridgeOS\n");
242 printf("\tname=value set named variable\n");
243 printf("\tname print variable\n");
244 printf("Note that arguments and options are executed in order.\n");
250 // States for ParseFile.
261 kMaxStringSize
= 0x800,
266 // ParseFile(fileName)
268 // Open and parse the specified file.
270 static void ParseFile(const char *fileName
)
272 long state
, ni
= 0, vi
= 0;
274 char name
[kMaxNameSize
];
275 char value
[kMaxStringSize
];
280 ParseXMLFile(fileName
);
284 patches
= fopen(fileName
, "r");
286 err(1, "Couldn't open patch file - '%s'", fileName
);
289 state
= kFirstColumn
;
290 while ((tc
= getc(patches
)) != EOF
) {
291 if(ni
==(kMaxNameSize
-1))
292 errx(1, "Name exceeded max length of %d", kMaxNameSize
);
293 if(vi
==(kMaxStringSize
-1))
294 errx(1, "Value exceeded max length of %d", kMaxStringSize
);
300 state
= kScanComment
;
301 } else if (tc
== '\n') {
302 // state stays kFirstColumn.
303 } else if (isspace(tc
)) {
306 state
= kCollectName
;
313 state
= kFirstColumn
;
315 // state stays kScanComment.
321 state
= kFirstColumn
;
322 } else if (isspace(tc
)) {
323 // state stays kFindName.
325 state
= kCollectName
;
333 warnx("Name must be followed by white space - '%s'", name
);
334 state
= kFirstColumn
;
335 } else if (isspace(tc
)) {
339 // state staus kCollectName.
344 case kContinueValue
:
347 } else if (isspace(tc
)) {
348 // state stays kFindValue or kContinueValue.
350 state
= kCollectValue
;
357 if (value
[vi
-1] == '\\') {
359 state
= kContinueValue
;
364 // state stays kCollectValue.
370 if (state
== kSetenv
) {
373 if ((kret
= SetOFVariable(name
, value
)) != KERN_SUCCESS
) {
374 errx(1, "Error setting variable - '%s': %s", name
,
375 mach_error_string(kret
));
377 state
= kFirstColumn
;
381 if (state
!= kFirstColumn
) {
382 errx(1, "Last line ended abruptly");
386 // ParseXMLFile(fileName)
388 // Open and parse the specified file in XML format,
389 // and set variables appropriately.
391 static void ParseXMLFile(const char *fileName
)
393 CFPropertyListRef plist
;
397 CFReadStreamRef stream
;
398 CFPropertyListFormat format
= kCFPropertyListBinaryFormat_v1_0
;
400 fd
= open(fileName
, O_RDONLY
| O_NOFOLLOW
, S_IFREG
);
402 errx(1, "Could not open %s: %s", fileName
, strerror(errno
));
405 if (fstat(fd
, &sb
) == -1) {
406 errx(1, "Could not fstat %s: %s", fileName
, strerror(errno
));
409 if (sb
.st_size
> UINT32_MAX
) {
410 errx(1, "too big for our purposes");
413 buffer
= malloc((size_t)sb
.st_size
);
414 if (buffer
== NULL
) {
415 errx(1, "Could not allocate buffer");
418 if (read(fd
, buffer
, (size_t)sb
.st_size
) != sb
.st_size
) {
419 errx(1, "Could not read %s: %s", fileName
, strerror(errno
));
424 stream
= CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault
,
425 (const UInt8
*)buffer
,
428 if (stream
== NULL
) {
429 errx(1, "Could not create stream from serialized data");
432 if (!CFReadStreamOpen(stream
)) {
433 errx(1, "Could not open the stream");
436 plist
= CFPropertyListCreateWithStream(kCFAllocatorDefault
,
439 kCFPropertyListImmutable
,
444 errx(1, "Error parsing XML file");
447 CFReadStreamClose(stream
);
453 CFDictionaryApplyFunction(plist
, &SetOFVariableFromFile
, 0);
458 // SetOrGetOFVariable(str)
460 // Parse the input string, then set, append or get
461 // the specified firmware variable.
463 static void SetOrGetOFVariable(char *str
)
469 CFStringRef nameRef
= NULL
;
470 CFTypeRef valueRef
= NULL
;
471 CFMutableStringRef appended
= NULL
;
472 kern_return_t result
;
474 // OF variable name is first.
477 // Find the equal sign for set or += for append
479 if (*str
== '+' && *(str
+1) == '=') {
494 // Read the current value if appending or if no =/+=
495 if (append
== 1 || (set
== 0 && append
== 0)) {
497 if (gBridgeToIntel
) {
498 result
= GetMacOFVariable(name
, &value
);
499 if (result
!= KERN_SUCCESS
) {
500 errx(1, "Error getting variable - '%s': %s", name
,
501 mach_error_string(result
));
503 nameRef
= CFStringCreateWithCString(kCFAllocatorDefault
, name
, kCFStringEncodingUTF8
);
504 valueRef
= CFStringCreateWithCString(kCFAllocatorDefault
, value
, kCFStringEncodingUTF8
);
510 result
= GetOFVariable(name
, &nameRef
, &valueRef
);
511 if (result
!= KERN_SUCCESS
) {
512 errx(1, "Error getting variable - '%s': %s", name
,
513 mach_error_string(result
));
519 // On sets, the OF variable's value follows the equal sign.
524 // On append, the value to append follows the += substring
525 appended
= CFStringCreateMutableCopy(NULL
, 0, valueRef
);
526 CFStringAppendCString(appended
, str
, kCFStringEncodingUTF8
);
527 value
= (char*)CFStringGetCStringPtr(appended
, kCFStringEncodingUTF8
);
530 if (set
== 1 || append
== 1) {
532 if (gBridgeToIntel
) {
533 result
= SetMacOFVariable(name
, value
);
538 result
= SetOFVariable(name
, value
);
539 /* Try syncing the new data to device, best effort! */
542 if (result
!= KERN_SUCCESS
) {
543 errx(1, "Error setting variable - '%s': %s", name
,
544 mach_error_string(result
));
547 PrintOFVariable(nameRef
, valueRef
, 0);
549 if (nameRef
) CFRelease(nameRef
);
550 if (valueRef
) CFRelease(valueRef
);
551 if (appended
) CFRelease(appended
);
555 static kern_return_t
LinkMacNVRAMSymbols()
557 gDL_handle
= dlopen("libMacEFIHostInterface.dylib", RTLD_LAZY
);
558 if (gDL_handle
== NULL
) {
559 errx(errno
, "Failed to dlopen libMacEFIHostInterface.dylib");
560 return KERN_FAILURE
; /* NOTREACHED */
563 hostInterfaceInitialize_fptr
= dlsym(gDL_handle
, "hostInterfaceInitialize");
564 if (hostInterfaceInitialize_fptr
== NULL
) {
565 errx(errno
, "failed to link hostInterfaceInitialize");
567 createNvramHostInterface_fptr
= dlsym(gDL_handle
, "createNvramHostInterface");
568 if (createNvramHostInterface_fptr
== NULL
) {
569 errx(errno
, "failed to link createNvramHostInterface");
571 destroyNvramHostInterface_fptr
= dlsym(gDL_handle
, "destroyNvramHostInterface");
572 if (destroyNvramHostInterface_fptr
== NULL
) {
573 errx(errno
, "failed to link destroyNvramHostInterface");
575 getNVRAMVariable_fptr
= dlsym(gDL_handle
, "getNVRAMVariable");
576 if (getNVRAMVariable_fptr
== NULL
) {
577 errx(errno
, "failed to link getNVRAMVariable");
579 setNVRAMVariable_fptr
= dlsym(gDL_handle
, "setNVRAMVariable");
580 if (setNVRAMVariable_fptr
== NULL
) {
581 errx(errno
, "failed to link setNVRAMVariable");
583 deleteNVRAMVariable_fptr
= dlsym(gDL_handle
, "deleteNVRAMVariable");
584 if (deleteNVRAMVariable_fptr
== NULL
) {
585 errx(errno
, "failed to link deleteNVRAMVariable");
587 hostInterfaceDeinitialize_fptr
= dlsym(gDL_handle
, "hostInterfaceDeinitialize");
588 if (hostInterfaceDeinitialize_fptr
== NULL
) {
589 errx(errno
, "failed to link hostInterfaceDeinitialize");
592 /* also do the initialization */
593 hostInterfaceInitialize_fptr();
594 gNvramInterface
= createNvramHostInterface_fptr(NULL
);
600 // GetOFVariable(name, nameRef, valueRef)
602 // Get the named firmware variable.
603 // Return it and it's symbol in valueRef and nameRef.
605 static kern_return_t
GetOFVariable(const char *name
, CFStringRef
*nameRef
,
608 *nameRef
= CFStringCreateWithCString(kCFAllocatorDefault
, name
,
609 kCFStringEncodingUTF8
);
611 errx(1, "Error creating CFString for key %s", name
);
614 *valueRef
= IORegistryEntryCreateCFProperty(gSelectedOptionsRef
, *nameRef
, 0, 0);
615 if (*valueRef
== 0) return kIOReturnNotFound
;
621 // GetMacOFVariable(name, value)
623 // Get the named firmware variable from the Intel side.
624 // Return the value in value
626 static kern_return_t
GetMacOFVariable(char *name
, char **value
)
630 return getNVRAMVariable_fptr(gNvramInterface
, name
, value
, &value_size
);
634 // SetOFVariable(name, value)
636 // Set or create an firmware variable with name and value.
638 static kern_return_t
SetOFVariable(const char *name
, const char *value
)
643 kern_return_t result
= KERN_SUCCESS
;
645 nameRef
= CFStringCreateWithCString(kCFAllocatorDefault
, name
,
646 kCFStringEncodingUTF8
);
648 errx(1, "Error creating CFString for key %s", name
);
651 valueRef
= IORegistryEntryCreateCFProperty(gSelectedOptionsRef
, nameRef
, 0, 0);
653 typeID
= CFGetTypeID(valueRef
);
656 valueRef
= ConvertValueToCFTypeRef(typeID
, value
);
658 errx(1, "Error creating CFTypeRef for value %s", value
);
659 } result
= IORegistryEntrySetCFProperty(gSelectedOptionsRef
, nameRef
, valueRef
);
662 // In the default case, try data, string, number, then boolean.
664 valueRef
= ConvertValueToCFTypeRef(CFDataGetTypeID(), value
);
666 result
= IORegistryEntrySetCFProperty(gSelectedOptionsRef
, nameRef
, valueRef
);
667 if (result
== KERN_SUCCESS
) break;
670 valueRef
= ConvertValueToCFTypeRef(CFStringGetTypeID(), value
);
672 result
= IORegistryEntrySetCFProperty(gSelectedOptionsRef
, nameRef
, valueRef
);
673 if (result
== KERN_SUCCESS
) break;
676 valueRef
= ConvertValueToCFTypeRef(CFNumberGetTypeID(), value
);
678 result
= IORegistryEntrySetCFProperty(gSelectedOptionsRef
, nameRef
, valueRef
);
679 if (result
== KERN_SUCCESS
) break;
682 valueRef
= ConvertValueToCFTypeRef(CFBooleanGetTypeID(), value
);
684 result
= IORegistryEntrySetCFProperty(gSelectedOptionsRef
, nameRef
, valueRef
);
685 if (result
== KERN_SUCCESS
) break;
698 static kern_return_t
SetMacOFVariable(char *name
, char *value
)
700 return setNVRAMVariable_fptr(gNvramInterface
, name
, value
);
704 // DeleteOFVariable(name)
706 // Delete the named firmware variable.
708 static void DeleteOFVariable(const char *name
)
710 SetOFVariable(kIONVRAMDeletePropertyKey
, name
);
714 static kern_return_t
DeleteMacOFVariable(char *name
)
716 return deleteNVRAMVariable_fptr(gNvramInterface
, name
);
720 static void NVRamSyncNow(void)
722 if (!gUseForceSync
) {
723 SetOFVariable(kIONVRAMSyncNowPropertyKey
, kIONVRAMSyncNowPropertyKey
);
725 SetOFVariable(kIONVRAMForceSyncNowPropertyKey
, kIONVRAMForceSyncNowPropertyKey
);
729 // PrintOFVariables()
731 // Print all of the firmware variables.
733 static void PrintOFVariables(void)
735 kern_return_t result
;
736 CFMutableDictionaryRef dict
;
738 result
= IORegistryEntryCreateCFProperties(gSelectedOptionsRef
, &dict
, 0, 0);
739 if (result
!= KERN_SUCCESS
) {
740 errx(1, "Error getting the firmware variables: %s", mach_error_string(result
));
746 data
= CFPropertyListCreateData( kCFAllocatorDefault
, dict
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
748 errx(1, "Error converting variables to xml");
751 fwrite(CFDataGetBytePtr(data
), sizeof(UInt8
), CFDataGetLength(data
), stdout
);
757 CFDictionaryApplyFunction(dict
, &PrintOFVariable
, 0);
764 // PrintOFVariable(key, value, context)
766 // Print the given firmware variable.
768 static void PrintOFVariable(const void *key
, const void *value
, void *context
)
772 char *nameBuffer
= 0;
773 const char *nameString
;
774 char numberBuffer
[10];
775 const uint8_t *dataPtr
;
777 char *dataBuffer
= 0;
779 char *valueBuffer
= 0;
780 const char *valueString
= 0;
787 CFDictionaryRef dict
= CFDictionaryCreate(kCFAllocatorDefault
, &key
, &value
, 1,
788 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
790 errx(1, "Error creating dictionary for variable value");
793 data
= CFPropertyListCreateData( kCFAllocatorDefault
, dict
, kCFPropertyListXMLFormat_v1_0
, 0, NULL
);
795 errx(1, "Error creating xml plist for variable");
798 fwrite(CFDataGetBytePtr(data
), sizeof(UInt8
), CFDataGetLength(data
), stdout
);
805 // Get the OF variable's name.
806 nameLen
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(key
),
807 kCFStringEncodingUTF8
) + 1;
808 nameBuffer
= malloc(nameLen
);
809 if( nameBuffer
&& CFStringGetCString(key
, nameBuffer
, nameLen
, kCFStringEncodingUTF8
) )
810 nameString
= nameBuffer
;
812 warnx("Unable to convert property name to C string");
813 nameString
= "<UNPRINTABLE>";
816 // Get the OF variable's type.
817 typeID
= CFGetTypeID(value
);
819 if (typeID
== CFBooleanGetTypeID()) {
820 if (CFBooleanGetValue(value
)) valueString
= "true";
821 else valueString
= "false";
822 } else if (typeID
== CFNumberGetTypeID()) {
823 CFNumberGetValue(value
, kCFNumberSInt32Type
, &number
);
824 if (number
== 0xFFFFFFFF) sprintf(numberBuffer
, "-1");
825 else if (number
< 1000) sprintf(numberBuffer
, "%d", number
);
826 else sprintf(numberBuffer
, "0x%x", number
);
827 valueString
= numberBuffer
;
828 } else if (typeID
== CFStringGetTypeID()) {
829 valueLen
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(value
),
830 kCFStringEncodingUTF8
) + 1;
831 valueBuffer
= malloc(valueLen
+ 1);
832 if ( valueBuffer
&& CFStringGetCString(value
, valueBuffer
, valueLen
, kCFStringEncodingUTF8
) )
833 valueString
= valueBuffer
;
835 warnx("Unable to convert value to C string");
836 valueString
= "<UNPRINTABLE>";
838 } else if (typeID
== CFDataGetTypeID()) {
839 length
= CFDataGetLength(value
);
840 if (length
== 0) valueString
= "";
842 dataBuffer
= malloc(length
* 3 + 1);
843 if (dataBuffer
!= 0) {
844 dataPtr
= CFDataGetBytePtr(value
);
845 for (cnt
= cnt2
= 0; cnt
< length
; cnt
++) {
846 dataChar
= dataPtr
[cnt
];
847 if (isprint(dataChar
) && dataChar
!= '%') {
848 dataBuffer
[cnt2
++] = dataChar
;
850 sprintf(dataBuffer
+ cnt2
, "%%%02x", dataChar
);
854 dataBuffer
[cnt2
] = '\0';
855 valueString
= dataBuffer
;
859 valueString
="<INVALID>";
862 if ((nameString
!= 0) && (valueString
!= 0))
863 printf("%s\t%s\n", nameString
, valueString
);
865 if (dataBuffer
!= 0) free(dataBuffer
);
866 if (nameBuffer
!= 0) free(nameBuffer
);
867 if (valueBuffer
!= 0) free(valueBuffer
);
870 // ClearOFVariables()
872 // Deletes all OF variables
874 static void ClearOFVariables(void)
876 kern_return_t result
;
877 CFMutableDictionaryRef dict
;
879 result
= IORegistryEntryCreateCFProperties(gSelectedOptionsRef
, &dict
, 0, 0);
880 if (result
!= KERN_SUCCESS
) {
881 errx(1, "Error getting the firmware variables: %s", mach_error_string(result
));
883 CFDictionaryApplyFunction(dict
, &ClearOFVariable
, 0);
888 static void ClearOFVariable(const void *key
, const void *value
, void *context
)
890 kern_return_t result
;
891 result
= IORegistryEntrySetCFProperty(gSelectedOptionsRef
,
892 CFSTR(kIONVRAMDeletePropertyKey
), key
);
893 if (result
!= KERN_SUCCESS
) {
894 assert(CFGetTypeID(key
) == CFStringGetTypeID());
895 const char *keyStr
= CFStringGetCStringPtr(key
, kCFStringEncodingUTF8
);
896 char *keyBuffer
= NULL
;
897 size_t keyBufferLen
= 0;
899 keyBufferLen
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(key
), kCFStringEncodingUTF8
) + 1;
900 keyBuffer
= (char *)malloc(keyBufferLen
);
901 if (keyBuffer
!= NULL
&& CFStringGetCString(key
, keyBuffer
, keyBufferLen
, kCFStringEncodingUTF8
)) {
904 warnx("Unable to convert property name to C string");
905 keyStr
= "<UNPRINTABLE>";
909 warnx("Error clearing firmware variable %s: %s", keyStr
, mach_error_string(result
));
916 // ConvertValueToCFTypeRef(typeID, value)
918 // Convert the value into a CFType given the typeID.
920 static CFTypeRef
ConvertValueToCFTypeRef(CFTypeID typeID
, const char *value
)
922 CFTypeRef valueRef
= 0;
923 long cnt
, cnt2
, length
;
924 unsigned long number
, tmp
;
926 if (typeID
== CFBooleanGetTypeID()) {
927 if (!strcmp("true", value
)) valueRef
= kCFBooleanTrue
;
928 else if (!strcmp("false", value
)) valueRef
= kCFBooleanFalse
;
929 } else if (typeID
== CFNumberGetTypeID()) {
930 number
= strtol(value
, 0, 0);
931 valueRef
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
,
933 } else if (typeID
== CFStringGetTypeID()) {
934 valueRef
= CFStringCreateWithCString(kCFAllocatorDefault
, value
,
935 kCFStringEncodingUTF8
);
936 } else if (typeID
== CFDataGetTypeID()) {
937 length
= strlen(value
);
938 char valueCopy
[length
+ 1];
940 for (cnt
= cnt2
= 0; cnt
< length
; cnt
++, cnt2
++) {
941 if (value
[cnt
] == '%') {
942 if ((cnt
+ 2 > length
) ||
943 !ishexnumber(value
[cnt
+ 1]) ||
944 !ishexnumber(value
[cnt
+ 2])) return 0;
945 number
= toupper(value
[++cnt
]) - '0';
946 if (number
> 9) number
-= 7;
947 tmp
= toupper(value
[++cnt
]) - '0';
948 if (tmp
> 9) tmp
-= 7;
949 number
= (number
<< 4) + tmp
;
950 valueCopy
[cnt2
] = number
;
951 } else valueCopy
[cnt2
] = value
[cnt
];
953 valueRef
= CFDataCreate(kCFAllocatorDefault
, (const UInt8
*)valueCopy
, cnt2
);
959 static void SetOFVariableFromFile(const void *key
, const void *value
, void *context
)
961 kern_return_t result
;
963 result
= IORegistryEntrySetCFProperty(gSelectedOptionsRef
, key
, value
);
964 if ( result
!= KERN_SUCCESS
) {
969 // Get the variable's name.
970 nameLen
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(key
),
971 kCFStringEncodingUTF8
) + 1;
972 nameBuffer
= malloc(nameLen
);
973 if( nameBuffer
&& CFStringGetCString(key
, nameBuffer
, nameLen
, kCFStringEncodingUTF8
) )
974 nameString
= nameBuffer
;
976 warnx("Unable to convert property name to C string");
977 nameString
= "<UNPRINTABLE>";
979 errx(1, "Error setting variable - '%s': %s", nameString
,
980 mach_error_string(result
));