windows-nt/Source/XPSP1/NT/base/hals/halia64/ia64/setupnvr.c
2020-09-26 16:20:57 +08:00

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;
}