|
// 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; |
|
} |
|
} |
Although looking at the GPL 2 of YAFI, I'm not sure if it'd be legal to redistribute the official PawnIO build with it, you'd probably need to ask a lawyer if you wanted to do that, or just make a license exception. However with all versions of PawnIO being actually the same code, virtually any combination works in practice, that is, you can say you used the LGPL 2.1 converted to GPL 2 for implementing the YAFI-side, but it happens to work with the proprietary one as well. If the end user combined proprietary PawnIO with GPL 2 YAFI on their machine, that's perfectly fine for them, as all these licenses only care about distributing works.
The licensing is complex like this exactly to allow anything from proprietary to GPL to use PawnIO as long as they don't wish to dig themselves into a hole with redistribution concerns. It also retains some leverage to me, as if someone forks PawnIO for free they must follow the GPL and open source every Pawn module, or they can contact me to custom license it if they don't want to support the OSS community.