/*++ Copyright (c) 1993-1996 Microsoft Corporation Module Name: nvram.c Abstract: ARC/NV-RAM manipulation routines for 32-bit winnt setup. Also works on boot.ini on i386 machines. Author: Ted Miller (tedm) 19-December-1993 Revision History: --*/ #include "nvram.h" typedef enum { BootVarSystemPartition, BootVarOsLoader, BootVarOsLoadPartition, BootVarOsLoadFilename, BootVarLoadIdentifier, BootVarOsLoadOptions, BootVarCountdown, BootVarMax } BOOT_VARS; PWSTR BootVarNames[BootVarMax] = { L"SYSTEMPARTITION", L"OSLOADER", L"OSLOADPARTITION", L"OSLOADFILENAME", L"LOADIDENTIFIER", L"OSLOADOPTIONS", L"COUNTDOWN" }; PWSTR PaddedBootVarNames[BootVarMax] = { L"SYSTEMPARTITION", L" OSLOADER", L"OSLOADPARTITION", L" OSLOADFILENAME", L" LOADIDENTIFIER", L" OSLOADOPTIONS", L" COUNTDOWN" }; #ifndef i386 // // Helper macro to make object attribute initialization a little cleaner. // #define INIT_OBJA(Obja,UnicodeString,UnicodeText) \ \ RtlInitUnicodeString((UnicodeString),(UnicodeText)); \ \ InitializeObjectAttributes( \ (Obja), \ (UnicodeString), \ OBJ_CASE_INSENSITIVE, \ NULL, \ NULL \ ) BOOL DoSetNvRamVar( IN PWSTR VarName, IN PWSTR VarValue ) { UNICODE_STRING U1,U2; RtlInitUnicodeString(&U1,VarName); RtlInitUnicodeString(&U2,VarValue); return(NT_SUCCESS(NtSetSystemEnvironmentValue(&U1,&U2))); } VOID PrintNvRamVariable( IN PWSTR VariableName, IN PWSTR VariableValue ) { PWSTR pEnd; WCHAR c; BOOL FirstComponent = TRUE; while(*VariableValue) { // // Find the termination of the current component, // which is either a ; or 0. // pEnd = wcschr(VariableValue,L';'); if(!pEnd) { pEnd = wcschr(VariableValue,0); } c = *pEnd; *pEnd = 0; wprintf( L"%s%s %s\n", FirstComponent ? VariableName : L" ", FirstComponent ? L":" : L" ", VariableValue ); *pEnd = c; VariableValue = pEnd + (c ? 1 : 0); FirstComponent = FALSE; } } int _cdecl main( IN int argc, IN char *argv[] ) { DWORD var; UNICODE_STRING UnicodeString; NTSTATUS Status; BOOLEAN OldPriv; WCHAR Buffer[32768]; WCHAR Buffer1[32768]; WCHAR Buffer2[32768]; Status = RtlAdjustPrivilege( SE_SYSTEM_ENVIRONMENT_PRIVILEGE, TRUE, FALSE, &OldPriv ); if(!NT_SUCCESS(Status)) { wprintf(L"Insufficient privilege.\n"); return(0); } if(argc == 1) { for(var=0; var\n",PaddedBootVarNames[var]); } wprintf(L"\n"); } } if((argc == 5) && !lstrcmpiA(argv[1]+1,"set") && !lstrcmpA(argv[3],"=")) { MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED, argv[2], -1, Buffer1, SIZECHARS(Buffer1) ); MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED, argv[4], -1, Buffer2, SIZECHARS(Buffer2) ); printf( "Setting variable %ws to %ws [%s]\n", Buffer1, Buffer2, DoSetNvRamVar(Buffer1,Buffer2) ? "OK" : "Error" ); } return(0); } #else TCHAR LoadID[500]; // load identifier (no quotes) TCHAR CountDown[100]; // countdown timer TCHAR OsLoadOptions[500]; // load options TCHAR OsName[500]; // name of default os TCHAR OsLine[500]; // complete line of os description and options #define STR_BOOTINI TEXT("c:\\boot.ini") #define STR_BOOTLDR TEXT("boot loader") #define STR_TIMEOUT TEXT("timeout") #define STR_DEFAULT TEXT("default") #define STR_OPERATINGSYS TEXT("operating systems") #define STR_NULL TEXT("") // // HandleOption - add option to OsLoadOptions // VOID HandleOption( TCHAR* Option ) { TCHAR SlashOption[200]; TCHAR SlashOptionSlash[200]; // // find out if option already exists // add blank to end to prevent debug from matching debugport // wsprintf( SlashOption, TEXT("/%s "), Option ); wsprintf( SlashOptionSlash, TEXT("/%s/"), Option ); if( wcsstr( OsLoadOptions, SlashOption ) || wcsstr( OsLoadOptions, SlashOptionSlash ) ) { printf("option already exists: %ws\n",Option); } else { // // append option without the trailing blank // printf("added option %ws\n",Option); lstrcat( OsLoadOptions, TEXT("/") ); lstrcat( OsLoadOptions, Option ); } } // // WriteBootIni - update the boot.ini file with our changes // VOID WriteBootIni() { DWORD FileAttr; // // Get file attributes of boot.ini for later restoration // FileAttr= GetFileAttributes( STR_BOOTINI ); // // Change file attributes on boot.ini so we can write to it. // if( !SetFileAttributes( STR_BOOTINI, FILE_ATTRIBUTE_NORMAL ) ) { printf("Failed to turn off read-only on boot.ini (lasterr= %d)\n", GetLastError() ); } // // Update boot.ini strings // if( !WritePrivateProfileString( STR_BOOTLDR, STR_TIMEOUT, CountDown, STR_BOOTINI ) ) { printf("failed to write timeout (lasterr= %d)\n",GetLastError()); } // // create the osline from its parts // wsprintf(OsLine, TEXT("\"%s\"%s"), LoadID, OsLoadOptions ); if( !WritePrivateProfileString( STR_OPERATINGSYS, OsName, OsLine, STR_BOOTINI ) ) { printf("failed to write OS line (lasterr= %d)\n",GetLastError()); } // // Restore boot.ini file attributes // if( FileAttr != 0xFFFFFFFF ) { SetFileAttributes( STR_BOOTINI, FileAttr ); } } // // Usage - print out usage information // VOID Usage() { printf("\nUsage:\n"); printf(" no parameters: prints current settings.\n"); printf(" /set parameter = value : sets value in boot.ini\n"); printf("\n"); printf("Example: nvram /set osloadoptions = debug\n"); printf(" This will set the debug option on\n\n"); printf("Available options:\n"); printf(" loadidentifier, osloadoptions, countdown\n"); } int _cdecl main( IN int argc, IN char *argv[] ) { DWORD dwStatus; LPWSTR* pArgs; // parse command line in unicode pArgs= CommandLineToArgvW( GetCommandLine(), &argc ); // // Get the boot information from boot.ini // // timeout dwStatus= GetPrivateProfileString( STR_BOOTLDR, STR_TIMEOUT, STR_NULL, CountDown, SIZECHARS(CountDown), STR_BOOTINI ); if( !dwStatus ) { printf("Failed to get timeout value\n"); return(-1); } // default os description and options dwStatus= GetPrivateProfileString( STR_BOOTLDR, STR_DEFAULT, STR_NULL, OsName, SIZECHARS(OsName), STR_BOOTINI ); if( !dwStatus ) { printf("Failed to get default OS name\n"); return(-1); } dwStatus= GetPrivateProfileString( STR_OPERATINGSYS, OsName, STR_NULL, OsLine, SIZECHARS(OsLine), STR_BOOTINI ); if( !dwStatus ) { printf("Failed to get default os description\n"); return(-1); } // // Now parse the line into description and options. // If it starts with a quote, it may have options. // If it doesn't start with a quote, it won't. // *LoadID= *OsLoadOptions= TEXT('\0'); if( *OsLine == TEXT('"') ) { INT i; for( i=1; OsLine[i]; i++ ) { LoadID[i-1]= OsLine[i]; if( OsLine[i] == TEXT('"') ) break; } if( OsLine[i] ) { LoadID[i-1]= TEXT('\0'); // don't copy final quote lstrcpy( OsLoadOptions, &OsLine[i+1] ); lstrcat( OsLoadOptions, TEXT(" ") ); // all options end with blank } } else { lstrcpy( LoadID, OsLine ); lstrcpy( OsLoadOptions, TEXT("") ); } // no parameters prints out values if( argc == 1 ) { printf("%ws: %ws\n",PaddedBootVarNames[BootVarLoadIdentifier], LoadID); printf("%ws: %ws\n",PaddedBootVarNames[BootVarOsLoadOptions], OsLoadOptions); printf("%ws: %ws\n",PaddedBootVarNames[BootVarCountdown], CountDown); } // -set parameter = value // sets parameter to some value if( (argc == 5) && !lstrcmpiW(pArgs[1]+1,L"set") && !lstrcmpW(pArgs[3],L"=") ) { INT i; // see if we understand parameter for( i=0; i