/*++ Module Name: setupnvr.c Abstract: Access function to r/w environment variables from pseudo-NVRAM file Author: Mudit Vats (v-muditv) 5-18-99 Revision History: 6/4/99 added OSLOADOPTIONS --*/ #include #include #include "halp.h" #include "setupnvr.h" #define SYSTEMPARTITION 0 #define OSLOADER 1 #define OSLOADPARTITION 2 #define OSLOADFILENAME 3 #define LOADIDENTIFIER 4 #define OSLOADOPTIONS 5 #define COUNTDOWN 6 #define AUTOLOAD 7 #define LASTKNOWNGOOD 8 #define BOOTNVRAMFILE L"\\device\\harddisk0\\partition1\\boot.nvr" PUCHAR HalpNvrKeys[] = { "SYSTEMPARTITION", "OSLOADER", "OSLOADPARTITION", "OSLOADFILENAME", "LOADIDENTIFIER", "OSLOADOPTIONS", "COUNTDOWN", "AUTOLOAD", "LASTKNOWNGOOD", "" }; // // All Pseudo-NVRAM vars stored here // char g_szBootVars[MAXBOOTVARS][MAXBOOTVARSIZE]; // // ReadNVRAM - read pseudo-nvram; read boot vars from "boot.nvr" file // int ReadNVRAM() { UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Obja; HANDLE Handle; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; FILE_STANDARD_INFORMATION StandardInfo; char szBuffer[MAXBOOTVARSIZE+20]; int i; ULONG LengthRemaining; ULONG CurrentLength; ULONG CurrentLine = 1; PCHAR KeyStart; PCHAR ValueStart; PCHAR pc; PCHAR ReadPos; PCHAR BufferEnd; CHAR c; BOOLEAN SkipSpace; // // Clear all variables. // for (i=SYSTEMPARTITION; i<=LASTKNOWNGOOD; i++) { g_szBootVars[i][0] = '\0'; } RtlInitUnicodeString( &UnicodeString, BOOTNVRAMFILE ); InitializeObjectAttributes(&Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwCreateFile( &Handle, FILE_GENERIC_READ, &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 ); if (!NT_SUCCESS(Status)) { //KdPrint(("HALIA64: Unable to open %ws for reading!\n", BOOTNVRAMFILE)); //return NT_SUCCESS(Status); // // We didn't find the boot.nvr, so we will assume we are // doing a setup from cd // strcpy( g_szBootVars[0], "multi(0)disk(0)rdisk(0)partition(1)\0" ); strcpy( g_szBootVars[1], "multi(0)disk(0)cdrom(1)\\setupldr.efi\0" ); strcpy( g_szBootVars[2], "multi(0)disk(0)cdrom(1)\0" ); strcpy( g_szBootVars[3], "\\IA64\0" ); strcpy( g_szBootVars[4], "Microsoft Windows 2000 Setup\0" ); strcpy( g_szBootVars[5], "\0" ); strcpy( g_szBootVars[6], "30\0" ); strcpy( g_szBootVars[7], "YES\0" ); strcpy( g_szBootVars[8], "False\0" ); return ERROR_OK; } Status = ZwQueryInformationFile( Handle, &IoStatusBlock, &StandardInfo, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation ); if (!NT_SUCCESS(Status)) { KdPrint(("HALIA64: Error querying info on file %ws\n", BOOTNVRAMFILE)); goto cleanup; } LengthRemaining = StandardInfo.EndOfFile.LowPart; KeyStart = ValueStart = szBuffer; ReadPos = szBuffer; SkipSpace = TRUE; while (LengthRemaining) { // // Read a buffer's worth of data from the 'nvram' file and // attempt to parse it one variable at a time. // CurrentLength = (ULONG)((szBuffer + sizeof(szBuffer)) - ReadPos); if (CurrentLength > LengthRemaining) { CurrentLength = LengthRemaining; } BufferEnd = ReadPos + CurrentLength; LengthRemaining -= CurrentLength; Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock, ReadPos, CurrentLength, NULL, NULL ); if (!NT_SUCCESS(Status)) { KdPrint(("HALIA64: Error reading from %ws!\n", BOOTNVRAMFILE)); goto cleanup; } // // Lines in the file are of the form KEY=VALUE\r, find the // start of the key, the start of the value and the start of // the next key. Note the buffer is large enough to contain // at least one of the largest key and largest value. // for (pc = ReadPos; TRUE; pc++) { if (pc == BufferEnd) { // // Hit end of buffer. If the data we are processing // begins at the start of the buffer then the data is // too big to process, abort. // if ((KeyStart == szBuffer) && (SkipSpace == FALSE)) { KdPrint(("HALIA64: %ws line %d too long to process, aborting\n", BOOTNVRAMFILE, CurrentLine)); Status = STATUS_UNSUCCESSFUL; goto cleanup; } // // Move current line to start of buffer then read more // data into the buffer. // i = (int)((szBuffer + sizeof(szBuffer)) - KeyStart); RtlMoveMemory(szBuffer, KeyStart, i); ValueStart -= KeyStart - szBuffer; KeyStart = szBuffer; ReadPos = szBuffer + i; // // Break out of this loop and reexecute the read loop. // break; } c = *pc; if (c == '\0') { // // Unexpected end of string, abort. // KdPrint(("HALIA64: Unexpected end of string in %ws!\n", BOOTNVRAMFILE)); Status = STATUS_UNSUCCESSFUL; goto cleanup; } if (SkipSpace == TRUE) { // // Skipping White Space. // if ((c == ' ') || (c == '\t') || (c == '\r') || (c == '\n')) { continue; } // // Current character is NOT white space, set as // beginning of things we will look at. // KeyStart = ValueStart = pc; SkipSpace = FALSE; } if (c == '=') { if (ValueStart == KeyStart) { // // This is the first '=' on the line, the value // starts in the next character position. // ValueStart = pc; } } if (c == '\r') { // // At end of line. Treat from KeyStart to current // position as a single line containing a variable. // *ValueStart = '\0'; for (i = 0; i < MAXBOOTVARS; i++) { if (strcmp(KeyStart, HalpNvrKeys[i]) == 0) { // // Have a key match, copy from ValueStart+1 // thru end of line as the variable's value. // ULONGLONG ValueLength = pc - ValueStart - 1; if (ValueLength >= MAXBOOTVARSIZE) { ValueLength = MAXBOOTVARSIZE - 1; } RtlCopyMemory(g_szBootVars[i], ValueStart + 1, ValueLength); g_szBootVars[i][ValueLength] = '\0'; CurrentLine++; SkipSpace = TRUE; break; } } // // Start looking for the next key at the current // character position. // KeyStart = pc; ValueStart = pc; } } } cleanup: ZwClose( Handle ); return NT_SUCCESS( Status ); } // // WriteNVRAM - write pseudo-nvram; read boot vars from "boot.nvr" file // int WriteNVRAM() { UNICODE_STRING UnicodeString; OBJECT_ATTRIBUTES Obja; HANDLE Handle; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status; UCHAR szBuffer[MAXBOOTVARSIZE+20]; ULONG BootVar; ULONG VarLen; RtlInitUnicodeString( &UnicodeString, BOOTNVRAMFILE ); InitializeObjectAttributes( &Obja, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ZwCreateFile( &Handle, FILE_GENERIC_WRITE | DELETE, &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, // no sharing FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_WRITE_THROUGH, NULL, 0 ); if(!NT_SUCCESS(Status)) { KdPrint(("HALIA64: Unable to open %ws for writing!\n", BOOTNVRAMFILE)); return ERROR_NOTOK; } // // Generate an entry of the form NAME=VALUE for each variable // and write it to the 'nvram' file. // for ( BootVar = 0; BootVar < MAXBOOTVARS; BootVar++ ) { VarLen = _snprintf(szBuffer, sizeof(szBuffer), "%s=%s\r\n", HalpNvrKeys[BootVar], g_szBootVars[BootVar]); Status = ZwWriteFile( Handle, NULL, NULL, NULL, &IoStatusBlock, szBuffer, VarLen, NULL, NULL ); if (!NT_SUCCESS(Status)) { KdPrint(("HALIA64: Error writing %s to %ws!\n", HalpNvrKeys[BootVar], BOOTNVRAMFILE)); goto cleanup; } } cleanup: ZwClose( Handle ); return NT_SUCCESS( Status ); } // // GetBootVar - gets the requested boot environment variable // // szBootVar - this is the requested boot var: // // SYSTEMPARTITION // OSLOADER // OSLOADPARTITION // OSLOADFILENAME // LOADIDENTIFIER // OSLOADOPTIONS // COUNTDOWN // AUTOLOAD // LASTKNOWNGOOD // nLength - length of szBootVal (input buffer) // szBootVal - boot environment variable returned here // int GetBootVar( PCHAR szBootVar, USHORT nLength, PCHAR szBootVal ) { ULONG BootVar; // // Search the boot variable keys for a match. // for ( BootVar = 0; BootVar < MAXBOOTVARS; BootVar++ ) { if (_stricmp(szBootVar, HalpNvrKeys[BootVar]) == 0) { // // Found a key match, copy the variable's value to the // caller's buffer. // strncpy(szBootVal, g_szBootVars[BootVar], nLength); return ERROR_OK; } } // // No such variable, return error. // return ERROR_NOTOK; } // // SetBootVar - sets the requested boot environment variable // // szBootVar - this is the requested boot var: // // SYSTEMPARTITION // OSLOADER // OSLOADPARTITION // OSLOADFILENAME // LOADIDENTIFIER // OSLOADOPTIONS // COUNTDOWN // AUTOLOAD // LASTKNOWNGOOD // szBootVal - new boot environment variable value // int SetBootVar( PCHAR szBootVar, PCHAR szBootVal ) { ULONG BootVar; // // Search the boot variable keys for a match. // for ( BootVar = 0; BootVar < MAXBOOTVARS; BootVar++ ) { if (_stricmp(szBootVar, HalpNvrKeys[BootVar]) == 0) { // // Found it, copy the new value to this value. // strncpy(g_szBootVars[BootVar], szBootVal, MAXBOOTVARSIZE); return ERROR_OK; } } // // No such variable, return error. // return ERROR_NOTOK; }