Skip to content

Instantly share code, notes, and snippets.

@Steve-Tech
Last active May 13, 2025 08:13
Show Gist options
  • Save Steve-Tech/100bf6958156fb7c4c5df122202c2d48 to your computer and use it in GitHub Desktop.
Save Steve-Tech/100bf6958156fb7c4c5df122202c2d48 to your computer and use it in GitHub Desktop.
Gets the reset reason on AMD systems

AMDResetStatus

This is a simple Windows exe to get the reset reason register on AMD systems.

The PawnIO driver is required to be installed, and you will need the AMDReset PawnIO module too.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
// 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;
}
}
@Steve-Tech
Copy link
Author

Oh okay, I mostly intended this to be thrown onto a USB for troubleshooting purposes and probably never touched again.

Fwiw that driver file in the zip is not allowed to be redistributed independently as per license.

I'm so sorry, I've removed everything else from the gist and nuked it from the git history.

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.

Yeah, what I attempted was just a low effort workaround so it didn't screw with an existing installation. In my basic testing, it didn't seem to screw with an already running driver, but maybe it was just luck.


Just curious, the CrOSEC module is included inside the exe of YAFI, is that fine?

@namazso
Copy link

namazso commented May 4, 2025

In my basic testing, it didn't seem to screw with an already running driver, but maybe it was just luck.

Yeah, because then your service will just fail. The problem is the other way around, you having PawnIO loaded will make it fail loading when installing the proper one, so after closing your app it won’t be running anymore until a reboot. It is less of a real problem for instant things like this, but something more persistent like LHM would cause issues.

Just curious, the CrOSEC module is included inside the exe of YAFI, is that fine?

Yeah, the modules are LGPL 2.1 as stated in their header. That lets them link against proprietary things (PawnIO official builds) as well as GPL 2 (PawnIO OSS). LGPL 2.1 grants you the permission to redistribute as long as source is made accessible or provided on request and license stuff is included (read the full license for accurate description)

@namazso
Copy link

namazso commented May 4, 2025

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.

@Steve-Tech
Copy link
Author

I'm not sure if it'd be legal to redistribute the official PawnIO build with it

Yeah that's fine, I have no intention of redistributing PawnIO with it, a download link to pawnio.eu is what I've doing. It was just 'AMDResetStatus.zip' I made without thinking things though.

That is unless 'official PawnIO build' includes the signed modules by themselves.

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

Oh cool, I guess the "System Library" loophole also works, since PawnIO isn't being included.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment