From b87fc6b140772ba3017de311c7063c259424264c Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 15 Aug 2016 17:11:31 +0200 Subject: First public release. Used by VeraCrypt 1.18. --- Library/CommonLib/EfiFile.c | 350 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 Library/CommonLib/EfiFile.c (limited to 'Library/CommonLib/EfiFile.c') diff --git a/Library/CommonLib/EfiFile.c b/Library/CommonLib/EfiFile.c new file mode 100644 index 0000000..b1e2076 --- /dev/null +++ b/Library/CommonLib/EfiFile.c @@ -0,0 +1,350 @@ +/** @file +EFI file system helpers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// EFI file +////////////////////////////////////////////////////////////////////////// + +EFI_FILE* gFileRoot = NULL; +EFI_HANDLE gFileRootHandle = NULL; + +EFI_HANDLE* gFSHandles = NULL; +UINTN gFSCount = 0; + +EFI_STATUS +InitFS() { + EFI_STATUS res; + EfiGetHandles(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, 0, &gFSHandles, &gFSCount); + res = EfiGetStartDevice(&gFileRootHandle); + if (!EFI_ERROR(res)) { + res = FileOpenRoot(gFileRootHandle, &gFileRoot); + } + return res; +} + +EFI_STATUS +FileOpenRoot( + IN EFI_HANDLE rootHandle, + OUT EFI_FILE** rootFile) +{ + EFI_STATUS res = 0; + EFI_FILE_IO_INTERFACE* fSysProtocol = NULL; + res = gBS->HandleProtocol(rootHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&fSysProtocol); + if (res == RETURN_SUCCESS && fSysProtocol != NULL) { + res = fSysProtocol->OpenVolume(fSysProtocol, rootFile); + } + return res; +} + +EFI_STATUS +FileOpen( + IN EFI_FILE* root, + IN CHAR16* name, + OUT EFI_FILE** file, + IN UINT64 mode, + IN UINT64 attributes + ) +{ + EFI_STATUS res; + + if (!name || !file) { return EFI_INVALID_PARAMETER; } + if (!root) root = gFileRoot; + if (!root) { return EFI_INVALID_PARAMETER; } + if (mode == 0) { + mode = EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE; + } + res = root->Open(root, file, name, mode , attributes); + return res; +} + +EFI_STATUS +FileClose( + IN EFI_FILE* f) +{ + if (!f) { return EFI_INVALID_PARAMETER; } + return f->Close(f); +} + +EFI_STATUS +FileDelete( + IN EFI_FILE* root, + IN CHAR16* name + ) +{ + EFI_FILE* f; + EFI_STATUS res; + if (!name) { return EFI_INVALID_PARAMETER; } + res = FileOpen(root, name, &f, 0, 0); + if (EFI_ERROR(res)) { + return res; + } + res = f->Delete(f); +// f->Close(f); + return res; +} + +EFI_STATUS +FileRead( + IN EFI_FILE* f, + OUT VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position) +{ + EFI_STATUS res; + + if (!f || !data || !bytes) { + return EFI_INVALID_PARAMETER; + } + if (position != NULL) { + res = f->SetPosition(f, *position); + if (EFI_ERROR(res)) { + return res; + } + } + res = f->Read(f, bytes, data); + if (position != NULL) { + f->GetPosition(f, position); + } + return res; +} + +EFI_STATUS +FileWrite( + IN EFI_FILE* f, + IN VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position) +{ + EFI_STATUS res; + + if (!f || !data || !bytes) { + return EFI_INVALID_PARAMETER; + } + if (position != NULL) { + res = f->SetPosition(f, *position); + if (EFI_ERROR(res)) { + return res; + } + } + res = f->Write(f, bytes, data); + if (position != NULL) { + f->GetPosition(f, position); + } + return res; +} + +EFI_STATUS +FileGetInfo( + IN EFI_FILE* f, + OUT EFI_FILE_INFO** info, + OUT UINTN* size + ) +{ + EFI_STATUS res; + UINTN sz = 0; + if (!f || !info) { return EFI_INVALID_PARAMETER; } + res = f->GetInfo(f, &gEfiFileInfoGuid, &sz, NULL); + if (res == RETURN_BUFFER_TOO_SMALL) { + *info = (EFI_FILE_INFO*)MEM_ALLOC(sz); + if (!(*info)) { + return res; + } + res = f->GetInfo(f, &gEfiFileInfoGuid, &sz, *info); + if (EFI_ERROR(res)) { + MEM_FREE(*info); + *info = NULL; + sz = 0; + } + } + if (size) { + *size = sz; + } + return res; +} + +EFI_STATUS +FileGetSize( + IN EFI_FILE* f, + OUT UINTN* size + ) +{ + EFI_STATUS res; + EFI_FILE_INFO* info = NULL; + if (!f || !size) { return EFI_INVALID_PARAMETER; } + res = FileGetInfo(f, &info, NULL); + if (!EFI_ERROR(res)) { + *size = (UINTN)info->FileSize; + MEM_FREE(info); + } + return res; +} + +EFI_STATUS +FileLoad( + IN EFI_FILE* root, + IN CHAR16* name, + OUT VOID** data, + OUT UINTN* size + ) +{ + EFI_FILE* file; + EFI_STATUS res; + UINTN sz; + if (!data) { + return EFI_INVALID_PARAMETER; + } + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetSize(file, &sz); + if (EFI_ERROR(res)) { + FileClose(file); + return res; + } + *data = MEM_ALLOC(sz); + if (*data == NULL) { + FileClose(file); + return EFI_BUFFER_TOO_SMALL; + } + res = FileRead(file, *data, &sz, NULL); + if (EFI_ERROR(res)) { + FileClose(file); + MEM_FREE(*data); + return res; + } + FileClose(file); + if (size != NULL) { + *size = sz; + } + return res; +} + +EFI_STATUS +FileSave( + IN EFI_FILE* root, + IN CHAR16* name, + IN VOID* data, + IN UINTN size + ) +{ + EFI_FILE* file; + EFI_STATUS res; + UINTN sz = size; + if (!data || !name) { return EFI_INVALID_PARAMETER; } + FileDelete(root, name); + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR(res)) return res; + res = FileWrite(file, data, &sz, NULL); + FileClose(file); + return res; +} + +EFI_STATUS +FileExist( + IN EFI_FILE* root, + IN CHAR16* name) +{ + EFI_FILE* file; + EFI_STATUS res; + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + FileClose(file); + return EFI_SUCCESS; +} + +EFI_STATUS +FileRename( + IN EFI_FILE* root, + IN CHAR16* src, + IN CHAR16* dst) +{ + EFI_STATUS res; + EFI_FILE* file; + EFI_FILE_INFO* info = NULL; + UINTN sz; + EFI_FILE_INFO* dstinfo = NULL; + UINTN dstinfosz; + + res = FileOpen(root, src, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetInfo(file, &info, &sz); + if (EFI_ERROR(res)) return res; + dstinfosz = SIZE_OF_EFI_FILE_INFO + StrSize(dst); + dstinfo = (EFI_FILE_INFO*)MEM_ALLOC(dstinfosz); + if (dstinfo != NULL) { + CopyMem(dstinfo, info, SIZE_OF_EFI_FILE_INFO); + dstinfo->FileName[0] = 0; + StrCat(dstinfo->FileName, dst); + res = file->SetInfo(file, &gEfiFileInfoGuid, dstinfosz, dstinfo); + } else { + res = EFI_BUFFER_TOO_SMALL; + } + + MEM_FREE(info); + MEM_FREE(dstinfo); + FileClose(file); + return res; +} + +EFI_STATUS +FileCopy( + IN EFI_FILE* srcroot, + IN CHAR16* src, + IN EFI_FILE* dstroot, + IN CHAR16* dst, + IN UINTN bufSz + ) +{ + EFI_STATUS res; + EFI_FILE* srcfile = NULL; + EFI_FILE* dstfile = NULL; + UINTN remains; + CHAR8* data = NULL; + UINTN datasz = bufSz; + + res = FileOpen(srcroot, src, &srcfile, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetSize(srcfile, &remains); + if (EFI_ERROR(res)) return res; + + data = (CHAR8*)MEM_ALLOC(bufSz); + if (data == NULL) { + res = EFI_BUFFER_TOO_SMALL; + goto copyerr; + } + + res = FileOpen(dstroot, dst, &dstfile, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) goto copyerr; + + do { + datasz = remains > bufSz ? bufSz : remains; + res =FileRead(srcfile, data, &datasz, NULL); + if (EFI_ERROR(res)) goto copyerr; + res = FileWrite(dstfile, data, &datasz, NULL); + if (EFI_ERROR(res)) goto copyerr; + remains -= datasz; + } while (remains > 0); + +copyerr: + MEM_FREE(data); + FileClose(srcfile); + FileClose(dstfile); + return res; +} -- cgit v1.2.3