X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/c3a08f5910a028cdace032ed79beb406c750d530..c00fdd175635bfca33c58d1b2951a1565ce91f17:/nvram.tproj/nvram.c diff --git a/nvram.tproj/nvram.c b/nvram.tproj/nvram.c index eabcdb9..3711499 100644 --- a/nvram.tproj/nvram.c +++ b/nvram.tproj/nvram.c @@ -1,52 +1,82 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * + * The contents of this file constitute Original Code as defined in and + * are subject to the Apple Public Source License Version 1.1 (the + * "License"). You may not use this file except in compliance with the + * License. Please obtain a copy of the License at + * http://www.apple.com/publicsource and read it before using this file. + * + * This Original Code and all software distributed under the License are + * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License. + * * @APPLE_LICENSE_HEADER_END@ */ /* -cc -o nvram nvram.c -framework IOKit -Wall +cc -o nvram nvram.c -framework CoreFoundation -framework IOKit -Wall */ #include #include +#include +#include #include +#include +#include +#include // Prototypes -static void Error(char *format, long item); -static void FatalError(long exitValue, char *format, long item); static void UsageMessage(char *message); static void ParseFile(char *fileName); +static void ParseXMLFile(char *fileName); static void SetOrGetOFVariable(char *str); static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef, CFTypeRef *valueRef); static kern_return_t SetOFVariable(char *name, char *value); +static void DeleteOFVariable(char *name); static void PrintOFVariables(void); static void PrintOFVariable(const void *key,const void *value,void *context); +static void SetOFVariableFromFile(const void *key, const void *value, void *context); +static void ClearOFVariables(void); +static void ClearOFVariable(const void *key,const void *value,void *context); static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value); +static void NVRamSyncNow(char *name); + // Global Variables static char *gToolName; static io_registry_entry_t gOptionsRef; +static bool gUseXML; +static bool gUseForceSync; + +#if TARGET_OS_BRIDGE /* Stuff for nvram bridge -> intel */ +#include +#include + +static kern_return_t LinkMacNVRAMSymbols(void); +static kern_return_t GetMacOFVariable(char *name, char **value); +static kern_return_t SetMacOFVariable(char *name, char *value); +static void DeleteMacOFVariable(char *name); +static bool gBridgeToIntel; +static void *gDL_handle; +static void *gNvramInterface; + +static void (*hostInterfaceInitialize_fptr)(void); +static void *(*createNvramHostInterface_fptr)(const char *handle); +static kern_return_t (*destroyNvramHostInterface_fptr)(void *interface); +static kern_return_t (*getNVRAMVariable_fptr)(void *interface, char *name, char **buffer, uint32_t *size); +static kern_return_t (*setNVRAMVariable_fptr)(void *interface, char *name, char *buffer, uint32_t size); +static void (*hostInterfaceDeinitialize_fptr)(void); /* may not need? */ + +#endif /* TARGET_OS_BRIDGE */ int main(int argc, char **argv) { @@ -54,24 +84,24 @@ int main(int argc, char **argv) char *str, errorMessage[256]; kern_return_t result; mach_port_t masterPort; - + int argcount = 0; + // Get the name of the command. gToolName = strrchr(argv[0], '/'); if (gToolName != 0) gToolName++; else gToolName = argv[0]; - + result = IOMasterPort(bootstrap_port, &masterPort); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (%d) getting the IOMaster port", result); - exit(-1); + errx(1, "Error getting the IOMaster port: %s", + mach_error_string(result)); } - + gOptionsRef = IORegistryEntryFromPath(masterPort, "IODeviceTree:/options"); if (gOptionsRef == 0) { - FatalError(-1, "Error (%d) getting a reference to /options", -1); - exit(-1); + errx(1, "nvram is not supported on this system"); } - + for (cnt = 1; cnt < argc; cnt++) { str = argv[cnt]; if (str[0] == '-' && str[1] != 0) { @@ -79,10 +109,26 @@ int main(int argc, char **argv) for (str += 1 ; *str; str++) { switch (*str) { case 'p' : +#if TARGET_OS_BRIDGE + if (gBridgeToIntel) { + fprintf(stderr, "-p not supported for Mac NVRAM store.\n"); + return 1; + } +#endif PrintOFVariables(); break; - + + case 'x' : + gUseXML = true; + break; + case 'f': +#if TARGET_OS_BRIDGE + if (gBridgeToIntel) { + fprintf(stderr, "-f not supported for Mac NVRAM store.\n"); + return 1; + } +#endif cnt++; if (cnt < argc && *argv[cnt] != '-') { ParseFile(argv[cnt]); @@ -90,7 +136,47 @@ int main(int argc, char **argv) UsageMessage("missing filename"); } break; - + + case 'd': +#if TARGET_OS_BRIDGE + if (gBridgeToIntel) { + fprintf(stderr, "-d not supported for Mac NVRAM store.\n"); + return 1; + } +#endif + cnt++; + if (cnt < argc && *argv[cnt] != '-') { + DeleteOFVariable(argv[cnt]); + } else { + UsageMessage("missing name"); + } + break; + + case 'c': +#if TARGET_OS_BRIDGE + if (gBridgeToIntel) { + fprintf(stderr, "-c not supported for Mac NVRAM store.\n"); + return 1; + } +#endif + ClearOFVariables(); + break; + case 's': + // -s option is unadvertised -- advises the kernel more forcibly to + // commit the variable to nonvolatile storage + gUseForceSync = true; + break; +#if TARGET_OS_BRIDGE + case 'm': + // -m option is unadvertised -- used to set nvram variables on the Intel side + // from the ARM side (Bridge -> Mac) + fprintf(stdout, "Using Mac NVRAM store.\n"); + + LinkMacNVRAMSymbols(); + gBridgeToIntel = true; + break; +#endif + default: strcpy(errorMessage, "no such option as --"); errorMessage[strlen(errorMessage)-1] = *str; @@ -98,58 +184,41 @@ int main(int argc, char **argv) } } } else { - // Other arguments will be Open Firmware variable requests. + // Other arguments will be firmware variable requests. + argcount++; SetOrGetOFVariable(str); } } - - IOObjectRelease(gOptionsRef); - - return 0; -} - -// Error(format, item) -// -// Print a message on standard error. -// -static void Error(char *format, long item) -{ - fprintf(stderr, "%s: ", gToolName); - fprintf(stderr, format, item); - fprintf(stderr, "\n"); -} + // radar:25206371 + if (argcount == 0 && gUseForceSync == true) { + NVRamSyncNow(""); + } + IOObjectRelease(gOptionsRef); -// FatalError(exitValue, format, item) -// -// Print a message on standard error and exit with value. -// -static void FatalError(long exitValue, char *format, long item) -{ - fprintf(stderr, "%s: ", gToolName); - fprintf(stderr, format, item); - fprintf(stderr, "\n"); - - exit(exitValue); + return 0; } - // UsageMessage(message) // // Print the usage information and exit. // static void UsageMessage(char *message) { - Error("(usage: %s)", (long)message); - - printf("%s [-p] [-f filename] name[=value] ...\n", gToolName); - printf("\t-p print all Open Firmware variables\n"); - printf("\t-f set Open Firmware variables from a text file\n"); + warnx("(usage: %s)", message); + + printf("%s [-x] [-p] [-f filename] [-d name] [-c] name[=value] ...\n", gToolName); + printf("\t-x use XML format for printing or reading variables\n"); + printf("\t (must appear before -p or -f)\n"); + printf("\t-p print all firmware variables\n"); + printf("\t-f set firmware variables from a text file\n"); + printf("\t-d delete the named variable\n"); + printf("\t-c delete all variables\n"); printf("\tname=value set named variable\n"); printf("\tname print variable\n"); printf("Note that arguments and options are executed in order.\n"); - + exit(1); } @@ -164,7 +233,7 @@ enum { kCollectValue, kContinueValue, kSetenv, - + kMaxStringSize = 0x800, kMaxNameSize = 0x100 }; @@ -176,18 +245,29 @@ enum { // static void ParseFile(char *fileName) { - long state, tc, ni = 0, vi = 0; + long state, ni = 0, vi = 0; + int tc; char name[kMaxNameSize]; char value[kMaxStringSize]; FILE *patches; - + kern_return_t kret; + + if (gUseXML) { + ParseXMLFile(fileName); + return; + } + patches = fopen(fileName, "r"); if (patches == 0) { - FatalError(errno, "Couldn't open patch file - '%s'", (long)fileName); + err(1, "Couldn't open patch file - '%s'", fileName); } - + state = kFirstColumn; while ((tc = getc(patches)) != EOF) { + if(ni==(kMaxNameSize-1)) + errx(1, "Name exceeded max length of %d", kMaxNameSize); + if(vi==(kMaxStringSize-1)) + errx(1, "Value exceeded max length of %d", kMaxStringSize); switch (state) { case kFirstColumn : ni = 0; @@ -203,7 +283,7 @@ static void ParseFile(char *fileName) name[ni++] = tc; } break; - + case kScanComment : if (tc == '\n') { state = kFirstColumn; @@ -211,7 +291,7 @@ static void ParseFile(char *fileName) // state stays kScanComment. } break; - + case kFindName : if (tc == '\n') { state = kFirstColumn; @@ -222,11 +302,11 @@ static void ParseFile(char *fileName) name[ni++] = tc; } break; - + case kCollectName : if (tc == '\n') { name[ni] = 0; - Error("Name must be followed by white space - '%s'", (long)name); + warnx("Name must be followed by white space - '%s'", name); state = kFirstColumn; } else if (isspace(tc)) { state = kFindValue; @@ -235,7 +315,7 @@ static void ParseFile(char *fileName) // state staus kCollectName. } break; - + case kFindValue : case kContinueValue : if (tc == '\n') { @@ -247,7 +327,7 @@ static void ParseFile(char *fileName) value[vi++] = tc; } break; - + case kCollectValue : if (tc == '\n') { if (value[vi-1] == '\\') { @@ -262,27 +342,99 @@ static void ParseFile(char *fileName) } break; } - + if (state == kSetenv) { name[ni] = 0; value[vi] = 0; - if (SetOFVariable(name, value) != KERN_SUCCESS) { - FatalError(-1, "Error (-1) setting variable - '%s'", (long)name); + if ((kret = SetOFVariable(name, value)) != KERN_SUCCESS) { + errx(1, "Error setting variable - '%s': %s", name, + mach_error_string(kret)); } state = kFirstColumn; } } - + if (state != kFirstColumn) { - FatalError(-1, "Last line ended abruptly", 0); + errx(1, "Last line ended abruptly"); } } +// ParseXMLFile(fileName) +// +// Open and parse the specified file in XML format, +// and set variables appropriately. +// +static void ParseXMLFile(char *fileName) +{ + CFPropertyListRef plist; + int fd; + struct stat sb; + char *buffer; + CFReadStreamRef stream; + CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0; + + fd = open(fileName, O_RDONLY | O_NOFOLLOW, S_IFREG); + if (fd == -1) { + errx(1, "Could not open %s: %s", fileName, strerror(errno)); + } + + if (fstat(fd, &sb) == -1) { + errx(1, "Could not fstat %s: %s", fileName, strerror(errno)); + } + + if (sb.st_size > UINT32_MAX) { + errx(1, "too big for our purposes"); + } + + buffer = malloc((size_t)sb.st_size); + if (buffer == NULL) { + errx(1, "Could not allocate buffer"); + } + + if (read(fd, buffer, (size_t)sb.st_size) != sb.st_size) { + errx(1, "Could not read %s: %s", fileName, strerror(errno)); + } + + close(fd); + + stream = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, + (const UInt8 *)buffer, + (CFIndex)sb.st_size, + kCFAllocatorNull); + if (stream == NULL) { + errx(1, "Could not create stream from serialized data"); + } + + if (!CFReadStreamOpen(stream)) { + errx(1, "Could not open the stream"); + } + + plist = CFPropertyListCreateWithStream(kCFAllocatorDefault, + stream, + (CFIndex)sb.st_size, + kCFPropertyListImmutable, + &format, + NULL); + + if (plist == NULL) { + errx(1, "Error parsing XML file"); + } + + CFReadStreamClose(stream); + + CFRelease(stream); + + free(buffer); + + CFDictionaryApplyFunction(plist, &SetOFVariableFromFile, 0); + + CFRelease(plist); +} // SetOrGetOFVariable(str) // -// Parse the input string the set or get the specified -// Open Firmware variable. +// Parse the input string, then set or get the specified +// firmware variable. // static void SetOrGetOFVariable(char *str) { @@ -292,10 +444,10 @@ static void SetOrGetOFVariable(char *str) CFStringRef nameRef; CFTypeRef valueRef; kern_return_t result; - + // OF variable name is first. name = str; - + // Find the equal sign for set while (*str) { if (*str == '=') { @@ -305,156 +457,322 @@ static void SetOrGetOFVariable(char *str) } str++; } - + if (set == 1) { // On sets, the OF variable's value follows the equal sign. value = str; - - result = SetOFVariable(name, value); +#if TARGET_OS_BRIDGE + if (gBridgeToIntel) { + result = SetMacOFVariable(name, value); + } + else +#endif + { + result = SetOFVariable(name, value); + NVRamSyncNow(name); /* Try syncing the new data to device, best effort! */ + } if (result != KERN_SUCCESS) { - FatalError(-1, "Error (-1) setting variable - '%s'", (long)name); + errx(1, "Error setting variable - '%s': %s", name, + mach_error_string(result)); } } else { - result = GetOFVariable(name, &nameRef, &valueRef); - if (result != KERN_SUCCESS) { - FatalError(-1, "Error (-1) getting variable - '%s'", (long)name); +#if TARGET_OS_BRIDGE + if (gBridgeToIntel) { + result = GetMacOFVariable(name, &value); + if (result != KERN_SUCCESS) { + errx(1, "Error getting variable - '%s': %s", name, + mach_error_string(result)); + } + nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); + valueRef = CFStringCreateWithCString(kCFAllocatorDefault, value, kCFStringEncodingUTF8); } - + else +#endif + { + result = GetOFVariable(name, &nameRef, &valueRef); + if (result != KERN_SUCCESS) { + errx(1, "Error getting variable - '%s': %s", name, + mach_error_string(result)); + } + } + PrintOFVariable(nameRef, valueRef, 0); CFRelease(nameRef); CFRelease(valueRef); } } +#if TARGET_OS_BRIDGE +static kern_return_t LinkMacNVRAMSymbols() +{ + gDL_handle = dlopen("libMacEFIHostInterface.dylib", RTLD_LAZY); + if (gDL_handle == NULL) { + errx(errno, "Failed to dlopen libMacEFIHostInterface.dylib"); + return KERN_FAILURE; /* NOTREACHED */ + } + + hostInterfaceInitialize_fptr = dlsym(gDL_handle, "hostInterfaceInitialize"); + if (hostInterfaceInitialize_fptr == NULL) { + errx(errno, "failed to link hostInterfaceInitialize"); + } + createNvramHostInterface_fptr = dlsym(gDL_handle, "createNvramHostInterface"); + if (createNvramHostInterface_fptr == NULL) { + errx(errno, "failed to link createNvramHostInterface"); + } + destroyNvramHostInterface_fptr = dlsym(gDL_handle, "destroyNvramHostInterface"); + if (destroyNvramHostInterface_fptr == NULL) { + errx(errno, "failed to link destroyNvramHostInterface"); + } + getNVRAMVariable_fptr = dlsym(gDL_handle, "getNVRAMVariable"); + if (getNVRAMVariable_fptr == NULL) { + errx(errno, "failed to link getNVRAMVariable"); + } + setNVRAMVariable_fptr = dlsym(gDL_handle, "setNVRAMVariable"); + if (setNVRAMVariable_fptr == NULL) { + errx(errno, "failed to link setNVRAMVariable"); + } + hostInterfaceDeinitialize_fptr = dlsym(gDL_handle, "hostInterfaceDeinitialize"); + if (hostInterfaceDeinitialize_fptr == NULL) { + errx(errno, "failed to link hostInterfaceDeinitialize"); + } + + /* also do the initialization */ + hostInterfaceInitialize_fptr(); + gNvramInterface = createNvramHostInterface_fptr(NULL); + + return KERN_SUCCESS; +} +#endif // GetOFVariable(name, nameRef, valueRef) // -// Get the named Open Firmware variable. +// Get the named firmware variable. // Return it and it's symbol in valueRef and nameRef. // static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef, CFTypeRef *valueRef) { *nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, - kCFStringEncodingMacRoman); + kCFStringEncodingUTF8); if (*nameRef == 0) { - FatalError(-1, "Error CFString for key %s", (long)name); + errx(1, "Error creating CFString for key %s", name); } - + *valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, *nameRef, 0, 0); - if (*valueRef == 0) return -1; - + if (*valueRef == 0) return kIOReturnNotFound; + return KERN_SUCCESS; } +#if TARGET_OS_BRIDGE +// GetMacOFVariable(name, value) +// +// Get the named firmware variable from the Intel side. +// Return the value in value +// +static kern_return_t GetMacOFVariable(char *name, char **value) +{ + uint32_t value_size; + kern_return_t result = KERN_FAILURE; + assert(getNVRAMVariable_fptr != NULL); + + result = getNVRAMVariable_fptr(gNvramInterface, name, value, &value_size); + + return result; +} +#endif // SetOFVariable(name, value) // -// Set or create an Open Firmware variable with name and value. +// Set or create an firmware variable with name and value. // static kern_return_t SetOFVariable(char *name, char *value) { CFStringRef nameRef; CFTypeRef valueRef; CFTypeID typeID; - kern_return_t result; - + kern_return_t result = KERN_SUCCESS; + nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, - kCFStringEncodingMacRoman); + kCFStringEncodingUTF8); if (nameRef == 0) { - FatalError(-1, "Error (-1) creating CFString for key %s", (long)name); + errx(1, "Error creating CFString for key %s", name); } - + valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, nameRef, 0, 0); if (valueRef) { typeID = CFGetTypeID(valueRef); CFRelease(valueRef); - + valueRef = ConvertValueToCFTypeRef(typeID, value); if (valueRef == 0) { - FatalError(-1, "Error (-1) creating CFTypeRef for value %s",(long)value); + errx(1, "Error creating CFTypeRef for value %s", value); } result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); } else { while (1) { - // In the default case, try data, string, number, then boolean. - + // In the default case, try data, string, number, then boolean. + valueRef = ConvertValueToCFTypeRef(CFDataGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - + valueRef = ConvertValueToCFTypeRef(CFStringGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - + valueRef = ConvertValueToCFTypeRef(CFNumberGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - + valueRef = ConvertValueToCFTypeRef(CFBooleanGetTypeID(), value); if (valueRef != 0) { result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef); if (result == KERN_SUCCESS) break; } - - result = -1; + break; } } - + CFRelease(nameRef); - + + return result; +} + +#if TARGET_OS_BRIDGE +static kern_return_t SetMacOFVariable(char *name, char *value) +{ + kern_return_t result = KERN_FAILURE; + assert(setNVRAMVariable_fptr != NULL); + + result = setNVRAMVariable_fptr(gNvramInterface, name, value, strlen(value)); + return result; } +#endif + +// DeleteOFVariable(name) +// +// Delete the named firmware variable. +// +// +static void DeleteOFVariable(char *name) +{ + SetOFVariable(kIONVRAMDeletePropertyKey, name); +} + +#if TARGET_OS_BRIDGE +static void DeleteMacOFVariable(char *name) +{ + /* Not yet implementable */ +} +#endif +static void NVRamSyncNow(char *name) +{ + if (!gUseForceSync) { + SetOFVariable(kIONVRAMSyncNowPropertyKey, name); + } else { + SetOFVariable(kIONVRAMForceSyncNowPropertyKey, name); + } +} // PrintOFVariables() // -// Print all of the Open Firmware variables. +// Print all of the firmware variables. // -static void PrintOFVariables() +static void PrintOFVariables(void) { kern_return_t result; CFMutableDictionaryRef dict; - + result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0); if (result != KERN_SUCCESS) { - FatalError(-1, "Error (%d) getting the Open Firmware variables", result); + errx(1, "Error getting the firmware variables: %s", mach_error_string(result)); } - CFDictionaryApplyFunction(dict, &PrintOFVariable, 0); - + + if (gUseXML) { + CFDataRef data; + + data = CFPropertyListCreateData( kCFAllocatorDefault, dict, kCFPropertyListXMLFormat_v1_0, 0, NULL ); + if (data == NULL) { + errx(1, "Error converting variables to xml"); + } + + fwrite(CFDataGetBytePtr(data), sizeof(UInt8), CFDataGetLength(data), stdout); + + CFRelease(data); + + } else { + + CFDictionaryApplyFunction(dict, &PrintOFVariable, 0); + + } + CFRelease(dict); } - // PrintOFVariable(key, value, context) // -// Print the given Open Firmware variable. +// Print the given firmware variable. // static void PrintOFVariable(const void *key, const void *value, void *context) { long cnt, cnt2; + CFIndex nameLen; + char *nameBuffer = 0; const char *nameString; char numberBuffer[10]; const uint8_t *dataPtr; uint8_t dataChar; char *dataBuffer = 0; + CFIndex valueLen; + char *valueBuffer = 0; const char *valueString = 0; - uint32_t number, length; + uint32_t number; + long length; CFTypeID typeID; - + + if (gUseXML) { + CFDataRef data; + CFDictionaryRef dict = CFDictionaryCreate(kCFAllocatorDefault, &key, &value, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + if (dict == NULL) { + errx(1, "Error creating dictionary for variable value"); + } + + data = CFPropertyListCreateData( kCFAllocatorDefault, dict, kCFPropertyListXMLFormat_v1_0, 0, NULL ); + if (data == NULL) { + errx(1, "Error creating xml plist for variable"); + } + + fwrite(CFDataGetBytePtr(data), sizeof(UInt8), CFDataGetLength(data), stdout); + + CFRelease(dict); + CFRelease(data); + return; + } + // Get the OF variable's name. - nameString = CFStringGetCStringPtr(key, kCFStringEncodingMacRoman); - + nameLen = CFStringGetLength(key) + 1; + nameBuffer = malloc(nameLen); + if( nameBuffer && CFStringGetCString(key, nameBuffer, nameLen, kCFStringEncodingUTF8) ) + nameString = nameBuffer; + else { + warnx("Unable to convert property name to C string"); + nameString = ""; + } + // Get the OF variable's type. typeID = CFGetTypeID(value); - - if (typeID == CFBooleanGetTypeID()) { + + if (typeID == CFBooleanGetTypeID()) { if (CFBooleanGetValue(value)) valueString = "true"; else valueString = "false"; } else if (typeID == CFNumberGetTypeID()) { @@ -464,7 +782,14 @@ static void PrintOFVariable(const void *key, const void *value, void *context) else sprintf(numberBuffer, "0x%x", number); valueString = numberBuffer; } else if (typeID == CFStringGetTypeID()) { - valueString = CFStringGetCStringPtr(value, kCFStringEncodingMacRoman); + valueLen = CFStringGetLength(value) + 1; + valueBuffer = malloc(valueLen + 1); + if ( valueBuffer && CFStringGetCString(value, valueBuffer, valueLen, kCFStringEncodingUTF8) ) + valueString = valueBuffer; + else { + warnx("Unable to convert value to C string"); + valueString = ""; + } } else if (typeID == CFDataGetTypeID()) { length = CFDataGetLength(value); if (length == 0) valueString = ""; @@ -474,8 +799,9 @@ static void PrintOFVariable(const void *key, const void *value, void *context) dataPtr = CFDataGetBytePtr(value); for (cnt = cnt2 = 0; cnt < length; cnt++) { dataChar = dataPtr[cnt]; - if (isprint(dataChar)) dataBuffer[cnt2++] = dataChar; - else { + if (isprint(dataChar) && dataChar != '%') { + dataBuffer[cnt2++] = dataChar; + } else { sprintf(dataBuffer + cnt2, "%%%02x", dataChar); cnt2 += 3; } @@ -484,14 +810,45 @@ static void PrintOFVariable(const void *key, const void *value, void *context) valueString = dataBuffer; } } - } else return; - + } else { + valueString=""; + } + if ((nameString != 0) && (valueString != 0)) printf("%s\t%s\n", nameString, valueString); - + if (dataBuffer != 0) free(dataBuffer); + if (nameBuffer != 0) free(nameBuffer); + if (valueBuffer != 0) free(valueBuffer); } +// ClearOFVariables() +// +// Deletes all OF variables +// +static void ClearOFVariables(void) +{ + kern_return_t result; + CFMutableDictionaryRef dict; + + result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0); + if (result != KERN_SUCCESS) { + errx(1, "Error getting the firmware variables: %s", mach_error_string(result)); + } + CFDictionaryApplyFunction(dict, &ClearOFVariable, 0); + + CFRelease(dict); +} + +static void ClearOFVariable(const void *key, const void *value, void *context) +{ + kern_return_t result; + result = IORegistryEntrySetCFProperty(gOptionsRef, + CFSTR(kIONVRAMDeletePropertyKey), key); + if (result != KERN_SUCCESS) { + errx(1, "Error clearing firmware variables: %s", mach_error_string(result)); + } +} // ConvertValueToCFTypeRef(typeID, value) // @@ -502,7 +859,7 @@ static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value) CFTypeRef valueRef = 0; long cnt, cnt2, length; unsigned long number, tmp; - + if (typeID == CFBooleanGetTypeID()) { if (!strcmp("true", value)) valueRef = kCFBooleanTrue; else if (!strcmp("false", value)) valueRef = kCFBooleanFalse; @@ -512,7 +869,7 @@ static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value) &number); } else if (typeID == CFStringGetTypeID()) { valueRef = CFStringCreateWithCString(kCFAllocatorDefault, value, - kCFStringEncodingMacRoman); + kCFStringEncodingUTF8); } else if (typeID == CFDataGetTypeID()) { length = strlen(value); for (cnt = cnt2 = 0; cnt < length; cnt++, cnt2++) { @@ -527,9 +884,33 @@ static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value) value[cnt2] = number; } else value[cnt2] = value[cnt]; } - valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, value, + valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)value, cnt2, kCFAllocatorDefault); } else return 0; - + return valueRef; } + +static void SetOFVariableFromFile(const void *key, const void *value, void *context) +{ + kern_return_t result; + + result = IORegistryEntrySetCFProperty(gOptionsRef, key, value); + if ( result != KERN_SUCCESS ) { + long nameLen; + char *nameBuffer; + char *nameString; + + // Get the variable's name. + nameLen = CFStringGetLength(key) + 1; + nameBuffer = malloc(nameLen); + if( nameBuffer && CFStringGetCString(key, nameBuffer, nameLen, kCFStringEncodingUTF8) ) + nameString = nameBuffer; + else { + warnx("Unable to convert property name to C string"); + nameString = ""; + } + errx(1, "Error setting variable - '%s': %s", nameString, + mach_error_string(result)); + } +}