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

530 lines
13 KiB
C

/*++
Copyright (c) 1999 Intel Corporation
Module Name:
libFileImage.c
Abstract:
Definition of the File Image - the complete image of the file that
resides in memory
--*/
#ifndef _LIB_FILE_IMAGE
#define _LIB_FILE_IMAGE
#include "libMisc.h"
STATIC EFI_EDITOR_LINE* FileImageCreateNode (VOID);
STATIC VOID FileImageDeleteLines (VOID);
#define FILE_ATTRIBUTES EFI_FILE_MODE_READ | \
EFI_FILE_MODE_WRITE | \
EFI_FILE_MODE_CREATE
#define FILE_READ_WRITE EFI_FILE_MODE_READ | \
EFI_FILE_MODE_WRITE
#define FILE_CREATE EFI_FILE_MODE_READ | \
EFI_FILE_MODE_WRITE | \
EFI_FILE_MODE_CREATE
STATIC EFI_STATUS FileImageInit (EFI_HANDLE);
STATIC EFI_STATUS FileImageCleanup (VOID);
STATIC EFI_STATUS FileImageOpen (VOID);
STATIC EFI_STATUS FileImageRead (VOID);
STATIC EFI_STATUS FileImageClose (VOID);
STATIC EFI_STATUS FileImageWrite (VOID);
STATIC EFI_STATUS FileImageSetFilename (CHAR16*);
EFI_EDITOR_FILE_IMAGE FileImage = {
NULL,
NULL,
NULL,
0,
UNICODE_FILE,
USE_LF,
NULL,
NULL,
NULL,
NULL,
NULL,
FileImageCleanup,
FileImageInit,
FileImageOpen,
FileImageRead,
FileImageClose,
FileImageWrite,
FileImageSetFilename,
FALSE
};
EFI_EDITOR_FILE_IMAGE FileImageConst = {
NULL,
NULL,
NULL,
0,
UNICODE_FILE,
USE_LF,
NULL,
NULL,
NULL,
NULL,
NULL,
FileImageCleanup,
FileImageInit,
FileImageOpen,
FileImageRead,
FileImageClose,
FileImageWrite,
FileImageSetFilename,
FALSE
};
STATIC
EFI_STATUS
FileImageInit (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
EFI_EDITOR_LINE *Line;
CHAR16 *CurDir;
UINTN i;
EFI_DEVICE_PATH *DevicePath;
CopyMem (&FileImage, &FileImageConst, sizeof(FileImage));
Status = BS->HandleProtocol (ImageHandle,&LoadedImageProtocol,&FileImage.LoadedImage);
if (EFI_ERROR(Status)) {
Print (L"Could not obtain Loaded Image Protocol\n");
return EFI_LOAD_ERROR;
}
if (FileImage.LoadedImage->DeviceHandle != NULL) {
Status = BS->HandleProtocol (FileImage.LoadedImage->DeviceHandle,&DevicePathProtocol,&FileImage.DevicePath);
if (EFI_ERROR(Status)) {
Print (L"Could not obtain Device Path Protocol\n");
return EFI_LOAD_ERROR;
}
Status = BS->HandleProtocol (FileImage.LoadedImage->DeviceHandle,&FileSystemProtocol,&FileImage.Vol);
if (EFI_ERROR(Status)) {
Print (L"Could not obtain File System Protocol\n");
return EFI_LOAD_ERROR;
}
} else {
CurDir = ShellCurDir(NULL);
if (CurDir == NULL) {
Print (L"Could not get current working directory\n");
return EFI_LOAD_ERROR;
}
for (i=0; i < StrLen(CurDir) && CurDir[i] != ':'; i++);
CurDir[i] = 0;
DevicePath = (EFI_DEVICE_PATH *)ShellGetMap (CurDir);
if (DevicePath == NULL) {
Print (L"Could not open volume for the filesystem\n");
return EFI_LOAD_ERROR;
}
Status = LibDevicePathToInterface (&FileSystemProtocol, DevicePath, &FileImage.Vol);
if (EFI_ERROR(Status)) {
Print (L"Could not obtain File System Protocol\n");
return EFI_LOAD_ERROR;
}
}
Status = FileImage.Vol->OpenVolume(FileImage.Vol,&FileImage.CurrentDir);
if (EFI_ERROR(Status)) {
Print (L"Could not open volume for the filesystem\n");
return EFI_LOAD_ERROR;
}
FileImage.FileName = PoolPrint(L"NewFile.txt");
FileImage.ListHead = AllocatePool(sizeof(LIST_ENTRY));
InitializeListHead(FileImage.ListHead);
Line = FileImageCreateNode();
MainEditor.FileBuffer->CurrentLine = FileImage.ListHead->Flink;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileImageOpen (
VOID
)
{
EFI_STATUS Status;
Status = FileImage.CurrentDir->Open (FileImage.CurrentDir,&FileImage.FileHandle,FileImage.FileName,FILE_ATTRIBUTES,0);
if (EFI_ERROR(Status)) {
MainEditor.StatusBar->SetStatusString(L"File Could Not be Opened");
return EFI_NOT_FOUND;
}
FileImage.FileIsOpen = TRUE;
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileImageCleanup (
VOID
)
{
EFI_EDITOR_LINE *Blank;
FreePool (FileImage.FileName);
FileImageDeleteLines ();
Blank = LineCurrent();
RemoveEntryList(&Blank->Link);
FreePool(Blank->Buffer);
FreePool(Blank);
FreePool(FileImage.ListHead);
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileImageRead (
VOID
)
{
EFI_EDITOR_LINE *Line = NULL;
UINTN i = 0;
UINTN LineSize;
VOID *FileBuffer;
CHAR16 *UnicodeBuffer;
CHAR8 *AsciiBuffer;
LIST_ENTRY *Blank;
UINTN FileSize = 0x100000;
FileBuffer = AllocatePool(FileSize);
if ( FileBuffer == NULL ) {
EditorError(EFI_OUT_OF_RESOURCES,L"Could not allocate File Buffer");
return EFI_SUCCESS;
}
FileImage.FileHandle->Read(FileImage.FileHandle,&FileSize,FileBuffer);
if (FileSize == 0) {
FreePool (FileBuffer);
return EFI_SUCCESS;
}
AsciiBuffer = FileBuffer;
if (AsciiBuffer[0] == 0xff && AsciiBuffer[1] == 0xfe) {
FileImage.FileType = UNICODE_FILE;
FileSize /= 2;
UnicodeBuffer = FileBuffer;
++UnicodeBuffer;
FileSize--;
} else {
FileImage.FileType = ASCII_FILE;
}
FileImageDeleteLines ();
Blank = FileImage.ListHead->Flink;
RemoveEntryList (Blank);
for (i = 0; i < FileSize; i++) {
for (LineSize = i; LineSize < FileSize; LineSize++) {
if (FileImage.FileType == ASCII_FILE) {
if (AsciiBuffer[LineSize] == CHAR_CR) {
FileImage.NewLineType = USE_CRLF;
break;
} else if (AsciiBuffer[LineSize] == CHAR_LF) {
break;
}
} else {
if (UnicodeBuffer[LineSize] == CHAR_CR) {
FileImage.NewLineType = USE_CRLF;
break;
} else if (UnicodeBuffer[LineSize] == CHAR_LF) {
break;
}
}
}
LineSize -= i;
Line = FileImageCreateNode ();
if (Line == NULL) {
EditorError(EFI_OUT_OF_RESOURCES,L"FileImageRead: Could Not Allocate another Line");
break;
}
Line->Buffer = AllocateZeroPool(LineSize*2+2);
if (Line->Buffer == NULL) {
EditorError(EFI_OUT_OF_RESOURCES,L"FileImageRead: Could not allocate buffer");
RemoveEntryList(&Line->Link);
break;
}
for (Line->Size = 0; Line->Size < LineSize; Line->Size++) {
if (FileImage.FileType == ASCII_FILE) {
Line->Buffer[Line->Size] = (CHAR16)AsciiBuffer[i];
} else {
Line->Buffer[Line->Size] = UnicodeBuffer[i];
}
i++;
}
Line->Size++;
if (FileImage.NewLineType == USE_CRLF) {
++i;
}
Line->Buffer[LineSize] = 0;
}
FreePool (FileBuffer);
InsertTailList(FileImage.ListHead,Blank);
MainEditor.FileBuffer->FilePosition.Row = 1;
MainEditor.FileBuffer->FilePosition.Column = 1;
MainEditor.FileBuffer->CurrentLine = FileImage.ListHead->Flink;
MainEditor.StatusBar->SetPosition(1,1);
UnicodeBuffer = PoolPrint(L"%d Lines Read",FileImage.NumLines);
MainEditor.StatusBar->SetStatusString(UnicodeBuffer);
FreePool (UnicodeBuffer);
FileImage.FileHandle->Close(FileImage.FileHandle);
FileImage.FileIsOpen = FALSE;
return EFI_SUCCESS;
}
STATIC
VOID
GetNewLine (
CHAR8 *Buffer,
UINT8 *Size
)
{
UINT8 size = 0;
if (FileImage.NewLineType == USE_CRLF) {
Buffer[size] = 0x0d;
size++;
if (FileImage.FileType == UNICODE_FILE) {
Buffer[size] = 0x00;
size++;
}
}
Buffer[size] = 0x0a;
size++;
if (FileImage.FileType == UNICODE_FILE) {
Buffer[size] = 0x00;
size++;
}
*Size = size;
}
STATIC
EFI_STATUS
FileImageWrite (
VOID
)
{
LIST_ENTRY *Link;
EFI_EDITOR_LINE *Line;
CHAR16 *Str;
VOID *Buffer;
EFI_STATUS Status;
UINTN Length = 0;
UINTN NumLines = 1;
CHAR8 NewLineBuffer[4];
UINT8 NewLineSize;
Status = FileImage.CurrentDir->Open (FileImage.CurrentDir,&FileImage.FileHandle,FileImage.FileName,FILE_READ_WRITE,0);
if (!EFI_ERROR(Status)) {
Status = FileImage.FileHandle->Delete (FileImage.FileHandle);
if (EFI_ERROR(Status)) {
EditorError(Status,L"Error Deleting File");
/* return EFI_SUCCESS; */
}
}
Status = FileImage.CurrentDir->Open(FileImage.CurrentDir,&FileImage.FileHandle,FileImage.FileName,FILE_CREATE,0);
if (EFI_ERROR(Status)) {
EditorError(Status,L"Error Accessing File");
return EFI_SUCCESS;
}
GetNewLine(NewLineBuffer,&NewLineSize);
if (FileImage.FileType == UNICODE_FILE) {
UINT8 Marker1 = 0xff,Marker2 = 0xfe;
Length = 1;
FileImage.FileHandle->Write(FileImage.FileHandle,&Length,&Marker1);
Length = 1;
FileImage.FileHandle->Write(FileImage.FileHandle,&Length,&Marker2);
}
for (Link = FileImage.ListHead->Flink;
Link != FileImage.ListHead->Blink; Link = Link->Flink) {
Line = CR(Link,EFI_EDITOR_LINE,Link,EFI_EDITOR_LINE_LIST);
Line->Buffer[Line->Size-1] = 0;
if (FileImage.FileType == ASCII_FILE) {
(CHAR8*)Buffer = AllocatePool(Line->Size);
UnicodeToAscii(Line->Buffer,Line->Size,(CHAR8*)Buffer);
Length = Line->Size - 1;
} else {
Length = (Line->Size*2) - 2;
(CHAR16*)Buffer = PoolPrint(L"%s",Line->Buffer);
}
Status = FileImage.FileHandle->Write(FileImage.FileHandle,&Length,Buffer);
FreePool(Buffer);
if (EFI_ERROR(Status)) {
EditorError(Status,L"Error Writing File");
return EFI_SUCCESS;
}
Length = NewLineSize;
Status = FileImage.FileHandle->Write(FileImage.FileHandle,&Length,NewLineBuffer);
if (EFI_ERROR(Status)) {
EditorError(Status,L"Error Writing Newline");
return EFI_SUCCESS;
}
NumLines++;
}
MainEditor.FileModified = FALSE;
MainEditor.TitleBar->Refresh();
Str = PoolPrint(L"Wrote %d Lines",NumLines);
MainEditor.StatusBar->SetStatusString(Str);
FreePool(Str);
Status = FileImage.FileHandle->Close(FileImage.FileHandle);
if ( EFI_ERROR(Status) ) {
EditorError(Status,L"Error Closing File");
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileImageClose (
VOID
)
{
FileImageDeleteLines ();
MainEditor.FileBuffer->FilePosition.Row = 1;
MainEditor.FileBuffer->FilePosition.Column = 1;
MainEditor.StatusBar->SetPosition(1,1);
MainEditor.FileBuffer->SetPosition(TEXT_START_ROW,TEXT_START_COLUMN);
MainEditor.FileModified = FALSE;
MainEditor.TitleBar->Refresh();
return EFI_SUCCESS;
}
STATIC
EFI_STATUS
FileImageSetFilename (
IN CHAR16* Filename
)
{
if (Filename == NULL) {
return EFI_LOAD_ERROR;
}
if (FileImage.FileName != NULL) {
FreePool(FileImage.FileName);
}
FileImage.FileName = PoolPrint(L"%s",Filename);
return EFI_SUCCESS;
}
STATIC
VOID
FileImageDeleteLines (
VOID
)
{
EFI_EDITOR_LINE *Line;
LIST_ENTRY *Blank;
LIST_ENTRY *Item;
Blank = FileImage.ListHead->Blink;
RemoveEntryList(Blank);
while (!IsListEmpty(FileImage.ListHead)) {
Item = FileImage.ListHead->Flink;
RemoveEntryList(Item);
Line = CR(Item,EFI_EDITOR_LINE,Link,EFI_EDITOR_LINE_LIST);
if (Line->Buffer != NULL && Line->Buffer != (CHAR16*)BAD_POINTER) {
FreePool(Line->Buffer);
}
FreePool (Line);
FileImage.NumLines--;
}
InsertTailList(FileImage.ListHead,Blank);
MainEditor.FileBuffer->CurrentLine = Blank;
FileImage.NumLines = 1;
}
STATIC
EFI_EDITOR_LINE*
FileImageCreateNode (
VOID
)
{
EFI_EDITOR_LINE *Line;
Line = AllocatePool (sizeof(EFI_EDITOR_LINE));
if ( Line == NULL ) {
EditorError(EFI_OUT_OF_RESOURCES,L"FileImageCreateNode: Could not allocate Node");
return NULL;
}
Line->Signature = EFI_EDITOR_LINE_LIST;
Line->Size = 1;
Line->Buffer = PoolPrint(L" \0");
FileImage.NumLines++;
InsertTailList(FileImage.ListHead,&Line->Link);
return Line;
}
#endif /* _LIB_FILE_IMAGE */