/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2012 Apple Computer, 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@
*/
/*
#include <IOKit/IOKitLib.h>
#include <IOKit/IOKitKeys.h>
#include <CoreFoundation/CoreFoundation.h>
+#include <err.h>
+#include <mach/mach_error.h>
// 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 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;
int main(int argc, char **argv)
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++) {
case 'p' :
PrintOFVariables();
break;
-
+
+ case 'x' :
+ gUseXML = true;
+ break;
+
case 'f':
cnt++;
if (cnt < argc && *argv[cnt] != '-') {
}
break;
+ case 'c':
+ ClearOFVariables();
+ break;
+
default:
strcpy(errorMessage, "no such option as --");
errorMessage[strlen(errorMessage)-1] = *str;
}
}
} else {
- // Other arguments will be Open Firmware variable requests.
+ // Other arguments will be firmware variable requests.
SetOrGetOFVariable(str);
}
}
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");
-}
-
-
-// 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);
-}
-
-
// UsageMessage(message)
//
// Print the usage information and exit.
//
static void UsageMessage(char *message)
{
- Error("(usage: %s)", (long)message);
+ warnx("(usage: %s)", message);
- printf("%s [-p] [-f filename] [-d name] 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");
+ 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");
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;
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;
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;
+ CFURLRef fileURL = NULL;
+ CFStringRef filePath = NULL;
+ CFStringRef errorString = NULL;
+ CFDataRef data = NULL;
+ SInt32 errorCode = 0;
+
+ filePath = CFStringCreateWithCString(kCFAllocatorDefault, fileName, kCFStringEncodingUTF8);
+ if (filePath == NULL) {
+ errx(1, "Could not create file path string");
+ }
+
+ // Create a URL that specifies the file we will create to
+ // hold the XML data.
+ fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault,
+ filePath,
+ kCFURLPOSIXPathStyle,
+ false /* not a directory */ );
+ if (fileURL == NULL) {
+ errx(1, "Could not create file path URL");
+ }
+
+ CFRelease(filePath);
+
+ if (! CFURLCreateDataAndPropertiesFromResource(
+ kCFAllocatorDefault,
+ fileURL,
+ &data,
+ NULL,
+ NULL,
+ &errorCode) || data == NULL ) {
+ errx(1, "Error reading XML file (%d)", (int)errorCode);
+ }
+
+ CFRelease(fileURL);
+
+ plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault,
+ data,
+ kCFPropertyListImmutable,
+ &errorString);
+
+ CFRelease(data);
+
+ if (plist == NULL) {
+ errx(1, "Error parsing XML file");
+ }
+
+ if (errorString != NULL) {
+ errx(1, "Error parsing XML file: %s", CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8));
+ }
+
+ 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)
{
value = str;
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);
+ errx(1, "Error getting variable - '%s': %s", name,
+ mach_error_string(result));
}
PrintOFVariable(nameRef, valueRef, 0);
// 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;
}
// 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);
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) {
if (result == KERN_SUCCESS) break;
}
- result = -1;
break;
}
}
// DeleteOFVariable(name)
//
-// Delete the named Open Firmware variable.
+// Delete the named firmware variable.
//
//
static void DeleteOFVariable(char *name)
SetOFVariable(kIONVRAMDeletePropertyKey, name);
}
+static void NVRamSyncNow(char *name)
+{
+ SetOFVariable(kIONVRAMSyncNowPropertyKey, name);
+}
// PrintOFVariables()
//
-// Print all of the Open Firmware variables.
+// Print all of the firmware variables.
//
static void PrintOFVariables()
{
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));
+ }
+
+ if (gUseXML) {
+ CFDataRef data;
+
+ data = CFPropertyListCreateXMLData( kCFAllocatorDefault, dict );
+ 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);
+
}
- 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;
CFTypeID typeID;
// 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 = "<UNPRINTABLE>";
+ }
// 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()) {
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 = "<UNPRINTABLE>";
+ }
} else if (typeID == CFDataGetTypeID()) {
length = CFDataGetLength(value);
if (length == 0) valueString = "";
valueString = dataBuffer;
}
}
- } else return;
+ } else {
+ valueString="<INVALID>";
+ }
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)
//
&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++) {
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 ) {
+ int 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 = "<UNPRINTABLE>";
+ }
+ errx(1, "Error setting variable - '%s': %s", nameString,
+ mach_error_string(result));
+ }
+}