|
// AMDResetStatus.cpp : Gets the reset reason on AMD systems |
|
// |
|
// Parts copied from https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/commit/?id=b343579de7b250101e4ed6c354b4c1fa986973a7 |
|
|
|
#include <iostream> |
|
#include <filesystem> |
|
#include <fstream> |
|
#include "Windows.h" |
|
#include "PawnIOLib.h" |
|
|
|
#define BIT(nr) (1UL << (nr)) |
|
|
|
constexpr const char* filename = "AMDReset.bin"; |
|
|
|
const char* const s5_reset_reason_txt[] = { |
|
"thermal pin BP_THERMTRIP_L was tripped", // index 0 |
|
"power button was pressed for 4 seconds", // index 1 |
|
"shutdown pin was shorted", // index 2 |
|
nullptr, // index 3 (reserved) |
|
"remote ASF power off command was received", // index 4 |
|
nullptr, // index 5 (reserved) |
|
nullptr, // index 6 (reserved) |
|
nullptr, // index 7 (reserved) |
|
nullptr, // index 8 (reserved) |
|
"internal CPU thermal limit was tripped", // index 9 |
|
nullptr, // index 10 (reserved) |
|
nullptr, // index 11 (reserved) |
|
nullptr, // index 12 (reserved) |
|
nullptr, // index 13 (reserved) |
|
nullptr, // index 14 (pmeturnofftime) |
|
nullptr, // index 15 (pmeturnofftime) |
|
"system reset pin BP_SYS_RST_L was tripped", // index 16 |
|
"software issued PCI reset", // index 17 |
|
"software wrote 0x4 (init) to reset control register 0xCF9", // index 18 |
|
"software wrote 0x6 (warm reset) to reset control register 0xCF9", // index 19 |
|
"software wrote 0xE (cold reset) to reset control register 0xCF9", // index 20 |
|
"ACPI power state transition occurred", // index 21 |
|
"keyboard reset pin KB_RST_L was asserted", // index 22 |
|
"internal CPU shutdown event occurred", // index 23 |
|
"system failed to boot before failed boot timer expired", // index 24 |
|
"hardware watchdog timer expired", // index 25 |
|
"remote ASF reset command was received", // index 26 |
|
"an uncorrected error caused a data fabric sync flood event", // index 27 |
|
nullptr, // index 28 (reserved) |
|
"FCH and MP1 failed warm reset handshake", // index 29 |
|
"a parity error occurred", // index 30 |
|
"a software sync flood event occurred" // index 31 |
|
}; |
|
|
|
int main() |
|
{ |
|
HRESULT status; |
|
HANDLE handle; |
|
|
|
status = pawnio_open(&handle); |
|
if (status != S_OK) { |
|
if (status == E_ACCESSDENIED) { |
|
fprintf(stderr, "Error Opening PawnIO: Permission Denied (%x)\n", status); |
|
} else { |
|
fprintf(stderr, "Error Opening PawnIO: (%x)\n", status); |
|
} |
|
return status; |
|
} |
|
|
|
if (!std::filesystem::exists(filename)) { |
|
fprintf(stderr, "Error Loading PawnIO Driver: Failed to find %s\n", filename); |
|
return status; |
|
} |
|
|
|
std::ifstream file(filename, std::ios::binary); |
|
if (!file.is_open()) { |
|
fprintf(stderr, "Error Loading PawnIO Driver: Failed to open %s\n", filename); |
|
return ERROR_OPEN_FAILED; |
|
} |
|
|
|
std::vector<char> blob((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); |
|
file.close(); |
|
|
|
status = pawnio_load(handle, reinterpret_cast<const UCHAR*>(blob.data()), blob.size()); |
|
if (status != S_OK) |
|
{ |
|
fprintf(stderr, "Error Loading PawnIO Driver: Failed to load %s (%x)\n", filename, status); |
|
return status; |
|
} |
|
|
|
ULONG64 out; |
|
SIZE_T return_size; |
|
status = pawnio_execute(handle, "ioctl_amd_reset_status", NULL, 0, &out, 1, &return_size); |
|
if (status != S_OK) |
|
{ |
|
fprintf(stderr, "Error Executing PawnIO Driver: (%x)\n", status); |
|
return status; |
|
} |
|
ULONG32 value = (ULONG32)out; |
|
|
|
printf("Previous system reset reason [0x%08lx]\n", value); |
|
for (size_t i = 0; i < 32; i++) { |
|
if (!(value & BIT(i))) |
|
continue; |
|
|
|
if (s5_reset_reason_txt[i]) |
|
printf("%s\n", s5_reset_reason_txt[i]); |
|
} |
|
|
|
status = pawnio_close(handle); |
|
if (status != S_OK) |
|
{ |
|
fprintf(stderr, "Error Closing PawnIO: (%x)\n", status); |
|
return status; |
|
} |
|
} |
Fwiw that driver file in the zip is not allowed to be redistributed independently as per license. Of course you can instead grab the OSS version (which is identical) then build & sign it yourself, but then I'd like to ask that you change the device object path to not clash. If you want to keep this version, I'd recommend instead bunding the installer and using the
/S
switch to make it silent (works for both installer and uninstaller). Additionally you might want to test if it's installed first, and skip the install-uninstall then.This all is mainly because the device object path is static, so you installing it this way will prevent the proper installation from working, and it'll be a mess like the WinRing0 copies. Ofc it's unlikely one would want to install PawnIO during the miliseconds your program runs but it's a bad pattern. There's only meant to be one canonical PawnIO per windows install as it is a global resource, the forcing of the installer usage is to remind you of that. Though if I made PawnIO today I'd probably make it pull the device object path from its assigned registry key...