windows-nt/Source/XPSP1/NT/base/efiutil/sdk/shell/shellenv/var.c
2020-09-26 16:20:57 +08:00

470 lines
11 KiB
C

/*++
Copyright (c) 1998 Intel Corporation
Module Name:
protid.c
Abstract:
Shell environment variable management
Revision History
--*/
#include "shelle.h"
/*
* The different variable catagories
*/
LIST_ENTRY SEnvEnv;
LIST_ENTRY SEnvMap;
LIST_ENTRY SEnvAlias;
VOID
SEnvInitVariables (
VOID
)
{
CHAR16 *Name;
CHAR16 *Data;
UINTN BufferSize;
UINTN NameSize, DataSize;
EFI_GUID Id;
LIST_ENTRY *ListHead;
VARIABLE_ID *Var;
EFI_STATUS Status;
BOOLEAN IsString;
UINT32 Attributes;
UINTN Size;
/*
* Initialize the different variable lists
*/
InitializeListHead (&SEnvEnv);
InitializeListHead (&SEnvMap);
InitializeListHead (&SEnvAlias);
BufferSize = 1024;
Name = AllocatePool (BufferSize);
Data = AllocatePool (BufferSize);
ASSERT(Name && Data);
/*
* Read all the variables in the system and collect ours
*/
Name[0] = 0;
for (; ;) {
NameSize = BufferSize;
Status = RT->GetNextVariableName (&NameSize, Name, &Id);
if (EFI_ERROR(Status)) {
break;
}
/*
* See if it's a shellenv variable
*/
ListHead = NULL;
IsString = FALSE;
if (CompareGuid (&Id, &SEnvEnvId) == 0) {
ListHead = &SEnvEnv;
IsString = TRUE;
}
if (CompareGuid (&Id, &SEnvMapId) == 0) {
ListHead = &SEnvMap;
}
if (CompareGuid (&Id, &SEnvAliasId) == 0) {
ListHead = &SEnvAlias;
IsString = TRUE;
}
if (ListHead) {
DataSize = BufferSize;
Status = RT->GetVariable (Name, &Id, &Attributes, &DataSize, Data);
if (!EFI_ERROR(Status)) {
/*
* Add this value
*/
Size = sizeof(VARIABLE_ID) + StrSize(Name) + DataSize;
Var = AllocateZeroPool (Size);
Var->Signature = VARIABLE_SIGNATURE;
Var->u.Value = ((UINT8 *) Var) + sizeof(VARIABLE_ID);
Var->Name = (CHAR16*) (Var->u.Value + DataSize);
Var->ValueSize = DataSize;
CopyMem (Var->u.Value, Data, DataSize);
CopyMem (Var->Name, Name, NameSize);
if( Attributes & EFI_VARIABLE_NON_VOLATILE ) {
Var->Flags = NON_VOL ;
}
else {
Var->Flags = VOL ;
}
InsertTailList (ListHead, &Var->Link);
}
}
/*
* If this is a protocol entry, add it
*/
if (CompareGuid (&Id, &SEnvProtId) == 0) {
DataSize = BufferSize;
Status = RT->GetVariable (Name, &Id, &Attributes, &DataSize, Data);
if (!EFI_ERROR(Status) && DataSize == sizeof (EFI_GUID)) {
SEnvIAddProtocol (FALSE, (EFI_GUID *) Data, NULL, NULL, Name);
} else {
DEBUG ((D_INIT|D_WARN, "SEnvInitVariables: skipping bogus protocol id %s\n", Var->Name));
RT->SetVariable (Name, &SEnvProtId, 0, 0, NULL);
}
}
}
FreePool (Name);
FreePool (Data);
}
CHAR16 *
SEnvIGetStr (
IN CHAR16 *Name,
IN LIST_ENTRY *Head
)
{
LIST_ENTRY *Link;
VARIABLE_ID *Var;
CHAR16 *Value;
AcquireLock (&SEnvLock);
Value = NULL;
for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
if (StriCmp (Var->Name, Name) == 0) {
Value = Var->u.Str;
break;
}
}
ReleaseLock (&SEnvLock);
return Value;
}
CHAR16 *
SEnvGetMap (
IN CHAR16 *Name
)
{
return SEnvIGetStr (Name, &SEnvMap);
}
CHAR16 *
SEnvGetEnv (
IN CHAR16 *Name
)
{
return SEnvIGetStr (Name, &SEnvEnv);
}
CHAR16 *
SEnvGetAlias (
IN CHAR16 *Name
)
{
return SEnvIGetStr (Name, &SEnvAlias);
}
VOID
SEnvSortVarList (
IN LIST_ENTRY *Head
)
{
ASSERT_LOCKED(&SEnvLock);
return ;
}
EFI_STATUS
SEnvCmdSA (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable,
IN LIST_ENTRY *Head,
IN EFI_GUID *Guid
)
/* Code for shell "set" & "alias" command */
{
LIST_ENTRY *Link;
VARIABLE_ID *Var;
VARIABLE_ID *Found;
CHAR16 *Name;
CHAR16 *Value;
UINTN Size, SLen, Len;
BOOLEAN Delete;
EFI_STATUS Status;
UINTN Index;
CHAR16 *p;
BOOLEAN PageBreaks;
UINTN TempColumn;
UINTN ScreenCount;
UINTN ScreenSize;
CHAR16 ReturnStr[1];
BOOLEAN Volatile;
InitializeShellApplication (ImageHandle, SystemTable);
Name = NULL;
Value = NULL;
Delete = FALSE;
Status = EFI_SUCCESS;
Found = NULL;
Volatile = FALSE;
/*
* Crack arguments
*/
PageBreaks = FALSE;
for (Index = 1; Index < SI->Argc; Index += 1) {
p = SI->Argv[Index];
if (*p == '-') {
switch (p[1]) {
case 'd':
case 'D':
Delete = TRUE;
break;
case 'b' :
case 'B' :
PageBreaks = TRUE;
ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
ScreenCount = 0;
break;
case 'v' :
case 'V' :
Volatile = TRUE;
break;
default:
Print (L"%ESet/Alias: Unknown flag %s\n", p);
return EFI_INVALID_PARAMETER;
}
continue;
}
if (!Name) {
Name = p;
continue;
}
if (!Value) {
Value = p;
continue;
}
Print (L"%ESet/Alias: too many arguments\n");
return EFI_INVALID_PARAMETER;
}
if (Delete && Value) {
Print (L"%ESet/Alias: too many arguments\n");
}
/*
* Process
*/
AcquireLock (&SEnvLock);
if (!Name) {
/* dump the list */
SEnvSortVarList (Head);
SLen = 0;
for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
Len = StrLen(Var->Name);
if (Len > SLen) {
SLen = Len;
}
}
for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
if( Var->Flags == VOL ) {
Print(L" * %h-.*s : %s\n", SLen, Var->Name, Var->u.Str);
}
else {
Print(L" %h-.*s : %s\n", SLen, Var->Name, Var->u.Str);
}
if (PageBreaks) {
ScreenCount++;
if (ScreenCount > ScreenSize - 4) {
ScreenCount = 0;
Print (L"\nPress Return to contiue :");
Input (L"", ReturnStr, sizeof(ReturnStr)/sizeof(CHAR16));
Print (L"\n\n");
}
}
}
} else {
/*
* Find the specified value
*/
for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
if (StriCmp(Var->Name, Name) == 0) {
Found = Var;
break;
}
}
if (Found && Delete) {
/*
* Remove it from the store
*/
Status = RT->SetVariable (Found->Name, Guid, 0, 0, NULL);
if (Status == EFI_NOT_FOUND) {
Print (L"Set/Alias: could not find '%hs'\n", Found->Name);
Status = EFI_SUCCESS;
}
} else if (Value) {
/*
* Add it to the store
*/
if( Found && ( ( Volatile && ( Found->Flags == NON_VOL ) ) ||
( !Volatile && ( Found->Flags == VOL ) ) ) )
{
if( Found->Flags == NON_VOL ) {
Print (L"Set/Alias: '%hs' already exists as non-volatile variable\n", Found->Name ) ;
}
else {
Print (L"Set/Alias: '%hs' already exists as volatile variable\n", Found->Name ) ;
}
Found = NULL ;
Status = EFI_ACCESS_DENIED ;
}
else
{
Status = RT->SetVariable (
Found ? Found->Name : Name,
Guid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | ( Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE ),
StrSize(Value),
Value
);
if (!EFI_ERROR(Status)) {
/*
* Make a new in memory copy
*/
Size = sizeof(VARIABLE_ID) + StrSize(Name) + StrSize(Value);
Var = AllocateZeroPool (Size);
Var->Signature = VARIABLE_SIGNATURE;
Var->u.Value = ((UINT8 *) Var) + sizeof(VARIABLE_ID);
Var->Name = (CHAR16*) (Var->u.Value + StrSize(Value));
Var->ValueSize = StrSize(Value);
StrCpy (Var->u.Str, Value);
StrCpy (Var->Name, Found ? Found->Name : Name);
if( Volatile ) {
Var->Flags = VOL ;
}
else {
Var->Flags = NON_VOL ;
}
InsertTailList (Head, &Var->Link);
}
}
} else {
if (Found) {
Print(L" %hs : %s\n", Var->Name, Var->u.Str);
} else {
Print(L"'%es' not found\n", Name);
}
Found = NULL;
}
/*
* Remove the old in memory copy if there was one
*/
if (Found) {
RemoveEntryList (&Found->Link);
FreePool (Found);
}
}
ReleaseLock (&SEnvLock);
return Status;
}
EFI_STATUS
SEnvCmdSet (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/* Code for internal shell "set" command */
{
return SEnvCmdSA (ImageHandle, SystemTable, &SEnvEnv, &SEnvEnvId);
}
EFI_STATUS
SEnvCmdAlias (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/* Code for internal shell "set" command */
{
return SEnvCmdSA (ImageHandle, SystemTable, &SEnvAlias, &SEnvAliasId);
}