880 lines
19 KiB
C
880 lines
19 KiB
C
/*++
|
|
|
|
Copyright (c) 1998 Intel Corporation
|
|
|
|
Module Name:
|
|
|
|
map.c
|
|
|
|
Abstract:
|
|
|
|
Shell environment short device name mapping information management
|
|
|
|
|
|
|
|
Revision History
|
|
|
|
--*/
|
|
|
|
#include "shelle.h"
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
extern LIST_ENTRY SEnvMap;
|
|
STATIC CHAR16 *SEnvCurDevice;
|
|
|
|
|
|
/*
|
|
*
|
|
*/
|
|
|
|
VOID
|
|
SEnvInitMap (
|
|
VOID
|
|
)
|
|
{
|
|
/*
|
|
* The mapping data is read in from the variable init.
|
|
*/
|
|
|
|
/*
|
|
* Init the default map device
|
|
*/
|
|
|
|
SEnvCurDevice = StrDuplicate(L"none");
|
|
}
|
|
|
|
CHAR16 *
|
|
SEnvGetDefaultMapping (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
|
|
{
|
|
EFI_LOADED_IMAGE *LoadedImage;
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *Head;
|
|
LIST_ENTRY *Link;
|
|
VARIABLE_ID *Var;
|
|
EFI_HANDLE Handle;
|
|
EFI_DEVICE_PATH *DevicePath;
|
|
|
|
Status = BS->HandleProtocol (ImageHandle, &LoadedImageProtocol, (VOID*)&LoadedImage);
|
|
if (EFI_ERROR(Status) || LoadedImage==NULL) {
|
|
return NULL;
|
|
}
|
|
Head = &SEnvMap;
|
|
for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
|
|
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
|
|
DevicePath = (EFI_DEVICE_PATH *)Var->u.Str;
|
|
Status = BS->LocateDevicePath(&DevicePathProtocol,&DevicePath,&Handle);
|
|
if (!EFI_ERROR(Status) && Handle!=NULL) {
|
|
if (LoadedImage->DeviceHandle == Handle) {
|
|
return(Var->Name);
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
VOID
|
|
SEnvDumpMapping(
|
|
IN UINTN SLen,
|
|
IN BOOLEAN Verbose,
|
|
IN VARIABLE_ID *Var
|
|
)
|
|
{
|
|
CHAR16 *p;
|
|
EFI_DEVICE_PATH *DPath;
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE DeviceHandle;
|
|
|
|
p = DevicePathToStr ((EFI_DEVICE_PATH *) Var->u.Str);
|
|
Print(L" %h-.*s : %s\n", SLen, Var->Name, p);
|
|
|
|
if (Verbose) {
|
|
/* lookup handle for this mapping */
|
|
DPath = (EFI_DEVICE_PATH *) Var->u.Value;
|
|
Status = BS->LocateDevicePath (&DevicePathProtocol, &DPath, &DeviceHandle);
|
|
if (EFI_ERROR(Status)) {
|
|
Print(L"%*s= Handle for this mapping not found\n", SLen+3);
|
|
} else {
|
|
Print(L"%*s= Handle", SLen + 3, L"");
|
|
SEnvDHProt (FALSE, 0, DeviceHandle);
|
|
}
|
|
|
|
/* print current directory for this mapping */
|
|
Print(L"%*s> %s\n\n", SLen+3, L"", Var->CurDir ? Var->CurDir : L"\\");
|
|
}
|
|
|
|
FreePool (p);
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
SEnvCmdMap (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
/* Code for internal "map" command */
|
|
{
|
|
LIST_ENTRY *Link, *Head;
|
|
VARIABLE_ID *Var;
|
|
VARIABLE_ID *Found;
|
|
CHAR16 *Name;
|
|
CHAR16 *Value;
|
|
UINTN SLen, Len;
|
|
UINTN Size, DataSize;
|
|
BOOLEAN Delete, Verbose, Remap;
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
CHAR16 *p;
|
|
EFI_HANDLE Handle;
|
|
EFI_DEVICE_PATH *DevicePath;
|
|
BOOLEAN PageBreaks;
|
|
UINTN TempColumn;
|
|
UINTN ScreenCount;
|
|
UINTN ScreenSize;
|
|
CHAR16 ReturnStr[1];
|
|
|
|
InitializeShellApplication (ImageHandle, SystemTable);
|
|
Head = &SEnvMap;
|
|
|
|
Name = NULL;
|
|
Value = NULL;
|
|
Delete = FALSE;
|
|
Verbose = FALSE;
|
|
Remap = FALSE;
|
|
Status = EFI_SUCCESS;
|
|
Found = NULL;
|
|
|
|
/*
|
|
* 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 'v':
|
|
case 'V':
|
|
Verbose = TRUE;
|
|
break;
|
|
|
|
case 'r':
|
|
case 'R':
|
|
Remap = TRUE;
|
|
break;
|
|
|
|
case 'b' :
|
|
case 'B' :
|
|
PageBreaks = TRUE;
|
|
ST->ConOut->QueryMode (ST->ConOut, ST->ConOut->Mode->Mode, &TempColumn, &ScreenSize);
|
|
ScreenCount = 0;
|
|
break;
|
|
|
|
default:
|
|
Print (L"Map: Unkown flag %s\n", p);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!Name) {
|
|
Name = p;
|
|
continue;
|
|
}
|
|
|
|
if (!Value) {
|
|
Value = p;
|
|
continue;
|
|
}
|
|
|
|
Print (L"Map: too many arguments\n");
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Delete && Value) {
|
|
Print (L"Map: too many arguments\n");
|
|
}
|
|
|
|
/*
|
|
* Process
|
|
*/
|
|
|
|
if (Remap && !Value && !Delete) {
|
|
AcquireLock (&SEnvLock);
|
|
for (Link=Head->Flink; Link != Head;) {
|
|
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
|
|
Status = RT->SetVariable (Var->Name, &SEnvMapId, 0, 0, NULL);
|
|
Link = Link->Flink;
|
|
RemoveEntryList (&Var->Link);
|
|
FreePool (Var);
|
|
}
|
|
ReleaseLock (&SEnvLock);
|
|
Status = SEnvReloadDefaults (ImageHandle,SystemTable);
|
|
Remap = FALSE;
|
|
}
|
|
|
|
if (Value || Verbose) {
|
|
SEnvLoadHandleTable ();
|
|
|
|
if (Verbose) {
|
|
SEnvLoadHandleProtocolInfo (&DevicePathProtocol);
|
|
}
|
|
}
|
|
|
|
AcquireLock (&SEnvLock);
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (!Name) {
|
|
Print (L"%EDevice mapping table%N\n");
|
|
for (Link=Head->Flink; Link != Head; Link=Link->Flink) {
|
|
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
|
|
SEnvDumpMapping(SLen, Verbose, Var);
|
|
|
|
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, &SEnvMapId, 0, 0, NULL);
|
|
|
|
} else if (Value) {
|
|
|
|
/*
|
|
* Find the handle in question
|
|
*/
|
|
|
|
Handle = SEnvHandleFromStr(Value);
|
|
if (!Handle) {
|
|
Print(L"map: Handle not found\n");
|
|
Status = EFI_NOT_FOUND;
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* Get the handle's device path
|
|
*/
|
|
|
|
DevicePath = DevicePathFromHandle(Handle);
|
|
if (!DevicePath) {
|
|
Print(L"map: handle does not have a device path\n");
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
DataSize = DevicePathSize(DevicePath);
|
|
|
|
|
|
/*
|
|
* Add it to the store
|
|
*/
|
|
|
|
Status = RT->SetVariable (
|
|
Found ? Found->Name : Name,
|
|
&SEnvMapId,
|
|
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
|
|
DataSize,
|
|
DevicePath
|
|
);
|
|
|
|
|
|
if (!EFI_ERROR(Status)) {
|
|
|
|
/*
|
|
* Make a new in memory copy
|
|
*/
|
|
|
|
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, DevicePath, DataSize);
|
|
StrCpy (Var->Name, Found ? Found->Name : Name);
|
|
InsertTailList (Head, &Var->Link);
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Found) {
|
|
SEnvDumpMapping(SLen, Verbose, Var);
|
|
} else {
|
|
Print(L"map: '%es' not found\n", Name);
|
|
}
|
|
|
|
Found = NULL;
|
|
}
|
|
|
|
/*
|
|
* Remove the old in memory copy if there was one
|
|
*/
|
|
|
|
if (Found) {
|
|
RemoveEntryList (&Found->Link);
|
|
FreePool (Found);
|
|
}
|
|
}
|
|
|
|
Done:
|
|
ReleaseLock (&SEnvLock);
|
|
SEnvFreeHandleTable ();
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
VARIABLE_ID *
|
|
SEnvMapDeviceFromName (
|
|
IN OUT CHAR16 **pPath
|
|
)
|
|
/* Check the Path for a device name, and updates the path to point after
|
|
* the device name. If no device name is found, the current default is used. */
|
|
{
|
|
CHAR16 *Path, *p;
|
|
CHAR16 *MappedName, c;
|
|
VARIABLE_ID *Var;
|
|
LIST_ENTRY *Link;
|
|
|
|
|
|
ASSERT_LOCKED (&SEnvLock);
|
|
|
|
Var = NULL;
|
|
Path = *pPath;
|
|
|
|
/*
|
|
* Check for a device name terminator
|
|
*/
|
|
|
|
for(p = Path; *p && *p != ':' && *p != '\\'; p++) ;
|
|
|
|
/*
|
|
* Use either the passed in name or the current device name setting
|
|
*/
|
|
|
|
MappedName = *p == ':' ? Path : SEnvCurDevice;
|
|
|
|
/*
|
|
* Null terminate the string in Path just in case that is the one we
|
|
* are using
|
|
*/
|
|
|
|
c = *p;
|
|
*p = 0;
|
|
|
|
/*
|
|
* Find the mapping for the device
|
|
*/
|
|
|
|
for (Link=SEnvMap.Flink; Link != &SEnvMap; Link=Link->Flink) {
|
|
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
|
|
if (StriCmp(Var->Name, MappedName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Restore the path
|
|
*/
|
|
|
|
*p = c;
|
|
|
|
/*
|
|
* If the mapped device was not found, return NULL
|
|
*/
|
|
|
|
if (Link == &SEnvMap) {
|
|
DEBUG((D_PARSE, "SEnvNameToPath: Mapping for '%es' not found\n", Path));
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* If we found it as part of the path, skip the path over it
|
|
*/
|
|
|
|
if (MappedName == Path) {
|
|
*pPath = p + 1;
|
|
}
|
|
|
|
/*
|
|
* Return the target mapping
|
|
*/
|
|
|
|
return Var;
|
|
}
|
|
|
|
|
|
EFI_DEVICE_PATH *
|
|
SEnvIFileNameToPath (
|
|
IN CHAR16 *Path
|
|
)
|
|
/* Builds a device path from the filename string. Note that the
|
|
* device name must already be stripped off of the file name string */
|
|
{
|
|
CHAR16 *LPath, *ps;
|
|
BOOLEAN UseLPath;
|
|
EFI_DEVICE_PATH *DPath, *Node, *NewPath;
|
|
CHAR16 Buffer[MAX_ARG_LENGTH];
|
|
UINTN Index;
|
|
|
|
ASSERT_LOCKED (&SEnvLock);
|
|
|
|
DPath = NULL;
|
|
|
|
/*
|
|
* If no path, return the root
|
|
*/
|
|
|
|
if (!*Path) {
|
|
DPath = FileDevicePath(NULL, L"\\");
|
|
}
|
|
|
|
|
|
/*
|
|
* Build a file path for the name component(s)
|
|
*/
|
|
|
|
while (*Path) {
|
|
|
|
Index = 0;
|
|
LPath = NULL;
|
|
UseLPath = FALSE;
|
|
|
|
ps = Path;
|
|
while (*ps) {
|
|
|
|
/* if buffer has run out, just handle to LPath */
|
|
if (Index > MAX_ARG_LENGTH-2 || *ps == '#') {
|
|
UseLPath = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (*ps == '^') {
|
|
if (ps[1]) {
|
|
ps += 1;
|
|
Buffer[Index++] = *ps;
|
|
}
|
|
ps += 1;
|
|
continue;
|
|
}
|
|
|
|
if (*ps == '\\') {
|
|
LPath = ps;
|
|
}
|
|
|
|
Buffer[Index++] = *ps;
|
|
ps += 1;
|
|
}
|
|
|
|
if (UseLPath) {
|
|
Index = LPath ? LPath - Path : 0;
|
|
ps = Path + Index;
|
|
}
|
|
|
|
/*
|
|
* If we have part of a path name, append it to the device path
|
|
*/
|
|
|
|
if (Index) {
|
|
Buffer[Index] = 0;
|
|
Node = FileDevicePath(NULL, Buffer);
|
|
NewPath = AppendDevicePath (DPath, Node);
|
|
FreePool (Node);
|
|
if (DPath) {
|
|
FreePool (DPath);
|
|
}
|
|
DPath = NewPath;
|
|
}
|
|
|
|
if (*ps == 0) {
|
|
break;
|
|
}
|
|
|
|
Path = ps + 1;
|
|
}
|
|
|
|
return DPath;
|
|
}
|
|
|
|
|
|
EFI_DEVICE_PATH *
|
|
SEnvFileNameToPath (
|
|
IN CHAR16 *Path
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH *FilePath;
|
|
|
|
AcquireLock (&SEnvLock);
|
|
FilePath = SEnvIFileNameToPath (Path);
|
|
ReleaseLock (&SEnvLock);
|
|
return FilePath;
|
|
}
|
|
|
|
|
|
EFI_DEVICE_PATH *
|
|
SEnvINameToPath (
|
|
IN CHAR16 *Path
|
|
)
|
|
/* Convert a filesystem stlye name to an file path */
|
|
{
|
|
EFI_DEVICE_PATH *DPath, *FPath, *RPath, *FilePath;
|
|
VARIABLE_ID *Var;
|
|
BOOLEAN FreeDPath;
|
|
|
|
DPath = NULL;
|
|
RPath = NULL;
|
|
FPath = NULL;
|
|
FilePath = NULL;
|
|
FreeDPath = FALSE;
|
|
|
|
ASSERT_LOCKED (&SEnvLock);
|
|
|
|
/*
|
|
* Get the device for the name, and advance past the device name
|
|
*/
|
|
|
|
Var = SEnvMapDeviceFromName (&Path);
|
|
if (!Var) {
|
|
DEBUG((D_PARSE, "SEnvNameToPath: mapped device not found\n"));
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* Start the file path with this mapping
|
|
*/
|
|
|
|
DPath = (EFI_DEVICE_PATH *) Var->u.Value;
|
|
|
|
/*
|
|
* If the path is realitve, append the current dir of the device to the dpath
|
|
*/
|
|
|
|
if (*Path != '\\') {
|
|
RPath = SEnvIFileNameToPath (Var->CurDir ? Var->CurDir : L"\\");
|
|
DPath = AppendDevicePath (DPath, RPath);
|
|
FreeDPath = TRUE;
|
|
}
|
|
|
|
/*
|
|
* Build a file path for the rest of the name string
|
|
*/
|
|
|
|
FPath = SEnvIFileNameToPath (Path);
|
|
|
|
/*
|
|
* Append the 2 paths
|
|
*/
|
|
|
|
FilePath = AppendDevicePath(DPath, FPath);
|
|
|
|
/*
|
|
* Done
|
|
*/
|
|
|
|
Done:
|
|
if (DPath && FreeDPath) {
|
|
FreePool (DPath);
|
|
}
|
|
|
|
if (RPath) {
|
|
FreePool (RPath);
|
|
}
|
|
|
|
if (FPath) {
|
|
FreePool (FPath);
|
|
}
|
|
|
|
return FilePath;
|
|
}
|
|
|
|
|
|
|
|
EFI_DEVICE_PATH *
|
|
SEnvNameToPath (
|
|
IN CHAR16 *Path
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH *DPath;
|
|
|
|
AcquireLock (&SEnvLock);
|
|
DPath = SEnvINameToPath (Path);
|
|
ReleaseLock (&SEnvLock);
|
|
|
|
return DPath;
|
|
}
|
|
|
|
|
|
|
|
EFI_STATUS
|
|
SEnvCmdCd (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH *FilePath;
|
|
EFI_STATUS Status;
|
|
EFI_FILE_HANDLE OpenDir;
|
|
CHAR16 *Dir;
|
|
CHAR16 *CurDir;
|
|
VARIABLE_ID *Var;
|
|
EFI_FILE_INFO *FileInfo;
|
|
|
|
|
|
InitializeShellApplication (ImageHandle, SystemTable);
|
|
FilePath = NULL;
|
|
|
|
/*
|
|
* If no arguments, print the current directory
|
|
*/
|
|
|
|
if (SI->Argc == 1) {
|
|
Dir = SEnvGetCurDir(NULL);
|
|
if (Dir) {
|
|
Print (L"%s\n", Dir);
|
|
FreePool (Dir);
|
|
} else {
|
|
Print (L"no current directory\n");
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
AcquireLock (&SEnvLock);
|
|
|
|
/*
|
|
* If more then 1 argument, syntax
|
|
*/
|
|
|
|
if (SI->Argc > 2) {
|
|
Print (L"cd: too many arguments\n");
|
|
Status =EFI_INVALID_PARAMETER;
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* Find the target device
|
|
*/
|
|
|
|
Dir = SI->Argv[1];
|
|
Var = SEnvMapDeviceFromName (&Dir);
|
|
if (!Var) {
|
|
Print(L"cd: mapped device not found\n");
|
|
Status = EFI_NOT_FOUND;
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* If there's no path specified, print the current path for the device
|
|
*/
|
|
|
|
if (*Dir == 0) {
|
|
Print (L"%s\n", Var->CurDir ? Var->CurDir : L"\\");
|
|
Status = EFI_SUCCESS;
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* Build a file path for the argument
|
|
*/
|
|
|
|
FilePath = SEnvINameToPath (SI->Argv[1]);
|
|
if (!FilePath) {
|
|
Status = EFI_NOT_FOUND;
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* Open the target directory
|
|
*/
|
|
|
|
OpenDir = ShellOpenFilePath(FilePath, EFI_FILE_MODE_READ);
|
|
|
|
if (!OpenDir) {
|
|
Print (L"cd: target directory not found\n");
|
|
Status = EFI_NOT_FOUND;
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* Get information on the file path that was opened.
|
|
*/
|
|
|
|
FileInfo = LibFileInfo(OpenDir);
|
|
if (FileInfo == NULL) {
|
|
Status = EFI_NOT_FOUND;
|
|
goto Done;
|
|
}
|
|
|
|
/*
|
|
* Verify that the file opened is a directory.
|
|
*/
|
|
|
|
if (!(FileInfo->Attribute & EFI_FILE_DIRECTORY)) {
|
|
Print (L"cd: target is not a directory\n");
|
|
FreePool (FileInfo);
|
|
OpenDir->Close (OpenDir);
|
|
Status = EFI_NOT_FOUND;
|
|
goto Done;
|
|
}
|
|
FreePool (FileInfo);
|
|
|
|
CurDir = SEnvFileHandleToFileName(OpenDir);
|
|
OpenDir->Close (OpenDir);
|
|
|
|
/*
|
|
* If we have a new path, update the device
|
|
*/
|
|
|
|
if (CurDir) {
|
|
if (Var->CurDir) {
|
|
FreePool(Var->CurDir);
|
|
}
|
|
Var->CurDir = CurDir;
|
|
|
|
} else {
|
|
|
|
Print (L"cd: could not cd to '%hs%'\n", FilePath);
|
|
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
Done:
|
|
ReleaseLock (&SEnvLock);
|
|
|
|
if (FilePath) {
|
|
FreePool (FilePath);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
CHAR16 *
|
|
SEnvGetCurDir (
|
|
IN CHAR16 *DeviceName OPTIONAL
|
|
)
|
|
/* N.B. results are allocated in pool */
|
|
{
|
|
CHAR16 *Dir;
|
|
LIST_ENTRY *Link;
|
|
VARIABLE_ID *Var;
|
|
|
|
Dir = NULL;
|
|
if (!DeviceName) {
|
|
DeviceName = SEnvCurDevice;
|
|
}
|
|
|
|
AcquireLock (&SEnvLock);
|
|
for (Link=SEnvMap.Flink; Link != &SEnvMap; Link=Link->Flink) {
|
|
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
|
|
if (StriCmp(Var->Name, DeviceName) == 0) {
|
|
Dir = PoolPrint(L"%s:%s", Var->Name, Var->CurDir ? Var->CurDir : L"\\");
|
|
break;
|
|
}
|
|
}
|
|
|
|
ReleaseLock (&SEnvLock);
|
|
return Dir;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
SEnvSetCurrentDevice (
|
|
IN CHAR16 *Name
|
|
)
|
|
{
|
|
VARIABLE_ID *Var;
|
|
LIST_ENTRY *Link;
|
|
EFI_STATUS Status;
|
|
UINTN Len;
|
|
CHAR16 *NewName, c;
|
|
|
|
|
|
Len = StrLen(Name);
|
|
if (Len < 1) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
/*
|
|
* If the name ends with a ":" strip it off
|
|
*/
|
|
|
|
Len -= 1;
|
|
c = Name[Len];
|
|
if (c == ':') {
|
|
Name[Len] = 0;
|
|
}
|
|
|
|
|
|
Status = EFI_NO_MAPPING;
|
|
AcquireLock (&SEnvLock);
|
|
|
|
for (Link=SEnvMap.Flink; Link != &SEnvMap; Link=Link->Flink) {
|
|
Var = CR(Link, VARIABLE_ID, Link, VARIABLE_SIGNATURE);
|
|
if (StriCmp(Var->Name, Name) == 0) {
|
|
NewName = StrDuplicate(Name);
|
|
if (NewName) {
|
|
FreePool (SEnvCurDevice);
|
|
SEnvCurDevice = NewName;
|
|
}
|
|
Status = EFI_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ReleaseLock (&SEnvLock);
|
|
|
|
/*
|
|
* Restore the name
|
|
*/
|
|
|
|
Name[Len] = c;
|
|
return Status;
|
|
}
|