diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin.sln b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin.sln new file mode 100644 index 0000000000..696b697898 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AdvLoggerDumpWin", "AdvLoggerDumpWin\AdvLoggerDumpWin.vcxproj", "{F983380B-B6C4-44EE-8835-0137E0876321}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|ARM64.Build.0 = Debug|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x64.ActiveCfg = Debug|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x64.Build.0 = Debug|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x86.ActiveCfg = Debug|Win32 + {F983380B-B6C4-44EE-8835-0137E0876321}.Debug|x86.Build.0 = Debug|Win32 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|ARM64.ActiveCfg = Release|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|ARM64.Build.0 = Release|ARM64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x64.ActiveCfg = Release|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x64.Build.0 = Release|x64 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x86.ActiveCfg = Release|Win32 + {F983380B-B6C4-44EE-8835-0137E0876321}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {514003CD-1327-488E-9C4E-8761C728A1E3} + EndGlobalSection +EndGlobal diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj new file mode 100644 index 0000000000..6faf8b2766 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/AdvLoggerDumpWin.vcxproj @@ -0,0 +1,160 @@ + + + + + true + true + true + true + 15.0 + {f983380b-b6c4-44ee-8835-0137e0876321} + Win32Proj + AdvLoggerDumpWin + 10.0 + 10.0.17134.0 + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + Application + v143 + v142 + v141 + v140 + Unicode + + + true + true + + + false + true + true + + + Static + + + Static + + + Static + + + + + + + + + + + + + + + + NotUsing + + + + + _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) + Level4 + %(AdditionalOptions) /permissive- /bigobj + + + + + Disabled + _DEBUG;%(PreprocessorDefinitions) + ProgramDatabase + MultiThreadedDebugDLL + false + ProgramDatabase + false + + + Console + false + RequireAdministrator + RequireAdministrator + true + + + + + WIN32;%(PreprocessorDefinitions) + + + + + MaxSpeed + true + true + NDEBUG;%(PreprocessorDefinitions) + MultiThreaded + MultiThreaded + Default + false + + + Console + false + + + false + + + RequireAdministrator + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/ReadMe.md b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/ReadMe.md new file mode 100644 index 0000000000..ab916944ab --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/ReadMe.md @@ -0,0 +1,32 @@ +# AdvLoggerPkg - AdvLoggerDumpWin +AdvLoggerDumpWin is used to retrieve the advanced UEFI debug log stored in system memory. + +## About +If the Advanced Logger is enabled, the debug log is stored in memory and is available through the UEFI +Variable store. +This tool creates a Windows executable that writes the UEFI variable data to a binary log file. As the +log in memory has additional metadata and alignment structure, DecodeUefiLog.py (in AdvLoggerPkg) +parses the in-memory UefiLog to a text stream and writes the decoded log to a local file. The Python +script can be used to both retrieve the log and decode it. +AdvLoggerDumpWin is able to be used in systems without Python. + +## Usage: +With administrator privileges, run the executable. +In an administrator command prompt: +``` +AdvLoggerDumpWin.exe +``` +The program creates a new log file `new_logfile.bin` in the current directory. + + +## Building +To build the project, open the solution file in Visual Studio. +Ensure you have the necessary dependencies. + * Microsoft.Windows.CppWinRT package + * Windows SDK + * VS build tools + + +## Copyright +Copyright (C) Microsoft Corporation. All rights reserved. +SPDX-License-Identifier: BSD-2-Clause-Patent \ No newline at end of file diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.cpp b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.cpp new file mode 100644 index 0000000000..d743400a03 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.cpp @@ -0,0 +1,161 @@ +#include "main.h" +#include +#include +#include +#include +#include +#include + +using namespace winrt; +using namespace Windows::Foundation; +using namespace std; + +// +// Elevate current process system environment privileges to access UEFI variables +// +static int ElevateCurrentPrivileges() +{ + HANDLE ProcessHandle = GetCurrentProcess(); + DWORD DesiredAccess = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY;; + HANDLE hProcessToken; + TOKEN_PRIVILEGES tp; + LUID luid; + int Status = 0; + + if (!LookupPrivilegeValue(NULL, L"SeSystemEnvironmentPrivilege", &luid)) { + Status = GetLastError(); + cout << "Failed to lookup privilege value. Errno " << Status << endl; + return Status; + } + + if (!OpenProcessToken(ProcessHandle, DesiredAccess, &hProcessToken)) { + Status = GetLastError(); + cout << "Failed to open process token. Errno " << Status << endl; + return Status; + } + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)) { + Status = GetLastError(); + cout << "Failed to adjust token privileges. Errno " << Status << endl; + return Status; + } + + if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { + Status = (int)ERROR_NOT_ALL_ASSIGNED; + cout << "The token does not have the specified privilege. Errno " << Status << endl; + return Status; + } + + CloseHandle(ProcessHandle); + return SUCCESS; +} + +// +// Create log file by retrieving AdvancedLogger variables from UEFI interface +// +int ReadLogFromUefiInterface(fstream& lfile) +{ + int Status = 0; + int i = 0; + DWORD length = 0; + DWORD err = 0; + + stringstream varName; + char* varBuffer = (char *) malloc(MAX_VAR_LENGTH + 1); + + // string to LPCWSTR conversion + string tmpGuid = "{a021bf2b-34ed-4a98-859c-420ef94f3e94}"; + wstring tmpGuidW = wstring(tmpGuid.begin(), tmpGuid.end()); + LPCWSTR guid = tmpGuidW.c_str(); + + // + // Parse variables by index until reached end of log + // + while (Status == 0) { + string tmpVarName = "V" + to_string(i); + wstring tmpVarNameW = wstring(tmpVarName.begin(), tmpVarName.end()); + LPCWSTR varNameConst = tmpVarNameW.c_str(); + + // Retrieve one advanced logger indexed variable via kernel32 API + length = GetFirmwareEnvironmentVariableW(varNameConst, guid, varBuffer, MAX_VAR_LENGTH); + + if (length == 0) { + err = GetLastError(); + + // If error is ERROR_NOT_FOUND (203), reached end of variables + if (err != 203) { + Status = EFI_ERROR; + cout << "Error reading variable " << tmpVarName << " errno: " << err << endl; + return Status; + } + else { + Status = (int)err; + } + } + + if (Status == 0) { + i += 1; + streamsize varSize = (streamsize)length; + lfile.write(varBuffer, varSize); + if (lfile.fail()) { + cout << "Failed to write to file\n"; + Status = CONS_ERROR; + return Status; + } + } + else if (i == 0) { + cout << "No variables found.\n"; + return Status; + } + else { + cout << i << " variables read. " << lfile.tellg() << " chars written.\n"; + } + + if (varBuffer) { + ZeroMemory(varBuffer, MAX_VAR_LENGTH); + } + } + + free(varBuffer); + return SUCCESS; +} + +int main() +{ + fstream logfile; + const char* newRawFilename = ".\\new_logfile.bin"; + int Status = 0; + + Status = ElevateCurrentPrivileges(); + if (Status !=0) { + cout << "Failed to elevate privileges, errno:" << Status << endl; + return Status; + } + + // Create new binary logfile + logfile.open(newRawFilename, ios::out | ios::binary); + if (!logfile) { + cout << "Error opening file.\n"; + Status = FILE_ERROR; + return Status; + } + + Status = ReadLogFromUefiInterface(logfile); + if (Status != SUCCESS) { + cerr << "Error reading log, exiting.\n"; + return LOG_ERROR; + } + + logfile.close(); + if (logfile.fail()) { + cout << "Error closing file.\n"; + return FILE_ERROR; + } + + return SUCCESS; +} + \ No newline at end of file diff --git a/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.h b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.h new file mode 100644 index 0000000000..7d3ad496d5 --- /dev/null +++ b/AdvLoggerPkg/Application/Windows/AdvLoggerDumpWin/main.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include + +#define EFI_ERROR 1 +#define CONS_ERROR 2 +#define FILE_ERROR 3 +#define LOG_ERROR 4 +#define SUCCESS 0 +#define MAX_VAR_LENGTH 1024*1024 \ No newline at end of file