/*++ 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 */