From 7e2ccccace24636f29ddc210b94606abd4c7e42b Mon Sep 17 00:00:00 2001 From: kx Date: Tue, 4 Jun 2024 06:43:08 +0300 Subject: Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305b --- .../UnitTestPersistenceLibSimpleFileSystem.c | 1020 ++++++++++---------- 1 file changed, 510 insertions(+), 510 deletions(-) (limited to 'UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.c') diff --git a/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.c b/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.c index 8f7f03646c..25b84c2740 100644 --- a/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.c +++ b/UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.c @@ -1,510 +1,510 @@ -/** @file - This is an instance of the Unit Test Persistence Lib that will utilize - the filesystem that a test application is running from to save a serialized - version of the internal test state in case the test needs to quit and restore. - - Copyright (c) Microsoft Corporation.
- Copyright (c) 2022, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent -**/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CACHE_FILE_SUFFIX L"_Cache.dat" - -CHAR16 *mCachePath = NULL; - -/** - Generate the file name and path to the cache file. - - @param[in] FrameworkHandle A pointer to the framework that is being persisted. - - @retval !NULL A pointer to the EFI_FILE protocol instance for the filesystem. - @retval NULL Filesystem could not be found or an error occurred. - -**/ -STATIC -CHAR16 * -GetCacheFileName ( - IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle - ) -{ - EFI_STATUS Status; - UNIT_TEST_FRAMEWORK *Framework; - EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - CHAR16 *AppPath; - CHAR16 *CacheFilePath; - CHAR16 *TestName; - UINTN DirectorySlashOffset; - UINTN CacheFilePathLength; - - Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; - AppPath = NULL; - CacheFilePath = NULL; - TestName = NULL; - - // - // First, we need to get some information from the loaded image. - // - Status = gBS->HandleProtocol ( - gImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **)&LoadedImage - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "%a - Failed to locate DevicePath for loaded image. %r\n", __func__, Status)); - return NULL; - } - - // - // Before we can start, change test name from ASCII to Unicode. - // - CacheFilePathLength = AsciiStrLen (Framework->ShortTitle) + 1; - TestName = AllocatePool (CacheFilePathLength * sizeof (CHAR16)); - if (!TestName) { - goto Exit; - } - - AsciiStrToUnicodeStrS (Framework->ShortTitle, TestName, CacheFilePathLength); - - // - // Now we should have the device path of the root device and a file path for the rest. - // In order to target the directory for the test application, we must process - // the file path a little. - // - // NOTE: This may not be necessary... Path processing functions exist... - // PathCleanUpDirectories (FileNameCopy); - // if (PathRemoveLastItem (FileNameCopy)) { - // - if (mCachePath == NULL) { - AppPath = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE); // NOTE: This must be freed. - if (AppPath == NULL) { - goto Exit; - } - - DirectorySlashOffset = StrLen (AppPath); - // - // Make sure we didn't get any weird data. - // - if (DirectorySlashOffset == 0) { - DEBUG ((DEBUG_ERROR, "%a - Weird 0-length string when processing app path.\n", __func__)); - goto Exit; - } - - // - // Now that we know we have a decent string, let's take a deeper look. - // - do { - if (AppPath[DirectorySlashOffset] == L'\\') { - break; - } - - DirectorySlashOffset--; - } while (DirectorySlashOffset > 0); - - // - // After that little maneuver, DirectorySlashOffset should be pointing at the last '\' in AppString. - // That would be the path to the parent directory that the test app is executing from. - // Let's check and make sure that's right. - // - if (AppPath[DirectorySlashOffset] != L'\\') { - DEBUG ((DEBUG_ERROR, "%a - Could not find a single directory separator in app path.\n", __func__)); - goto Exit; - } - } else { - AppPath = FullyQualifyPath (mCachePath); // NOTE: This must be freed. - if (AppPath == NULL) { - goto Exit; - } - - DirectorySlashOffset = StrLen (AppPath); - - if (AppPath[DirectorySlashOffset - 1] != L'\\') { - // Set the slash if user did not specify it on the newly allocated pool - AppPath = ReallocatePool ( - (DirectorySlashOffset + 1) * sizeof (CHAR16), - (DirectorySlashOffset + 2) * sizeof (CHAR16), - AppPath - ); - AppPath[DirectorySlashOffset] = L'\\'; - AppPath[DirectorySlashOffset + 1] = L'\0'; - } else { - // Otherwise the user input is good enough to go, mostly - DirectorySlashOffset--; - } - } - - // - // Now we know some things, we're ready to produce our output string, I think. - // - CacheFilePathLength = DirectorySlashOffset + 1; - CacheFilePathLength += StrLen (TestName); - CacheFilePathLength += StrLen (CACHE_FILE_SUFFIX); - CacheFilePathLength += 1; // Don't forget the NULL terminator. - CacheFilePath = AllocateZeroPool (CacheFilePathLength * sizeof (CHAR16)); - if (!CacheFilePath) { - goto Exit; - } - - // - // Let's produce our final path string, shall we? - // - StrnCpyS (CacheFilePath, CacheFilePathLength, AppPath, DirectorySlashOffset + 1); // Copy the path for the parent directory. - StrCatS (CacheFilePath, CacheFilePathLength, TestName); // Copy the base name for the test cache. - StrCatS (CacheFilePath, CacheFilePathLength, CACHE_FILE_SUFFIX); // Copy the file suffix. - -Exit: - // - // Free allocated buffers. - // - if (AppPath != NULL) { - FreePool (AppPath); - } - - if (TestName != NULL) { - FreePool (TestName); - } - - return CacheFilePath; -} - -/** - Determines whether a persistence cache already exists for - the given framework. - - @param[in] FrameworkHandle A pointer to the framework that is being persisted. - - @retval TRUE - @retval FALSE Cache doesn't exist or an error occurred. - -**/ -BOOLEAN -EFIAPI -DoesCacheExist ( - IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle - ) -{ - CHAR16 *FileName; - EFI_STATUS Status; - SHELL_FILE_HANDLE FileHandle; - - // - // NOTE: This devpath is allocated and must be freed. - // - FileName = GetCacheFileName (FrameworkHandle); - if (FileName == NULL) { - return FALSE; - } - - // - // Check to see whether the file exists. If the file can be opened for - // reading, it exists. Otherwise, probably not. - // - Status = ShellOpenFileByName ( - FileName, - &FileHandle, - EFI_FILE_MODE_READ, - 0 - ); - if (!EFI_ERROR (Status)) { - ShellCloseFile (&FileHandle); - } - - if (FileName != NULL) { - FreePool (FileName); - } - - DEBUG ((DEBUG_VERBOSE, "%a - Returning %d\n", __func__, !EFI_ERROR (Status))); - - return (!EFI_ERROR (Status)); -} - -/** - Will save the data associated with an internal Unit Test Framework - state in a manner that can persist a Unit Test Application quit or - even a system reboot. - - @param[in] FrameworkHandle A pointer to the framework that is being persisted. - @param[in] SaveData A pointer to the buffer containing the serialized - framework internal state. - @param[in] SaveStateSize The size of SaveData in bytes. - - @retval EFI_SUCCESS Data is persisted and the test can be safely quit. - @retval Others Data is not persisted and test cannot be resumed upon exit. - -**/ -EFI_STATUS -EFIAPI -SaveUnitTestCache ( - IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle, - IN VOID *SaveData, - IN UINTN SaveStateSize - ) -{ - CHAR16 *FileName; - EFI_STATUS Status; - SHELL_FILE_HANDLE FileHandle; - UINTN WriteCount; - - // - // Check the inputs for sanity. - // - if ((FrameworkHandle == NULL) || (SaveData == NULL)) { - return EFI_INVALID_PARAMETER; - } - - // - // Determine the path for the cache file. - // NOTE: This devpath is allocated and must be freed. - // - FileName = GetCacheFileName (FrameworkHandle); - if (FileName == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // First lets open the file if it exists so we can delete it...This is the work around for truncation - // - Status = ShellOpenFileByName ( - FileName, - &FileHandle, - (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE), - 0 - ); - - if (!EFI_ERROR (Status)) { - // - // If file handle above was opened it will be closed by the delete. - // - Status = ShellDeleteFile (&FileHandle); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a failed to delete file %r\n", __func__, Status)); - } - } - - // - // Now that we know the path to the file... let's open it for writing. - // - Status = ShellOpenFileByName ( - FileName, - &FileHandle, - (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), - 0 - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __func__, Status)); - goto Exit; - } - - // - // Write the data to the file. - // - WriteCount = SaveStateSize; - DEBUG ((DEBUG_INFO, "%a - Writing %d bytes to file...\n", __func__, WriteCount)); - Status = ShellWriteFile ( - FileHandle, - &WriteCount, - SaveData - ); - - if (EFI_ERROR (Status) || (WriteCount != SaveStateSize)) { - DEBUG ((DEBUG_ERROR, "%a - Writing to file failed! %r\n", __func__, Status)); - } else { - DEBUG ((DEBUG_INFO, "%a - SUCCESS!\n", __func__)); - } - - // - // No matter what, we should probably close the file. - // - ShellCloseFile (&FileHandle); - -Exit: - if (FileName != NULL) { - FreePool (FileName); - } - - return Status; -} - -/** - Will retrieve any cached state associated with the given framework. - Will allocate a buffer to hold the loaded data. - - @param[in] FrameworkHandle A pointer to the framework that is being persisted. - @param[out] SaveData A pointer pointer that will be updated with the address - of the loaded data buffer. - @param[out] SaveStateSize Return the size of SaveData in bytes. - - @retval EFI_SUCCESS Data has been loaded successfully and SaveData is updated - with a pointer to the buffer. - @retval Others An error has occurred and no data has been loaded. SaveData - is set to NULL. - -**/ -EFI_STATUS -EFIAPI -LoadUnitTestCache ( - IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle, - OUT VOID **SaveData, - OUT UINTN *SaveStateSize - ) -{ - EFI_STATUS Status; - CHAR16 *FileName; - SHELL_FILE_HANDLE FileHandle; - BOOLEAN IsFileOpened; - UINT64 LargeFileSize; - UINTN FileSize; - VOID *Buffer; - - IsFileOpened = FALSE; - Buffer = NULL; - - // - // Check the inputs for sanity. - // - if ((FrameworkHandle == NULL) || (SaveData == NULL)) { - return EFI_INVALID_PARAMETER; - } - - // - // Determine the path for the cache file. - // NOTE: This devpath is allocated and must be freed. - // - FileName = GetCacheFileName (FrameworkHandle); - if (FileName == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Now that we know the path to the file... let's open it for writing. - // - Status = ShellOpenFileByName ( - FileName, - &FileHandle, - EFI_FILE_MODE_READ, - 0 - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __func__, Status)); - goto Exit; - } else { - IsFileOpened = TRUE; - } - - // - // Now that the file is opened, we need to determine how large a buffer we need. - // - Status = ShellGetFileSize (FileHandle, &LargeFileSize); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a - Failed to determine file size! %r\n", __func__, Status)); - goto Exit; - } - - // - // Now that we know the size, let's allocated a buffer to hold the contents. - // - FileSize = (UINTN)LargeFileSize; // You know what... if it's too large, this lib don't care. - *SaveStateSize = FileSize; - Buffer = AllocatePool (FileSize); - if (Buffer == NULL) { - DEBUG ((DEBUG_ERROR, "%a - Failed to allocate a pool to hold the file contents! %r\n", __func__, Status)); - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - // - // Finally, let's read the data. - // - Status = ShellReadFile (FileHandle, &FileSize, Buffer); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a - Failed to read the file contents! %r\n", __func__, Status)); - } - -Exit: - // - // Free allocated buffers - // - if (FileName != NULL) { - FreePool (FileName); - } - - if (IsFileOpened) { - ShellCloseFile (&FileHandle); - } - - // - // If we're returning an error, make sure - // the state is sane. - if (EFI_ERROR (Status) && (Buffer != NULL)) { - FreePool (Buffer); - Buffer = NULL; - } - - *SaveData = Buffer; - return Status; -} - -/** - Shell based UnitTestPersistenceLib library constructor. - - @param[in] ImageHandle The firmware allocated handle for the EFI image. - @param[in] SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The constructor finished successfully. - @retval Others Error codes returned from gBS->HandleProtocol. - **/ -EFI_STATUS -EFIAPI -UnitTestPersistenceLibConstructor ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - UINTN Index; - UINTN Argc; - CHAR16 **Argv; - EFI_STATUS Status; - EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters; - - Status = gBS->HandleProtocol ( - gImageHandle, - &gEfiShellParametersProtocolGuid, - (VOID **)&ShellParameters - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - goto Done; - } - - Argc = ShellParameters->Argc; - Argv = ShellParameters->Argv; - - Status = EFI_SUCCESS; - if ((Argc > 1) && (Argv != NULL)) { - // This might be our cue, check for whether we need to do anything - for (Index = 1; Index < Argc; Index++) { - if (StrCmp (Argv[Index], L"--CachePath") == 0) { - // Need to update the potential cache path to designated path - if (Index < Argc - 1) { - mCachePath = Argv[Index + 1]; - } else { - Print (L" --CachePath \n"); - } - } - } - } - -Done: - return Status; -} +/** @file + This is an instance of the Unit Test Persistence Lib that will utilize + the filesystem that a test application is running from to save a serialized + version of the internal test state in case the test needs to quit and restore. + + Copyright (c) Microsoft Corporation.
+ Copyright (c) 2022, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CACHE_FILE_SUFFIX L"_Cache.dat" + +CHAR16 *mCachePath = NULL; + +/** + Generate the file name and path to the cache file. + + @param[in] FrameworkHandle A pointer to the framework that is being persisted. + + @retval !NULL A pointer to the EFI_FILE protocol instance for the filesystem. + @retval NULL Filesystem could not be found or an error occurred. + +**/ +STATIC +CHAR16 * +GetCacheFileName ( + IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle + ) +{ + EFI_STATUS Status; + UNIT_TEST_FRAMEWORK *Framework; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + CHAR16 *AppPath; + CHAR16 *CacheFilePath; + CHAR16 *TestName; + UINTN DirectorySlashOffset; + UINTN CacheFilePathLength; + + Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; + AppPath = NULL; + CacheFilePath = NULL; + TestName = NULL; + + // + // First, we need to get some information from the loaded image. + // + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a - Failed to locate DevicePath for loaded image. %r\n", __func__, Status)); + return NULL; + } + + // + // Before we can start, change test name from ASCII to Unicode. + // + CacheFilePathLength = AsciiStrLen (Framework->ShortTitle) + 1; + TestName = AllocatePool (CacheFilePathLength * sizeof (CHAR16)); + if (!TestName) { + goto Exit; + } + + AsciiStrToUnicodeStrS (Framework->ShortTitle, TestName, CacheFilePathLength); + + // + // Now we should have the device path of the root device and a file path for the rest. + // In order to target the directory for the test application, we must process + // the file path a little. + // + // NOTE: This may not be necessary... Path processing functions exist... + // PathCleanUpDirectories (FileNameCopy); + // if (PathRemoveLastItem (FileNameCopy)) { + // + if (mCachePath == NULL) { + AppPath = ConvertDevicePathToText (LoadedImage->FilePath, TRUE, TRUE); // NOTE: This must be freed. + if (AppPath == NULL) { + goto Exit; + } + + DirectorySlashOffset = StrLen (AppPath); + // + // Make sure we didn't get any weird data. + // + if (DirectorySlashOffset == 0) { + DEBUG ((DEBUG_ERROR, "%a - Weird 0-length string when processing app path.\n", __func__)); + goto Exit; + } + + // + // Now that we know we have a decent string, let's take a deeper look. + // + do { + if (AppPath[DirectorySlashOffset] == L'\\') { + break; + } + + DirectorySlashOffset--; + } while (DirectorySlashOffset > 0); + + // + // After that little maneuver, DirectorySlashOffset should be pointing at the last '\' in AppString. + // That would be the path to the parent directory that the test app is executing from. + // Let's check and make sure that's right. + // + if (AppPath[DirectorySlashOffset] != L'\\') { + DEBUG ((DEBUG_ERROR, "%a - Could not find a single directory separator in app path.\n", __func__)); + goto Exit; + } + } else { + AppPath = FullyQualifyPath (mCachePath); // NOTE: This must be freed. + if (AppPath == NULL) { + goto Exit; + } + + DirectorySlashOffset = StrLen (AppPath); + + if (AppPath[DirectorySlashOffset - 1] != L'\\') { + // Set the slash if user did not specify it on the newly allocated pool + AppPath = ReallocatePool ( + (DirectorySlashOffset + 1) * sizeof (CHAR16), + (DirectorySlashOffset + 2) * sizeof (CHAR16), + AppPath + ); + AppPath[DirectorySlashOffset] = L'\\'; + AppPath[DirectorySlashOffset + 1] = L'\0'; + } else { + // Otherwise the user input is good enough to go, mostly + DirectorySlashOffset--; + } + } + + // + // Now we know some things, we're ready to produce our output string, I think. + // + CacheFilePathLength = DirectorySlashOffset + 1; + CacheFilePathLength += StrLen (TestName); + CacheFilePathLength += StrLen (CACHE_FILE_SUFFIX); + CacheFilePathLength += 1; // Don't forget the NULL terminator. + CacheFilePath = AllocateZeroPool (CacheFilePathLength * sizeof (CHAR16)); + if (!CacheFilePath) { + goto Exit; + } + + // + // Let's produce our final path string, shall we? + // + StrnCpyS (CacheFilePath, CacheFilePathLength, AppPath, DirectorySlashOffset + 1); // Copy the path for the parent directory. + StrCatS (CacheFilePath, CacheFilePathLength, TestName); // Copy the base name for the test cache. + StrCatS (CacheFilePath, CacheFilePathLength, CACHE_FILE_SUFFIX); // Copy the file suffix. + +Exit: + // + // Free allocated buffers. + // + if (AppPath != NULL) { + FreePool (AppPath); + } + + if (TestName != NULL) { + FreePool (TestName); + } + + return CacheFilePath; +} + +/** + Determines whether a persistence cache already exists for + the given framework. + + @param[in] FrameworkHandle A pointer to the framework that is being persisted. + + @retval TRUE + @retval FALSE Cache doesn't exist or an error occurred. + +**/ +BOOLEAN +EFIAPI +DoesCacheExist ( + IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle + ) +{ + CHAR16 *FileName; + EFI_STATUS Status; + SHELL_FILE_HANDLE FileHandle; + + // + // NOTE: This devpath is allocated and must be freed. + // + FileName = GetCacheFileName (FrameworkHandle); + if (FileName == NULL) { + return FALSE; + } + + // + // Check to see whether the file exists. If the file can be opened for + // reading, it exists. Otherwise, probably not. + // + Status = ShellOpenFileByName ( + FileName, + &FileHandle, + EFI_FILE_MODE_READ, + 0 + ); + if (!EFI_ERROR (Status)) { + ShellCloseFile (&FileHandle); + } + + if (FileName != NULL) { + FreePool (FileName); + } + + DEBUG ((DEBUG_VERBOSE, "%a - Returning %d\n", __func__, !EFI_ERROR (Status))); + + return (!EFI_ERROR (Status)); +} + +/** + Will save the data associated with an internal Unit Test Framework + state in a manner that can persist a Unit Test Application quit or + even a system reboot. + + @param[in] FrameworkHandle A pointer to the framework that is being persisted. + @param[in] SaveData A pointer to the buffer containing the serialized + framework internal state. + @param[in] SaveStateSize The size of SaveData in bytes. + + @retval EFI_SUCCESS Data is persisted and the test can be safely quit. + @retval Others Data is not persisted and test cannot be resumed upon exit. + +**/ +EFI_STATUS +EFIAPI +SaveUnitTestCache ( + IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle, + IN VOID *SaveData, + IN UINTN SaveStateSize + ) +{ + CHAR16 *FileName; + EFI_STATUS Status; + SHELL_FILE_HANDLE FileHandle; + UINTN WriteCount; + + // + // Check the inputs for sanity. + // + if ((FrameworkHandle == NULL) || (SaveData == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Determine the path for the cache file. + // NOTE: This devpath is allocated and must be freed. + // + FileName = GetCacheFileName (FrameworkHandle); + if (FileName == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // First lets open the file if it exists so we can delete it...This is the work around for truncation + // + Status = ShellOpenFileByName ( + FileName, + &FileHandle, + (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE), + 0 + ); + + if (!EFI_ERROR (Status)) { + // + // If file handle above was opened it will be closed by the delete. + // + Status = ShellDeleteFile (&FileHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a failed to delete file %r\n", __func__, Status)); + } + } + + // + // Now that we know the path to the file... let's open it for writing. + // + Status = ShellOpenFileByName ( + FileName, + &FileHandle, + (EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE), + 0 + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __func__, Status)); + goto Exit; + } + + // + // Write the data to the file. + // + WriteCount = SaveStateSize; + DEBUG ((DEBUG_INFO, "%a - Writing %d bytes to file...\n", __func__, WriteCount)); + Status = ShellWriteFile ( + FileHandle, + &WriteCount, + SaveData + ); + + if (EFI_ERROR (Status) || (WriteCount != SaveStateSize)) { + DEBUG ((DEBUG_ERROR, "%a - Writing to file failed! %r\n", __func__, Status)); + } else { + DEBUG ((DEBUG_INFO, "%a - SUCCESS!\n", __func__)); + } + + // + // No matter what, we should probably close the file. + // + ShellCloseFile (&FileHandle); + +Exit: + if (FileName != NULL) { + FreePool (FileName); + } + + return Status; +} + +/** + Will retrieve any cached state associated with the given framework. + Will allocate a buffer to hold the loaded data. + + @param[in] FrameworkHandle A pointer to the framework that is being persisted. + @param[out] SaveData A pointer pointer that will be updated with the address + of the loaded data buffer. + @param[out] SaveStateSize Return the size of SaveData in bytes. + + @retval EFI_SUCCESS Data has been loaded successfully and SaveData is updated + with a pointer to the buffer. + @retval Others An error has occurred and no data has been loaded. SaveData + is set to NULL. + +**/ +EFI_STATUS +EFIAPI +LoadUnitTestCache ( + IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle, + OUT VOID **SaveData, + OUT UINTN *SaveStateSize + ) +{ + EFI_STATUS Status; + CHAR16 *FileName; + SHELL_FILE_HANDLE FileHandle; + BOOLEAN IsFileOpened; + UINT64 LargeFileSize; + UINTN FileSize; + VOID *Buffer; + + IsFileOpened = FALSE; + Buffer = NULL; + + // + // Check the inputs for sanity. + // + if ((FrameworkHandle == NULL) || (SaveData == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Determine the path for the cache file. + // NOTE: This devpath is allocated and must be freed. + // + FileName = GetCacheFileName (FrameworkHandle); + if (FileName == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Now that we know the path to the file... let's open it for writing. + // + Status = ShellOpenFileByName ( + FileName, + &FileHandle, + EFI_FILE_MODE_READ, + 0 + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a - Opening file for writing failed! %r\n", __func__, Status)); + goto Exit; + } else { + IsFileOpened = TRUE; + } + + // + // Now that the file is opened, we need to determine how large a buffer we need. + // + Status = ShellGetFileSize (FileHandle, &LargeFileSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a - Failed to determine file size! %r\n", __func__, Status)); + goto Exit; + } + + // + // Now that we know the size, let's allocated a buffer to hold the contents. + // + FileSize = (UINTN)LargeFileSize; // You know what... if it's too large, this lib don't care. + *SaveStateSize = FileSize; + Buffer = AllocatePool (FileSize); + if (Buffer == NULL) { + DEBUG ((DEBUG_ERROR, "%a - Failed to allocate a pool to hold the file contents! %r\n", __func__, Status)); + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + // + // Finally, let's read the data. + // + Status = ShellReadFile (FileHandle, &FileSize, Buffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a - Failed to read the file contents! %r\n", __func__, Status)); + } + +Exit: + // + // Free allocated buffers + // + if (FileName != NULL) { + FreePool (FileName); + } + + if (IsFileOpened) { + ShellCloseFile (&FileHandle); + } + + // + // If we're returning an error, make sure + // the state is sane. + if (EFI_ERROR (Status) && (Buffer != NULL)) { + FreePool (Buffer); + Buffer = NULL; + } + + *SaveData = Buffer; + return Status; +} + +/** + Shell based UnitTestPersistenceLib library constructor. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor finished successfully. + @retval Others Error codes returned from gBS->HandleProtocol. + **/ +EFI_STATUS +EFIAPI +UnitTestPersistenceLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + UINTN Index; + UINTN Argc; + CHAR16 **Argv; + EFI_STATUS Status; + EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters; + + Status = gBS->HandleProtocol ( + gImageHandle, + &gEfiShellParametersProtocolGuid, + (VOID **)&ShellParameters + ); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + goto Done; + } + + Argc = ShellParameters->Argc; + Argv = ShellParameters->Argv; + + Status = EFI_SUCCESS; + if ((Argc > 1) && (Argv != NULL)) { + // This might be our cue, check for whether we need to do anything + for (Index = 1; Index < Argc; Index++) { + if (StrCmp (Argv[Index], L"--CachePath") == 0) { + // Need to update the potential cache path to designated path + if (Index < Argc - 1) { + mCachePath = Argv[Index + 1]; + } else { + Print (L" --CachePath \n"); + } + } + } + } + +Done: + return Status; +} -- cgit v1.2.3