491 lines
13 KiB
C
491 lines
13 KiB
C
/*++
|
|
|
|
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 <stdio.h>
|
|
#include <string.h>
|
|
#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;
|
|
}
|