X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/9726c1377126b4aeb5693fd4c32d17dafc8c4d7e..530d02b6d6489eaa76ff9853c2897b2dc48d2d8e:/nvram.tproj/nvram.c diff --git a/nvram.tproj/nvram.c b/nvram.tproj/nvram.c index fc6a24a..3711499 100644 --- a/nvram.tproj/nvram.c +++ b/nvram.tproj/nvram.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2016 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * @@ -30,6 +30,7 @@ cc -o nvram nvram.c -framework CoreFoundation -framework IOKit -Wall #include #include #include +#include // Prototypes static void UsageMessage(char *message); @@ -55,6 +56,27 @@ 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) { @@ -62,23 +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) { errx(1, "Error getting the IOMaster port: %s", mach_error_string(result)); } - + gOptionsRef = IORegistryEntryFromPath(masterPort, "IODeviceTree:/options"); if (gOptionsRef == 0) { errx(1, "nvram is not supported on this system"); } - + for (cnt = 1; cnt < argc; cnt++) { str = argv[cnt]; if (str[0] == '-' && str[1] != 0) { @@ -86,6 +109,12 @@ 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; @@ -94,6 +123,12 @@ int main(int argc, char **argv) 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]); @@ -101,8 +136,14 @@ 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]); @@ -110,8 +151,14 @@ int main(int argc, char **argv) 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': @@ -119,6 +166,17 @@ int main(int argc, char **argv) // 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; @@ -127,12 +185,18 @@ int main(int argc, char **argv) } } else { // Other arguments will be firmware variable requests. + argcount++; SetOrGetOFVariable(str); } } - + + // radar:25206371 + if (argcount == 0 && gUseForceSync == true) { + NVRamSyncNow(""); + } + IOObjectRelease(gOptionsRef); - + return 0; } @@ -143,7 +207,7 @@ int main(int argc, char **argv) static void UsageMessage(char *message) { 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"); @@ -154,7 +218,7 @@ static void UsageMessage(char *message) 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); } @@ -169,7 +233,7 @@ enum { kCollectValue, kContinueValue, kSetenv, - + kMaxStringSize = 0x800, kMaxNameSize = 0x100 }; @@ -181,7 +245,8 @@ 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; @@ -191,15 +256,15 @@ static void ParseFile(char *fileName) ParseXMLFile(fileName); return; } - + patches = fopen(fileName, "r"); if (patches == 0) { err(1, "Couldn't open patch file - '%s'", fileName); } - + state = kFirstColumn; while ((tc = getc(patches)) != EOF) { - if(ni==(kMaxNameSize-1)) + 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); @@ -218,7 +283,7 @@ static void ParseFile(char *fileName) name[ni++] = tc; } break; - + case kScanComment : if (tc == '\n') { state = kFirstColumn; @@ -226,7 +291,7 @@ static void ParseFile(char *fileName) // state stays kScanComment. } break; - + case kFindName : if (tc == '\n') { state = kFirstColumn; @@ -237,7 +302,7 @@ static void ParseFile(char *fileName) name[ni++] = tc; } break; - + case kCollectName : if (tc == '\n') { name[ni] = 0; @@ -250,7 +315,7 @@ static void ParseFile(char *fileName) // state staus kCollectName. } break; - + case kFindValue : case kContinueValue : if (tc == '\n') { @@ -262,7 +327,7 @@ static void ParseFile(char *fileName) value[vi++] = tc; } break; - + case kCollectValue : if (tc == '\n') { if (value[vi-1] == '\\') { @@ -277,7 +342,7 @@ static void ParseFile(char *fileName) } break; } - + if (state == kSetenv) { name[ni] = 0; value[vi] = 0; @@ -288,13 +353,12 @@ static void ParseFile(char *fileName) state = kFirstColumn; } } - + if (state != kFirstColumn) { errx(1, "Last line ended abruptly"); } } - // ParseXMLFile(fileName) // // Open and parse the specified file in XML format, @@ -303,55 +367,64 @@ static void ParseFile(char *fileName) 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"); + 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)); } - // 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"); + if (sb.st_size > UINT32_MAX) { + errx(1, "too big for our purposes"); } - CFRelease(filePath); + buffer = malloc((size_t)sb.st_size); + if (buffer == NULL) { + errx(1, "Could not allocate buffer"); + } - if (! CFURLCreateDataAndPropertiesFromResource( - kCFAllocatorDefault, - fileURL, - &data, - NULL, - NULL, - &errorCode) || data == NULL ) { - errx(1, "Error reading XML file (%d)", (int)errorCode); + if (read(fd, buffer, (size_t)sb.st_size) != sb.st_size) { + errx(1, "Could not read %s: %s", fileName, strerror(errno)); } - CFRelease(fileURL); + close(fd); - plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, - data, - kCFPropertyListImmutable, - &errorString); + stream = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, + (const UInt8 *)buffer, + (CFIndex)sb.st_size, + kCFAllocatorNull); + if (stream == NULL) { + errx(1, "Could not create stream from serialized data"); + } - CFRelease(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"); } - if (errorString != NULL) { - errx(1, "Error parsing XML file: %s", CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8)); - } + CFReadStreamClose(stream); + + CFRelease(stream); + + free(buffer); CFDictionaryApplyFunction(plist, &SetOFVariableFromFile, 0); @@ -371,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 == '=') { @@ -384,30 +457,92 @@ 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); - NVRamSyncNow(name); /* Try syncing the new data to device, best effort! */ +#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) { errx(1, "Error setting variable - '%s': %s", name, mach_error_string(result)); } } else { - result = GetOFVariable(name, &nameRef, &valueRef); - if (result != KERN_SUCCESS) { - errx(1, "Error getting variable - '%s': %s", name, - mach_error_string(result)); +#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) // @@ -422,13 +557,30 @@ static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef, if (*nameRef == 0) { errx(1, "Error creating CFString for key %s", name); } - + *valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, *nameRef, 0, 0); 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) // @@ -440,70 +592,88 @@ static kern_return_t SetOFVariable(char *name, char *value) CFTypeRef valueRef; CFTypeID typeID; kern_return_t result = KERN_SUCCESS; - + nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingUTF8); if (nameRef == 0) { 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) { 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; } - + 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) { @@ -517,11 +687,11 @@ static void NVRamSyncNow(char *name) // // 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) { errx(1, "Error getting the firmware variables: %s", mach_error_string(result)); @@ -530,7 +700,7 @@ static void PrintOFVariables() if (gUseXML) { CFDataRef data; - data = CFPropertyListCreateXMLData( kCFAllocatorDefault, dict ); + data = CFPropertyListCreateData( kCFAllocatorDefault, dict, kCFPropertyListXMLFormat_v1_0, 0, NULL ); if (data == NULL) { errx(1, "Error converting variables to xml"); } @@ -544,7 +714,7 @@ static void PrintOFVariables() CFDictionaryApplyFunction(dict, &PrintOFVariable, 0); } - + CFRelease(dict); } @@ -565,9 +735,30 @@ static void PrintOFVariable(const void *key, const void *value, void *context) 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. nameLen = CFStringGetLength(key) + 1; nameBuffer = malloc(nameLen); @@ -577,10 +768,10 @@ static void PrintOFVariable(const void *key, const void *value, void *context) warnx("Unable to convert property name to C string"); nameString = ""; } - + // Get the OF variable's type. typeID = CFGetTypeID(value); - + if (typeID == CFBooleanGetTypeID()) { if (CFBooleanGetValue(value)) valueString = "true"; else valueString = "false"; @@ -622,10 +813,10 @@ static void PrintOFVariable(const void *key, const void *value, void *context) } 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); @@ -668,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; @@ -696,7 +887,7 @@ static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value) valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)value, cnt2, kCFAllocatorDefault); } else return 0; - + return valueRef; } @@ -706,7 +897,7 @@ static void SetOFVariableFromFile(const void *key, const void *value, void *cont result = IORegistryEntrySetCFProperty(gOptionsRef, key, value); if ( result != KERN_SUCCESS ) { - int nameLen; + long nameLen; char *nameBuffer; char *nameString;