refactors, goodbye post codes...

This commit is contained in:
rawhide kobayashi 2025-03-19 21:39:57 -05:00
parent 0d35fb76e0
commit 2d8a698e7b
No known key found for this signature in database
GPG Key ID: 7789B80FB28A85D4
21 changed files with 1368 additions and 939 deletions

View File

@ -0,0 +1,264 @@
digraph bios
{
//compound = true
node [shape = "box"]
style = dashed
color = red
//rankdir = "LR"
//VALUES ARE DEFAULT VALUES FROM A FRESHLY CLEARED CMOS
//THIS FILE IS NOT TO BE MODIFIED EXCEPT FOR BREAKING BIOS UPDATES
subgraph cluster_headers
{
"EZ Mode"
"Main"
"Ai Tweaker"
subgraph cluster_ai_tweaker
{
"Ai Overclock Tuner"
"DOCP"
"BCLK Frequency"
"Memory Frequency"
"FCLK Frequency"
"Core tunings Configuration for gaming"
"Core Performance Boost"
"CPU Core Ratio"
"CPU Core Ratio (Per CCX)"
"Turbo Game Mode"
"Gaming Adaptive CCD Parker"
"AI Cache Boost"
"DRAM Timing Control"
// "Precision Boost Overdrive" skip over this, not using it
"DIGI + VRM"
subgraph cluster_vrm
{
"DIGI + VRM (Enter subfolder)"
"VRM Initialization Check"
"Voltage training" [option_type = "list" value = "Auto" options = "Auto,Disabled,Enabled" traversal_key = "ArrowDown"]
"CPU Load-line Calibration" [option_type = "list" value = "Auto" options = "Auto,Level 1,Level 2,Level 3,Level 4,Level 5,Level 6,Level 7,Level 8" traversal_key = "ArrowDown"]
"CPU Current Capability" [option_type = "list" value = "Auto" options = "Auto,100%,110%,120%,130%,140%" traversal_key = "ArrowDown"]
"CPU VRM Switching Frequency"
"Fixed CPU VRM Switching Frequency(KHz)" [option_type = "field" value = "600"]
"CPU Power Duty Control"
"CPU Power Phase Control" [option_type = "list" value = "Auto" options = "Auto,Standard,Optimized,Extreme,Manual" traversal_key = "ArrowDown"]
"VDDSOC Current Capability" [option_type = "list" value = "Auto" options = "Auto,100%,110%,120%,130%,140%" traversal_key = "ArrowDown"]
"VDDSOC Switching Frequency"
"Fixed VDDSOC Switching Frequency(KHz)" [option_type = "field" value = "600"]
"VDDSOC Power Duty Control"
"VDDSOC Power Phase Control" [option_type = "list" value = "Auto" options = "Auto,Standard,Optimized,Extreme,Manual" traversal_key = "ArrowDown"]
}
"Performance Bias"
"Tweaker's Paradise"
"Core Flex"
"AI Features"
"CPU Core Voltage"
"CPU SOC Voltage"
"VDDSOC Voltage Override" [option_type = "field" value = "Auto"]
"CPU VDDIO/MC Voltage"
"Misc Voltage"
"VDDP Voltage"
"High DRAM Voltage Mode"
"DRAM VDD Voltage"
"DRAM VDDQ Voltage"
"VDDG CCD Voltage"
"VDDG IOD Voltage"
"Advanced Memory Voltages"
}
"Advanced"
subgraph cluster_advanced
{
"Trusted Computing"
// unimportant
// "AMD fTPM Configuration"
// "UEFI Variable Protection"
// "CPU Configuration"
// "PCI Subsystem Settings"
// "USB Configuration"
// "Network Stack Configuration"
// "NVMe Configuration"
// "HDD/SSD SMART Information"
// "SATA Configuration"
// "APM Configuration"
"Onboard Devices Configuration"
"NB Configuration"
subgraph cluster_nb_config
{
"NB Configuration (Enter subfolder)"
"Primary Video Device"
"Integrated Graphics" [option_type = "list" value = "Auto" options = "Auto,Force,Disabled" traversal_key = "ArrowUp"]
"UMA Frame Buffer Size"
}
"AMD CBS"
subgraph cluster_amd_cbs
{
// why in the name of all that is unholy is this list in reverse?!
// this is probably the only option that matters
"ACPI SRAT L3 Cache As NUMA Domain" [option_type = "list" value = "Auto" options = "Auto,Enabled,Disabled" traversal_key = "ArrowUp"]
}
"AMD PBS"
"AMD Overclocking"
subgraph cluster_amd_overclocking
{
"AMD Overclocking Subfolder"
"Manual CPU Overclocking"
"DDR and Infinity Fabric Frequency/Timings"
"Precision Boost Overdrive"
subgraph cluster_pbo
{
"Precision Boost Overdrive (Enter subfolder)"
"Precision Boost Overdrive (Setting)"
"PBO Limits" [option_type = "list" value = "Auto" options = "Auto,Disable,Motherboard,Manual" traversal_key = "ArrowDown"]
"Precision Boost Overdrive Scalar Ctrl"
"Precision Boost Overdrive Scalar" [option_type = "list" value = "1X" options = "1X,2X,3X,4X,5X,6X,7X,8X,9X,10X" traversal_key = "ArrowDown"]
"CPU Boost Clock Override"
"Max CPU Boost Clock Override(+)" [option_type = "field" value = "25"]
"Platform Thermal Throttle Ctrl"
"GFX Curve Optimizer"
"Curve Optimizer"
"Curve Shaper"
}
}
}
"Monitor"
"Boot"
"Tool"
subgraph cluster_tool
{
// nothing else here matters
"Download & Install ASUS DriverHub app" [option_type = "list" value = "Enabled" options = "Enabled,Disabled" traversal_key = "ArrowUp"]
}
"Exit"
}
"Monitor"
"Boot"
"Exit"
"Save Changes and Exit"
"EZ Mode" -> "Main" [keypath = "F7"]
"Main" -> "Ai Tweaker" [keypath = "ArrowRight"]
"Ai Tweaker" -> "Advanced" [keypath = "ArrowRight"]
"Advanced" -> "Tool" [keypath = "ArrowRight"]
"Tool" -> "Monitor" [keypath = "ArrowRight"]
"Monitor" -> "Boot" [keypath = "ArrowRight"]
"Boot" -> "Exit" [keypath = "ArrowRight"]
"Exit" -> "Boot" [keypath = "ArrowLeft"]
"Boot" -> "Monitor" [keypath = "ArrowLeft"]
"Monitor" -> "Tool" [keypath = "ArrowLeft"]
"Tool" -> "Advanced" [keypath = "ArrowLeft"]
"Advanced" -> "Ai Tweaker" [keypath = "ArrowLeft"]
"Ai Tweaker" -> "Ai Overclock Tuner" [keypath = "Home" initial_keypath = "Home,Enter,ArrowDown,ArrowDown,ArrowDown,ArrowDown,Enter" visited = "false"]
"Ai Overclock Tuner" -> "DOCP" [keypath = "ArrowDown"]
"DOCP" -> "BCLK Frequency" [keypath = "ArrowDown"]
"BCLK Frequency" -> "Memory Frequency" [keypath = "ArrowDown"]
"Memory Frequency" -> "FCLK Frequency" [keypath = "ArrowDown"]
"FCLK Frequency" -> "Core tunings Configuration for gaming" [keypath = "ArrowDown"]
"Core tunings Configuration for gaming" -> "Core Performance Boost" [keypath = "ArrowDown"]
"Core Performance Boost" -> "CPU Core Ratio" [keypath = "ArrowDown"]
"CPU Core Ratio" -> "CPU Core Ratio (Per CCX)" [keypath = "ArrowDown"]
"CPU Core Ratio (Per CCX)" -> "Turbo Game Mode" [keypath = "ArrowDown"]
"Turbo Game Mode" -> "Gaming Adaptive CCD Parker" [keypath = "ArrowDown"]
"Gaming Adaptive CCD Parker" -> "AI Cache Boost" [keypath = "ArrowDown"]
"AI Cache Boost" -> "DRAM Timing Control" [keypath = "ArrowDown"]
// skip over PBO menu here, it's bad
"DRAM Timing Control" -> "DIGI + VRM" [keypath = "ArrowDown,ArrowDown"]
"DIGI + VRM" -> "DIGI + VRM (Enter subfolder)" [keypath = "Enter,Home"]
"DIGI + VRM (Enter subfolder)" -> "VRM Initialization Check" [keypath = "ArrowDown"]
"VRM Initialization Check" -> "Voltage training" [keypath = "ArrowDown"]
"Voltage training" -> "CPU Load-line Calibration" [keypath = "ArrowDown"]
"CPU Load-line Calibration" -> "CPU Current Capability" [keypath = "ArrowDown"]
"CPU Current Capability" -> "CPU VRM Switching Frequency" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"CPU VRM Switching Frequency" -> "Fixed CPU VRM Switching Frequency(KHz)" [keypath = "ArrowDown"]
"Fixed CPU VRM Switching Frequency(KHz)" -> "CPU Power Duty Control" [keypath = "ArrowDown"]
"CPU Power Duty Control" -> "CPU Power Phase Control" [keypath = "ArrowDown"]
"CPU Power Phase Control" -> "VDDSOC Current Capability" [keypath = "ArrowDown"]
"VDDSOC Current Capability" -> "VDDSOC Switching Frequency" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"VDDSOC Switching Frequency" -> "Fixed VDDSOC Switching Frequency(KHz)" [keypath = "ArrowDown"]
"Fixed VDDSOC Switching Frequency(KHz)" -> "VDDSOC Power Duty Control" [keypath = "ArrowDown"]
"VDDSOC Power Duty Control" -> "VDDSOC Power Phase Control" [keypath = "ArrowDown"]
"DIGI + VRM (Enter subfolder)", "VRM Initialization Check", "Voltage training", "CPU Load-line Calibration", "CPU Current Capability", "CPU VRM Switching Frequency", "CPU Power Duty Control", "CPU Power Phase Control", "VDDSOC Current Capability", "VDDSOC Switching Frequency", "VDDSOC Power Duty Control", "VDDSOC Power Phase Control" -> "DIGI + VRM" [keypath = "Escape"]
"DIGI + VRM" -> "Performance Bias" [keypath = "ArrowDown"]
"Performance Bias" -> "Tweaker's Paradise" [keypath = "ArrowDown"]
"Tweaker's Paradise" -> "Core Flex" [keypath = "ArrowDown"]
"Core Flex" -> "AI Features" [keypath = "ArrowDown"]
"AI Features" -> "CPU Core Voltage" [keypath = "ArrowDown"]
"CPU Core Voltage" -> "CPU SOC Voltage" [keypath = "ArrowDown", initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"CPU SOC Voltage" -> "VDDSOC Voltage Override" [keypath = "ArrowDown"]
"VDDSOC Voltage Override" -> "CPU VDDIO/MC Voltage" [keypath = "ArrowDown"]
"CPU VDDIO/MC Voltage" -> "Misc Voltage" [keypath = "ArrowDown"]
"Misc Voltage" -> "VDDP Voltage" [keypath = "ArrowDown"]
"VDDP Voltage" -> "High DRAM Voltage Mode" [keypath = "ArrowDown"]
"High DRAM Voltage Mode" -> "DRAM VDD Voltage" [keypath = "ArrowDown"]
"DRAM VDD Voltage" -> "DRAM VDDQ Voltage" [keypath = "ArrowDown"]
"DRAM VDDQ Voltage" -> "VDDG CCD Voltage" [keypath = "ArrowDown"]
"VDDG CCD Voltage" -> "VDDG IOD Voltage" [keypath = "ArrowDown"]
"VDDG IOD Voltage" -> "Advanced Memory Voltages" [keypath = "ArrowDown"]
"Ai Overclock Tuner", "DOCP", "BCLK Frequency", "Memory Frequency", "FCLK Frequency", "Core tunings Configuration for gaming", "Core Performance Boost", "CPU Core Ratio", "CPU Core Ratio (Per CCX)", "Turbo Game Mode", "Gaming Adaptive CCD Parker", "AI Cache Boost", "DRAM Timing Control", "DIGI + VRM", "Performance Bias", "Tweaker's Paradise", "Core Flex", "AI Features", "CPU Core Voltage", "CPU SOC Voltage", "CPU VDDIO/MC Voltage", "Misc Voltage", "VDDP Voltage", "High DRAM Voltage Mode", "DRAM VDD Voltage", "DRAM VDDQ Voltage", "VDDG CCD Voltage", "VDDG IOD Voltage", "Advanced Memory Voltages" -> "Ai Tweaker" [keypath = "Home"]
"Advanced" -> "Trusted Computing" [keypath = "Home"]
"Trusted Computing" -> "Onboard Devices Configuration" [keypath = "ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown"]
"Onboard Devices Configuration" -> "NB Configuration" [keypath = "ArrowDown"]
"NB Configuration" -> "NB Configuration (Enter subfolder)" [keypath = "Enter,Home"]
"NB Configuration (Enter subfolder)" -> "Primary Video Device" [keypath = "ArrowDown"]
"Primary Video Device" -> "Integrated Graphics" [keypath = "ArrowDown"]
"Integrated Graphics" -> "UMA Frame Buffer Size" [keypath = "ArrowDown"]
"NB Configuration (Enter subfolder)", "Primary Video Device", "Integrated Graphics", "UMA Frame Buffer Size" -> "NB Configuration" [keypath = "Escape"]
"NB Configuration" -> "AMD CBS" [keypath = "ArrowDown"]
"AMD CBS" -> "AMD PBS" [keypath = "ArrowDown"]
"AMD PBS" -> "AMD Overclocking" [keypath = "ArrowDown"]
"Onboard Devices Configuration", "NB Configuration", "AMD CBS", "AMD PBS", "Trusted Computing" -> "Advanced" [keypath = "Home"]
"AMD CBS" -> "ACPI SRAT L3 Cache As NUMA Domain" [keypath = "Enter,Home,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,Enter,Home,ArrowDown,ArrowDown,Enter,Home,ArrowDown"]
"ACPI SRAT L3 Cache As NUMA Domain" -> "AMD CBS" [keypath = "Escape,Escape,Escape"]
"AMD Overclocking" -> "AMD Overclocking Subfolder" [keypath = "Enter,Home,ArrowDown,Enter,Home"]
"AMD Overclocking Subfolder" -> "Manual CPU Overclocking" [keypath = "ArrowDown"]
"Manual CPU Overclocking" -> "DDR and Infinity Fabric Frequency/Timings" [keypath = "ArrowDown"]
"DDR and Infinity Fabric Frequency/Timings" -> "Precision Boost Overdrive" [keypath = "ArrowDown"]
"AMD Overclocking Subfolder", "Manual CPU Overclocking", "DDR and Infinity Fabric Frequency/Timings", "Precision Boost Overdrive" -> "AMD PBS" [keypath = "Escape,Escape"]
"Precision Boost Overdrive" -> "Precision Boost Overdrive (Enter subfolder)" [keypath = "Enter"]
"Precision Boost Overdrive (Enter subfolder)" -> "Precision Boost Overdrive (Setting)" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,ArrowDown,ArrowDown,Enter" visited = "false"]
"Precision Boost Overdrive (Setting)" -> "PBO Limits" [keypath = "ArrowDown"]
"PBO Limits" -> "Precision Boost Overdrive Scalar Ctrl" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"Precision Boost Overdrive Scalar Ctrl" -> "Precision Boost Overdrive Scalar" [keypath = "ArrowDown"]
"Precision Boost Overdrive Scalar" -> "CPU Boost Clock Override" [keypath = "ArrowDown" initial_keypath = "ArrowDown,Enter,ArrowDown,Enter" visited = "false"]
"CPU Boost Clock Override" -> "Max CPU Boost Clock Override(+)" [keypath = "ArrowDown"]
"Max CPU Boost Clock Override(+)" -> "Platform Thermal Throttle Ctrl" [keypath = "ArrowDown"]
"Platform Thermal Throttle Ctrl" -> "GFX Curve Optimizer" [keypath = "ArrowDown"]
"GFX Curve Optimizer" -> "Curve Optimizer" [keypath = "ArrowDown"]
"Curve Optimizer" -> "Curve Shaper" [keypath = "ArrowDown"]
"Precision Boost Overdrive", "PBO Limits", "Precision Boost Overdrive Scalar Ctrl", "CPU Boost Clock Override", "Platform Thermal Throttle Ctrl" -> "Precision Boost Overdrive (Enter subfolder)" [keypath = "Escape"]
"Precision Boost Overdrive (Enter subfolder)" -> "AMD Overclocking" [keypath = "Escape,Escape"]
"Tool" -> "Download & Install ASUS DriverHub app" [keypath = "Home,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,ArrowDown,Enter,Home,ArrowDown"]
"Download & Install ASUS DriverHub app" -> "Tool" [keypath = "Escape"]
"Exit" -> "Save Changes and Exit" [keypath = "Enter,Enter"]
}

View File

@ -9,37 +9,40 @@ void loop() {}
#include <Arduino.h>
#include <ArduinoJson.h>
#include <USB.h>
#include <USBHID.h>
#include <USBHIDMouse.h>
#include <USBHIDKeyboard.h>
#include <USBHIDSystemControl.h>
USBHID HID;
USBHIDAbsoluteMouse Mouse;
USBHIDKeyboard Keyboard;
HardwareSerial &host_serial = Serial;
HardwareSerial &mobo_serial = Serial1;
// HardwareSerial &mobo_serial = Serial1;
JsonDocument mkb_input;
JsonDocument post_codes;
// JsonDocument post_codes;
JsonDocument power_status;
// put function declarations here:
int myFunction(int, int);
const int8_t pwr_button = 3;
const int8_t cmos_button = 46;
const int8_t pwr_detect = 8;
const int8_t pwr_button = 46;
const int8_t cmos_button = 3;
// const int8_t pwr_detect = 8;
void setup()
{
host_serial.begin(115200);
mobo_serial.begin(115200, SERIAL_8N1, 18);
// mobo_serial.begin(115200, SERIAL_8N1, 18);
HID.begin();
Mouse.begin();
Keyboard.begin();
USB.begin();
pinMode(pwr_button, OUTPUT);
pinMode(cmos_button, OUTPUT);
pinMode(pwr_detect, INPUT);
// pinMode(pwr_detect, INPUT);
}
void loop()
@ -51,7 +54,7 @@ void loop()
if (cur_loop_timestamp - check_power_status_timestamp >= 100000)
{
if (analogRead(pwr_detect) > 1000)
/* if (analogRead(pwr_detect) > 1000)
{
power_status["pwr"] = true;
}
@ -59,6 +62,16 @@ void loop()
else
{
power_status["pwr"] = false;
} */
if (HID.ready())
{
power_status["usb"] = true;
}
else
{
power_status["usb"] = false;
}
serializeJson(power_status, host_serial);
@ -66,12 +79,12 @@ void loop()
check_power_status_timestamp = esp_timer_get_time();
}
while (mobo_serial.available())
/* while (mobo_serial.available())
{
post_codes["post_code"] = mobo_serial.read();
serializeJson(post_codes, host_serial);
host_serial.write('\n');
}
} */
if (host_serial.available())
{

View File

@ -1,254 +1,268 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 12.1.2 (0)
<!-- Generated by graphviz version 12.2.1 (0)
-->
<!-- Pages: 1 -->
<svg width="1856pt" height="543pt"
viewBox="0.00 0.00 1856.00 543.32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 539.32)">
<polygon fill="white" stroke="none" points="-4,4 -4,-539.32 1852,-539.32 1852,4 -4,4"/>
<text text-anchor="middle" x="924" y="-4.95" font-family="Times,serif" font-size="14.00">State Machine</text>
<svg width="1745pt" height="637pt"
viewBox="0.00 0.00 1744.50 636.50" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 632.5)">
<polygon fill="white" stroke="none" points="-4,4 -4,-632.5 1740.5,-632.5 1740.5,4 -4,4"/>
<text text-anchor="middle" x="868.25" y="-4.95" font-family="Times,serif" font-size="14.00">State Machine</text>
<!-- PoweredOff -->
<g id="node1" class="node">
<title>PoweredOff</title>
<path fill="white" stroke="black" d="M422.38,-349.07C422.38,-349.07 365.12,-349.07 365.12,-349.07 359.12,-349.07 353.12,-343.07 353.12,-337.07 353.12,-337.07 353.12,-325.07 353.12,-325.07 353.12,-319.07 359.12,-313.07 365.12,-313.07 365.12,-313.07 422.38,-313.07 422.38,-313.07 428.38,-313.07 434.38,-319.07 434.38,-325.07 434.38,-325.07 434.38,-337.07 434.38,-337.07 434.38,-343.07 428.38,-349.07 422.38,-349.07"/>
<text text-anchor="start" x="361.12" y="-324.89" font-family="Times,serif" font-size="14.00">PoweredOff</text>
<path fill="white" stroke="black" d="M69.25,-258.25C69.25,-258.25 12,-258.25 12,-258.25 6,-258.25 0,-252.25 0,-246.25 0,-246.25 0,-234.25 0,-234.25 0,-228.25 6,-222.25 12,-222.25 12,-222.25 69.25,-222.25 69.25,-222.25 75.25,-222.25 81.25,-228.25 81.25,-234.25 81.25,-234.25 81.25,-246.25 81.25,-246.25 81.25,-252.25 75.25,-258.25 69.25,-258.25"/>
<text text-anchor="start" x="8" y="-234.07" font-family="Times,serif" font-size="14.00">PoweredOff</text>
</g>
<!-- POST -->
<g id="node2" class="node">
<title>POST</title>
<path fill="white" stroke="black" d="M676.88,-296.07C676.88,-296.07 646.88,-296.07 646.88,-296.07 640.88,-296.07 634.88,-290.07 634.88,-284.07 634.88,-284.07 634.88,-272.07 634.88,-272.07 634.88,-266.07 640.88,-260.07 646.88,-260.07 646.88,-260.07 676.88,-260.07 676.88,-260.07 682.88,-260.07 688.88,-266.07 688.88,-272.07 688.88,-272.07 688.88,-284.07 688.88,-284.07 688.88,-290.07 682.88,-296.07 676.88,-296.07"/>
<text text-anchor="start" x="642.88" y="-271.89" font-family="Times,serif" font-size="14.00">POST</text>
<path fill="white" stroke="black" d="M268,-295.25C268,-295.25 238,-295.25 238,-295.25 232,-295.25 226,-289.25 226,-283.25 226,-283.25 226,-271.25 226,-271.25 226,-265.25 232,-259.25 238,-259.25 238,-259.25 268,-259.25 268,-259.25 274,-259.25 280,-265.25 280,-271.25 280,-271.25 280,-283.25 280,-283.25 280,-289.25 274,-295.25 268,-295.25"/>
<text text-anchor="start" x="234" y="-271.07" font-family="Times,serif" font-size="14.00">POST</text>
</g>
<!-- PoweredOff&#45;&gt;POST -->
<g id="edge1" class="edge">
<title>PoweredOff&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M422.41,-312.63C433.95,-305.86 447.77,-298.86 461.25,-294.82 515.83,-278.45 582.3,-276.17 623.1,-276.65"/>
<polygon fill="black" stroke="black" points="622.82,-280.15 632.88,-276.84 622.95,-273.15 622.82,-280.15"/>
<text text-anchor="middle" x="502.88" y="-295.77" font-family="Times,serif" font-size="14.00">power_on</text>
<path fill="none" stroke="black" d="M81.48,-251.24C87.41,-252.7 93.47,-254.09 99.25,-255.25 138.26,-263.11 183.42,-269.26 214.46,-273.03"/>
<polygon fill="black" stroke="black" points="213.78,-276.47 224.13,-274.18 214.61,-269.52 213.78,-276.47"/>
<text text-anchor="middle" x="140.88" y="-269.8" font-family="Times,serif" font-size="14.00">power_on</text>
</g>
<!-- POST&#45;&gt;PoweredOff -->
<g id="edge14" class="edge">
<g id="edge15" class="edge">
<title>POST&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M634.73,-285.95C611.28,-292.8 575.83,-302.62 544.5,-309.07 511.9,-315.78 474.89,-321.24 445.82,-325.04"/>
<polygon fill="black" stroke="black" points="445.67,-321.53 436.2,-326.27 446.56,-328.47 445.67,-321.53"/>
<text text-anchor="middle" x="502.88" y="-323.63" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
<path fill="none" stroke="black" d="M227.68,-258.92C214.94,-250.46 198.66,-241.34 182.5,-237 153.45,-229.2 119.82,-229.64 92.7,-232.2"/>
<polygon fill="black" stroke="black" points="92.58,-228.7 83.01,-233.25 93.33,-235.66 92.58,-228.7"/>
<text text-anchor="middle" x="140.88" y="-237.95" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- EnterBIOS -->
<g id="node3" class="node">
<title>EnterBIOS</title>
<path fill="white" stroke="black" d="M975.12,-325.07C975.12,-325.07 923.12,-325.07 923.12,-325.07 917.12,-325.07 911.12,-319.07 911.12,-313.07 911.12,-313.07 911.12,-301.07 911.12,-301.07 911.12,-295.07 917.12,-289.07 923.12,-289.07 923.12,-289.07 975.12,-289.07 975.12,-289.07 981.12,-289.07 987.12,-295.07 987.12,-301.07 987.12,-301.07 987.12,-313.07 987.12,-313.07 987.12,-319.07 981.12,-325.07 975.12,-325.07"/>
<text text-anchor="start" x="919.12" y="-300.89" font-family="Times,serif" font-size="14.00">EnterBIOS</text>
<path fill="white" stroke="black" d="M594.38,-408.25C594.38,-408.25 542.38,-408.25 542.38,-408.25 536.38,-408.25 530.38,-402.25 530.38,-396.25 530.38,-396.25 530.38,-384.25 530.38,-384.25 530.38,-378.25 536.38,-372.25 542.38,-372.25 542.38,-372.25 594.38,-372.25 594.38,-372.25 600.38,-372.25 606.38,-378.25 606.38,-384.25 606.38,-384.25 606.38,-396.25 606.38,-396.25 606.38,-402.25 600.38,-408.25 594.38,-408.25"/>
<text text-anchor="start" x="538.38" y="-384.07" font-family="Times,serif" font-size="14.00">EnterBIOS</text>
</g>
<!-- POST&#45;&gt;EnterBIOS -->
<g id="edge15" class="edge">
<g id="edge16" class="edge">
<title>POST&#45;&gt;EnterBIOS</title>
<path fill="none" stroke="black" d="M689.2,-280.75C737.01,-285.61 838.78,-295.95 899.52,-302.13"/>
<polygon fill="black" stroke="black" points="898.92,-305.58 909.22,-303.11 899.62,-298.62 898.92,-305.58"/>
<text text-anchor="middle" x="828.38" y="-300.24" font-family="Times,serif" font-size="14.00">enter_bios</text>
<path fill="none" stroke="black" d="M264.12,-295.51C275.77,-314.61 296.77,-343.79 323.5,-358.25 384.82,-391.44 467.13,-395.31 518.71,-393.76"/>
<polygon fill="black" stroke="black" points="518.81,-397.26 528.66,-393.37 518.53,-390.26 518.81,-397.26"/>
<text text-anchor="middle" x="410.12" y="-394.95" font-family="Times,serif" font-size="14.00">enter_bios</text>
</g>
<!-- IdleWaitingForInput -->
<g id="node5" class="node">
<title>IdleWaitingForInput</title>
<path fill="darksalmon" stroke="red" d="M865.5,-304.25C865.5,-304.25 762.5,-304.25 762.5,-304.25 756.5,-304.25 750.5,-298.25 750.5,-292.25 750.5,-292.25 750.5,-280.25 750.5,-280.25 750.5,-274.25 756.5,-268.25 762.5,-268.25 762.5,-268.25 865.5,-268.25 865.5,-268.25 871.5,-268.25 877.5,-274.25 877.5,-280.25 877.5,-280.25 877.5,-292.25 877.5,-292.25 877.5,-298.25 871.5,-304.25 865.5,-304.25"/>
<path fill="none" stroke="red" d="M869.5,-308.25C869.5,-308.25 758.5,-308.25 758.5,-308.25 752.5,-308.25 746.5,-302.25 746.5,-296.25 746.5,-296.25 746.5,-276.25 746.5,-276.25 746.5,-270.25 752.5,-264.25 758.5,-264.25 758.5,-264.25 869.5,-264.25 869.5,-264.25 875.5,-264.25 881.5,-270.25 881.5,-276.25 881.5,-276.25 881.5,-296.25 881.5,-296.25 881.5,-302.25 875.5,-308.25 869.5,-308.25"/>
<text text-anchor="start" x="758.5" y="-280.07" font-family="Times,serif" font-size="14.00">IdleWaitingForInput</text>
</g>
<!-- POST&#45;&gt;IdleWaitingForInput -->
<g id="edge19" class="edge">
<title>POST&#45;&gt;IdleWaitingForInput</title>
<path fill="none" stroke="black" d="M280.21,-277.67C360.88,-278.97 607.65,-282.94 735.06,-285"/>
<polygon fill="black" stroke="black" points="734.69,-288.49 744.75,-285.15 734.8,-281.49 734.69,-288.49"/>
<text text-anchor="middle" x="568.38" y="-284.03" font-family="Times,serif" font-size="14.00">go_idle</text>
</g>
<!-- WaitingForOS -->
<g id="node5" class="node">
<g id="node6" class="node">
<title>WaitingForOS</title>
<path fill="white" stroke="black" d="M984.5,-144.07C984.5,-144.07 913.75,-144.07 913.75,-144.07 907.75,-144.07 901.75,-138.07 901.75,-132.07 901.75,-132.07 901.75,-120.07 901.75,-120.07 901.75,-114.07 907.75,-108.07 913.75,-108.07 913.75,-108.07 984.5,-108.07 984.5,-108.07 990.5,-108.07 996.5,-114.07 996.5,-120.07 996.5,-120.07 996.5,-132.07 996.5,-132.07 996.5,-138.07 990.5,-144.07 984.5,-144.07"/>
<text text-anchor="start" x="909.75" y="-119.89" font-family="Times,serif" font-size="14.00">WaitingForOS</text>
<path fill="white" stroke="black" d="M603.75,-124.25C603.75,-124.25 533,-124.25 533,-124.25 527,-124.25 521,-118.25 521,-112.25 521,-112.25 521,-100.25 521,-100.25 521,-94.25 527,-88.25 533,-88.25 533,-88.25 603.75,-88.25 603.75,-88.25 609.75,-88.25 615.75,-94.25 615.75,-100.25 615.75,-100.25 615.75,-112.25 615.75,-112.25 615.75,-118.25 609.75,-124.25 603.75,-124.25"/>
<text text-anchor="start" x="529" y="-100.08" font-family="Times,serif" font-size="14.00">WaitingForOS</text>
</g>
<!-- POST&#45;&gt;WaitingForOS -->
<g id="edge16" class="edge">
<g id="edge17" class="edge">
<title>POST&#45;&gt;WaitingForOS</title>
<path fill="none" stroke="black" d="M675.07,-259.57C693.94,-232.54 732.95,-182.74 779.25,-157.82 789.09,-152.52 845.24,-142.55 890.13,-135.19"/>
<polygon fill="black" stroke="black" points="890.47,-138.69 899.78,-133.63 889.34,-131.78 890.47,-138.69"/>
<text text-anchor="middle" x="828.38" y="-158.77" font-family="Times,serif" font-size="14.00">enter_os</text>
<path fill="none" stroke="black" d="M263.64,-258.89C280.46,-227.13 314.28,-164.67 323.5,-158 352.68,-136.9 446.96,-121.37 509.38,-113.08"/>
<polygon fill="black" stroke="black" points="509.68,-116.57 519.14,-111.81 508.77,-109.63 509.68,-116.57"/>
<text text-anchor="middle" x="410.12" y="-158.95" font-family="Times,serif" font-size="14.00">wait_os</text>
</g>
<!-- BootLoop -->
<g id="node11" class="node">
<g id="node12" class="node">
<title>BootLoop</title>
<path fill="white" stroke="black" d="M972.88,-417.07C972.88,-417.07 925.38,-417.07 925.38,-417.07 919.38,-417.07 913.38,-411.07 913.38,-405.07 913.38,-405.07 913.38,-393.07 913.38,-393.07 913.38,-387.07 919.38,-381.07 925.38,-381.07 925.38,-381.07 972.88,-381.07 972.88,-381.07 978.88,-381.07 984.88,-387.07 984.88,-393.07 984.88,-393.07 984.88,-405.07 984.88,-405.07 984.88,-411.07 978.88,-417.07 972.88,-417.07"/>
<text text-anchor="start" x="921.38" y="-392.89" font-family="Times,serif" font-size="14.00">BootLoop</text>
<path fill="white" stroke="black" d="M592.12,-178.25C592.12,-178.25 544.62,-178.25 544.62,-178.25 538.62,-178.25 532.62,-172.25 532.62,-166.25 532.62,-166.25 532.62,-154.25 532.62,-154.25 532.62,-148.25 538.62,-142.25 544.62,-142.25 544.62,-142.25 592.12,-142.25 592.12,-142.25 598.12,-142.25 604.12,-148.25 604.12,-154.25 604.12,-154.25 604.12,-166.25 604.12,-166.25 604.12,-172.25 598.12,-178.25 592.12,-178.25"/>
<text text-anchor="start" x="540.62" y="-154.07" font-family="Times,serif" font-size="14.00">BootLoop</text>
</g>
<!-- POST&#45;&gt;BootLoop -->
<g id="edge17" class="edge">
<g id="edge18" class="edge">
<title>POST&#45;&gt;BootLoop</title>
<path fill="none" stroke="black" d="M686.03,-296.45C708.6,-313.5 744.49,-338.37 779.25,-353.07 820.53,-370.52 834.34,-363.74 877.5,-375.82 885.53,-378.07 894.01,-380.66 902.2,-383.28"/>
<polygon fill="black" stroke="black" points="901.08,-386.6 911.67,-386.38 903.25,-379.95 901.08,-386.6"/>
<text text-anchor="middle" x="828.38" y="-376.77" font-family="Times,serif" font-size="14.00">unsuccessful_post</text>
<path fill="none" stroke="black" d="M264.71,-258.92C276.57,-240.46 297.49,-212.79 323.5,-199 392.11,-162.62 420.3,-189.9 496.75,-176.25 504.66,-174.84 513.02,-173.13 521.11,-171.37"/>
<polygon fill="black" stroke="black" points="521.83,-174.8 530.82,-169.2 520.3,-167.97 521.83,-174.8"/>
<text text-anchor="middle" x="410.12" y="-199.95" font-family="Times,serif" font-size="14.00">unsuccessful_post</text>
</g>
<!-- BIOSSetup -->
<g id="node4" class="node">
<title>BIOSSetup</title>
<path fill="white" stroke="black" d="M1215.62,-325.07C1215.62,-325.07 1162.12,-325.07 1162.12,-325.07 1156.12,-325.07 1150.12,-319.07 1150.12,-313.07 1150.12,-313.07 1150.12,-301.07 1150.12,-301.07 1150.12,-295.07 1156.12,-289.07 1162.12,-289.07 1162.12,-289.07 1215.62,-289.07 1215.62,-289.07 1221.62,-289.07 1227.62,-295.07 1227.62,-301.07 1227.62,-301.07 1227.62,-313.07 1227.62,-313.07 1227.62,-319.07 1221.62,-325.07 1215.62,-325.07"/>
<text text-anchor="start" x="1158.12" y="-300.89" font-family="Times,serif" font-size="14.00">BIOSSetup</text>
<path fill="white" stroke="black" d="M840.75,-462.25C840.75,-462.25 787.25,-462.25 787.25,-462.25 781.25,-462.25 775.25,-456.25 775.25,-450.25 775.25,-450.25 775.25,-438.25 775.25,-438.25 775.25,-432.25 781.25,-426.25 787.25,-426.25 787.25,-426.25 840.75,-426.25 840.75,-426.25 846.75,-426.25 852.75,-432.25 852.75,-438.25 852.75,-438.25 852.75,-450.25 852.75,-450.25 852.75,-456.25 846.75,-462.25 840.75,-462.25"/>
<text text-anchor="start" x="783.25" y="-438.07" font-family="Times,serif" font-size="14.00">BIOSSetup</text>
</g>
<!-- EnterBIOS&#45;&gt;BIOSSetup -->
<g id="edge2" class="edge">
<title>EnterBIOS&#45;&gt;BIOSSetup</title>
<path fill="none" stroke="black" d="M987.53,-307.07C1028.32,-307.07 1093.74,-307.07 1138.66,-307.07"/>
<polygon fill="black" stroke="black" points="1138.38,-310.57 1148.38,-307.07 1138.38,-303.57 1138.38,-310.57"/>
<text text-anchor="middle" x="1065" y="-308.02" font-family="Times,serif" font-size="14.00">start_bios_setup</text>
<path fill="none" stroke="black" d="M606.69,-394.55C639.16,-398.7 687.33,-405.86 728.5,-416 740.22,-418.89 752.65,-422.64 764.27,-426.46"/>
<polygon fill="black" stroke="black" points="763.08,-429.76 773.67,-429.64 765.32,-423.12 763.08,-429.76"/>
<text text-anchor="middle" x="684.25" y="-416.95" font-family="Times,serif" font-size="14.00">start_bios_setup</text>
</g>
<!-- EnterBIOS&#45;&gt;IdleWaitingForInput -->
<g id="edge3" class="edge">
<title>EnterBIOS&#45;&gt;IdleWaitingForInput</title>
<path fill="none" stroke="black" d="M606.64,-374.34C644.73,-358.08 704.58,-332.53 750.03,-313.13"/>
<polygon fill="black" stroke="black" points="751.16,-316.45 758.99,-309.31 748.42,-310.01 751.16,-316.45"/>
<text text-anchor="middle" x="684.25" y="-360.47" font-family="Times,serif" font-size="14.00">go_idle</text>
</g>
<!-- BIOSSetup&#45;&gt;PoweredOff -->
<g id="edge3" class="edge">
<g id="edge4" class="edge">
<title>BIOSSetup&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1167.93,-325.54C1135.97,-353.74 1070.02,-406.31 1002.75,-426.07 897.77,-456.9 571.58,-377.59 445.35,-344.64"/>
<polygon fill="black" stroke="black" points="446.51,-341.32 435.94,-342.17 444.73,-348.1 446.51,-341.32"/>
<text text-anchor="middle" x="828.38" y="-430.51" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
<path fill="none" stroke="black" d="M774.97,-454.2C760.51,-457.61 743.84,-461.11 728.5,-463.25 550.01,-488.17 491.43,-508.67 323.5,-443.25 217.43,-401.93 114.54,-311.19 67.8,-266.36"/>
<polygon fill="black" stroke="black" points="70.44,-264.05 60.83,-259.6 65.57,-269.07 70.44,-264.05"/>
<text text-anchor="middle" x="410.12" y="-487.27" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- BIOSSetup&#45;&gt;POST -->
<g id="edge4" class="edge">
<title>BIOSSetup&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1149.64,-295.97C1112.49,-285.8 1054.3,-271.49 1002.75,-265.82 893.3,-253.77 762.96,-265.78 700.24,-273.19"/>
<polygon fill="black" stroke="black" points="699.99,-269.69 690.48,-274.37 700.83,-276.64 699.99,-269.69"/>
<text text-anchor="middle" x="949.12" y="-266.77" font-family="Times,serif" font-size="14.00">finished_bios_setup</text>
</g>
<!-- WaitingForOS&#45;&gt;PoweredOff -->
<g id="edge5" class="edge">
<title>WaitingForOS&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M901.6,-125.18C867.31,-125.53 819.79,-128.14 779.25,-138.07 629.6,-174.72 592.58,-195.51 461.25,-276.07 457.16,-278.58 440.47,-292.38 424.84,-305.53"/>
<polygon fill="black" stroke="black" points="422.9,-302.59 417.51,-311.71 427.41,-307.94 422.9,-302.59"/>
<text text-anchor="middle" x="661.88" y="-216.91" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- WaitingForHWInfo -->
<g id="node6" class="node">
<title>WaitingForHWInfo</title>
<path fill="white" stroke="black" d="M1238.5,-137.07C1238.5,-137.07 1139.25,-137.07 1139.25,-137.07 1133.25,-137.07 1127.25,-131.07 1127.25,-125.07 1127.25,-125.07 1127.25,-113.07 1127.25,-113.07 1127.25,-107.07 1133.25,-101.07 1139.25,-101.07 1139.25,-101.07 1238.5,-101.07 1238.5,-101.07 1244.5,-101.07 1250.5,-107.07 1250.5,-113.07 1250.5,-113.07 1250.5,-125.07 1250.5,-125.07 1250.5,-131.07 1244.5,-137.07 1238.5,-137.07"/>
<text text-anchor="start" x="1135.25" y="-112.89" font-family="Times,serif" font-size="14.00">WaitingForHWInfo</text>
</g>
<!-- WaitingForOS&#45;&gt;WaitingForHWInfo -->
<g id="edge6" class="edge">
<title>WaitingForOS&#45;&gt;WaitingForHWInfo</title>
<path fill="none" stroke="black" d="M996.81,-124.7C1030.66,-123.7 1077.07,-122.33 1115.68,-121.2"/>
<polygon fill="black" stroke="black" points="1115.46,-124.7 1125.35,-120.91 1115.25,-117.71 1115.46,-124.7"/>
<text text-anchor="middle" x="1065" y="-124.76" font-family="Times,serif" font-size="14.00">os_booted</text>
</g>
<!-- OCTypeDecision -->
<g id="node7" class="node">
<title>OCTypeDecision</title>
<path fill="white" stroke="black" d="M1478.75,-226.07C1478.75,-226.07 1392.25,-226.07 1392.25,-226.07 1386.25,-226.07 1380.25,-220.07 1380.25,-214.07 1380.25,-214.07 1380.25,-202.07 1380.25,-202.07 1380.25,-196.07 1386.25,-190.07 1392.25,-190.07 1392.25,-190.07 1478.75,-190.07 1478.75,-190.07 1484.75,-190.07 1490.75,-196.07 1490.75,-202.07 1490.75,-202.07 1490.75,-214.07 1490.75,-214.07 1490.75,-220.07 1484.75,-226.07 1478.75,-226.07"/>
<text text-anchor="start" x="1388.25" y="-201.89" font-family="Times,serif" font-size="14.00">OCTypeDecision</text>
</g>
<!-- WaitingForHWInfo&#45;&gt;OCTypeDecision -->
<g id="edge18" class="edge">
<title>WaitingForHWInfo&#45;&gt;OCTypeDecision</title>
<path fill="none" stroke="black" d="M1240.56,-137.51C1279.1,-151.53 1332.29,-170.88 1373.22,-185.77"/>
<polygon fill="black" stroke="black" points="1371.86,-189.01 1382.46,-189.14 1374.26,-182.43 1371.86,-189.01"/>
<text text-anchor="middle" x="1315.38" y="-182.72" font-family="Times,serif" font-size="14.00">hwinfo_available</text>
</g>
<!-- RoughMulticoreUndervolt -->
<g id="node8" class="node">
<title>RoughMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1834.5,-277.07C1834.5,-277.07 1697,-277.07 1697,-277.07 1691,-277.07 1685,-271.07 1685,-265.07 1685,-265.07 1685,-253.07 1685,-253.07 1685,-247.07 1691,-241.07 1697,-241.07 1697,-241.07 1834.5,-241.07 1834.5,-241.07 1840.5,-241.07 1846.5,-247.07 1846.5,-253.07 1846.5,-253.07 1846.5,-265.07 1846.5,-265.07 1846.5,-271.07 1840.5,-277.07 1834.5,-277.07"/>
<text text-anchor="start" x="1693" y="-252.89" font-family="Times,serif" font-size="14.00">RoughMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;RoughMulticoreUndervolt -->
<g id="edge7" class="edge">
<title>OCTypeDecision&#45;&gt;RoughMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1491.03,-210.75C1537.67,-213.69 1606.43,-219.57 1665.5,-230.82 1675.22,-232.67 1685.36,-235.04 1695.29,-237.61"/>
<polygon fill="black" stroke="black" points="1694.36,-240.98 1704.92,-240.2 1696.17,-234.22 1694.36,-240.98"/>
<text text-anchor="middle" x="1587.12" y="-231.77" font-family="Times,serif" font-size="14.00">rough_multicore_undervolt</text>
</g>
<!-- PreciseMulticoreUndervolt -->
<g id="node9" class="node">
<title>PreciseMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1836,-178.07C1836,-178.07 1695.5,-178.07 1695.5,-178.07 1689.5,-178.07 1683.5,-172.07 1683.5,-166.07 1683.5,-166.07 1683.5,-154.07 1683.5,-154.07 1683.5,-148.07 1689.5,-142.07 1695.5,-142.07 1695.5,-142.07 1836,-142.07 1836,-142.07 1842,-142.07 1848,-148.07 1848,-154.07 1848,-154.07 1848,-166.07 1848,-166.07 1848,-172.07 1842,-178.07 1836,-178.07"/>
<text text-anchor="start" x="1691.5" y="-153.89" font-family="Times,serif" font-size="14.00">PreciseMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt -->
<g id="edge8" class="edge">
<title>OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1490.87,-196.96C1496.9,-195.84 1502.95,-194.77 1508.75,-193.82 1562.72,-184.95 1623.38,-176.87 1672.11,-170.84"/>
<polygon fill="black" stroke="black" points="1672.27,-174.35 1681.77,-169.65 1671.42,-167.4 1672.27,-174.35"/>
<text text-anchor="middle" x="1587.12" y="-194.77" font-family="Times,serif" font-size="14.00">precise_multicore_undervolt</text>
</g>
<!-- SingleCoreTuning -->
<g id="node10" class="node">
<title>SingleCoreTuning</title>
<path fill="white" stroke="black" d="M1811.25,-468.07C1811.25,-468.07 1720.25,-468.07 1720.25,-468.07 1714.25,-468.07 1708.25,-462.07 1708.25,-456.07 1708.25,-456.07 1708.25,-444.07 1708.25,-444.07 1708.25,-438.07 1714.25,-432.07 1720.25,-432.07 1720.25,-432.07 1811.25,-432.07 1811.25,-432.07 1817.25,-432.07 1823.25,-438.07 1823.25,-444.07 1823.25,-444.07 1823.25,-456.07 1823.25,-456.07 1823.25,-462.07 1817.25,-468.07 1811.25,-468.07"/>
<text text-anchor="start" x="1716.25" y="-443.89" font-family="Times,serif" font-size="14.00">SingleCoreTuning</text>
</g>
<!-- OCTypeDecision&#45;&gt;SingleCoreTuning -->
<g id="edge9" class="edge">
<title>OCTypeDecision&#45;&gt;SingleCoreTuning</title>
<path fill="none" stroke="black" d="M1461.44,-226.46C1519.62,-269.35 1664.39,-376.08 1730.66,-424.94"/>
<polygon fill="black" stroke="black" points="1728.5,-427.69 1738.63,-430.81 1732.66,-422.06 1728.5,-427.69"/>
<text text-anchor="middle" x="1587.12" y="-372.74" font-family="Times,serif" font-size="14.00">single_core_tuning</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge10" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1757.07,-277.52C1743.54,-307.33 1712.4,-365.22 1665.5,-390.07 1612.58,-418.11 1186.67,-410.6 1127.25,-418.07 1071.25,-425.11 1058.71,-435.75 1002.75,-443.07 896.12,-457.02 868.74,-454.73 761.25,-458.07 627.56,-462.22 570.49,-511.26 461.25,-434.07 435.14,-415.62 416.77,-383.36 406.06,-359.85"/>
<polygon fill="black" stroke="black" points="409.33,-358.6 402.14,-350.81 402.91,-361.38 409.33,-358.6"/>
<text text-anchor="middle" x="1065" y="-441.28" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;POST -->
<g id="edge11" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1684.66,-258.79C1545.83,-258.32 1251.46,-257.4 1002.75,-257.07 903.42,-256.94 878.19,-248.21 779.25,-257.07 752.61,-259.45 722.94,-264.85 700.23,-269.58"/>
<polygon fill="black" stroke="black" points="699.57,-266.14 690.52,-271.65 701.03,-272.98 699.57,-266.14"/>
<text text-anchor="middle" x="1188.88" y="-258.48" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge12" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1737.58,-141.75C1683.02,-106.8 1555.23,-34.07 1436.5,-34.07 827.38,-34.07 827.38,-34.07 827.38,-34.07 709.17,-34.07 662.94,4.26 562.5,-58.07 489.39,-103.44 495.26,-144.04 461.25,-223.07 449.06,-251.39 459.78,-264.04 443.25,-290.07 439.77,-295.56 435.32,-300.69 430.53,-305.34"/>
<polygon fill="black" stroke="black" points="428.54,-302.42 423.4,-311.69 433.19,-307.65 428.54,-302.42"/>
<text text-anchor="middle" x="1065" y="-35.02" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;POST -->
<g id="edge13" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1683.38,-162.44C1584.97,-165.75 1414.35,-172.88 1268.5,-186.07 1050.15,-205.82 994.7,-208.5 779.25,-249.07 752.47,-254.11 722.65,-261.58 699.9,-267.67"/>
<polygon fill="black" stroke="black" points="699.22,-264.23 690.49,-270.23 701.06,-270.99 699.22,-264.23"/>
<text text-anchor="middle" x="1188.88" y="-199.62" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- SingleCoreTuning&#45;&gt;PoweredOff -->
<g id="edge23" class="edge">
<title>SingleCoreTuning&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1712.63,-468.54C1648.51,-489.58 1535.91,-521.07 1436.5,-521.07 660.88,-521.07 660.88,-521.07 660.88,-521.07 568.96,-521.07 532.13,-525.58 461.25,-467.07 428,-439.62 410.06,-391.51 401.46,-360.48"/>
<polygon fill="black" stroke="black" points="404.89,-359.77 398.99,-350.97 398.11,-361.53 404.89,-359.77"/>
<text text-anchor="middle" x="1065" y="-522.02" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- SingleCoreTuning&#45;&gt;POST -->
<g id="edge24" class="edge">
<title>SingleCoreTuning&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1707.81,-446.81C1555.28,-437.12 1125.54,-403.62 779.25,-317.07 752.25,-310.32 722.5,-300.3 699.84,-292.11"/>
<polygon fill="black" stroke="black" points="701.35,-288.94 690.75,-288.78 698.94,-295.51 701.35,-288.94"/>
<text text-anchor="middle" x="1188.88" y="-402.53" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- BootLoop&#45;&gt;PoweredOff -->
<g id="edge19" class="edge">
<title>BootLoop&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M912.98,-416.02C901.89,-420.54 889.42,-424.79 877.5,-427.07 786.56,-444.44 544.18,-450.23 461.25,-409.07 439.33,-398.19 421.77,-376.49 410.21,-358.73"/>
<polygon fill="black" stroke="black" points="413.45,-357.32 405.21,-350.65 407.5,-361 413.45,-357.32"/>
<text text-anchor="middle" x="661.88" y="-441.21" font-family="Times,serif" font-size="14.00">trigger_cmos_reset | hard_shutdown</text>
</g>
<!-- IdleWaitingForInput -->
<g id="node12" class="node">
<title>IdleWaitingForInput</title>
<path fill="darksalmon" stroke="red" d="M119,-279.07C119,-279.07 16,-279.07 16,-279.07 10,-279.07 4,-273.07 4,-267.07 4,-267.07 4,-255.07 4,-255.07 4,-249.07 10,-243.07 16,-243.07 16,-243.07 119,-243.07 119,-243.07 125,-243.07 131,-249.07 131,-255.07 131,-255.07 131,-267.07 131,-267.07 131,-273.07 125,-279.07 119,-279.07"/>
<path fill="none" stroke="red" d="M123,-283.07C123,-283.07 12,-283.07 12,-283.07 6,-283.07 0,-277.07 0,-271.07 0,-271.07 0,-251.07 0,-251.07 0,-245.07 6,-239.07 12,-239.07 12,-239.07 123,-239.07 123,-239.07 129,-239.07 135,-245.07 135,-251.07 135,-251.07 135,-271.07 135,-271.07 135,-277.07 129,-283.07 123,-283.07"/>
<text text-anchor="start" x="12" y="-254.89" font-family="Times,serif" font-size="14.00">IdleWaitingForInput</text>
<title>BIOSSetup&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M774.91,-446.46C673.09,-451.63 397.39,-460.7 323.5,-412.25 286.78,-388.18 268.43,-338.29 260.08,-306.36"/>
<polygon fill="black" stroke="black" points="263.56,-305.86 257.8,-296.97 256.75,-307.51 263.56,-305.86"/>
<text text-anchor="middle" x="568.38" y="-451.64" font-family="Times,serif" font-size="14.00">finished_bios_setup</text>
</g>
<!-- IdleWaitingForInput&#45;&gt;PoweredOff -->
<g id="edge20" class="edge">
<g id="edge22" class="edge">
<title>IdleWaitingForInput&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M135.29,-275.49C196.69,-288.74 286.38,-308.11 342.07,-320.13"/>
<polygon fill="black" stroke="black" points="341.09,-323.5 351.6,-322.19 342.56,-316.65 341.09,-323.5"/>
<text text-anchor="middle" x="239.62" y="-316.9" font-family="Times,serif" font-size="14.00">hard_shutdown | soft_shutdown</text>
<path fill="none" stroke="black" d="M782.75,-263.83C770.97,-254.56 757.65,-243.39 746.5,-232.25 684.48,-170.29 701.17,-116.9 622,-79.25 452.13,1.52 376.7,-51.42 200.5,-117.25 153.49,-134.82 138.25,-135.67 99.25,-167.25 83.5,-180 69.34,-197.8 59,-212.62"/>
<polygon fill="black" stroke="black" points="56.31,-210.35 53.63,-220.6 62.12,-214.27 56.31,-210.35"/>
<text text-anchor="middle" x="410.12" y="-70.19" font-family="Times,serif" font-size="14.00">hard_shutdown | soft_shutdown</text>
</g>
<!-- IdleWaitingForInput&#45;&gt;POST -->
<g id="edge21" class="edge">
<g id="edge23" class="edge">
<title>IdleWaitingForInput&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M135.3,-262.99C260.06,-266.57 524.71,-274.16 623.04,-276.98"/>
<polygon fill="black" stroke="black" points="622.85,-280.48 632.94,-277.27 623.05,-273.48 622.85,-280.48"/>
<text text-anchor="middle" x="393.75" y="-272.76" font-family="Times,serif" font-size="14.00">power_on | reboot</text>
<path fill="none" stroke="black" d="M746,-276.08C709.45,-271.04 663.35,-265.51 622,-263 501.29,-255.68 358.06,-266.96 291.49,-273.34"/>
<polygon fill="black" stroke="black" points="291.46,-269.83 281.85,-274.29 292.15,-276.8 291.46,-269.83"/>
<text text-anchor="middle" x="568.38" y="-263.95" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- WaitingForHWInfo -->
<g id="node7" class="node">
<title>WaitingForHWInfo</title>
<path fill="white" stroke="black" d="M1127,-304.25C1127,-304.25 1027.75,-304.25 1027.75,-304.25 1021.75,-304.25 1015.75,-298.25 1015.75,-292.25 1015.75,-292.25 1015.75,-280.25 1015.75,-280.25 1015.75,-274.25 1021.75,-268.25 1027.75,-268.25 1027.75,-268.25 1127,-268.25 1127,-268.25 1133,-268.25 1139,-274.25 1139,-280.25 1139,-280.25 1139,-292.25 1139,-292.25 1139,-298.25 1133,-304.25 1127,-304.25"/>
<text text-anchor="start" x="1023.75" y="-280.07" font-family="Times,serif" font-size="14.00">WaitingForHWInfo</text>
</g>
<!-- IdleWaitingForInput&#45;&gt;WaitingForHWInfo -->
<g id="edge22" class="edge">
<g id="edge24" class="edge">
<title>IdleWaitingForInput&#45;&gt;WaitingForHWInfo</title>
<path fill="none" stroke="black" d="M89.75,-238.88C138.43,-190.54 263.81,-80.07 392.75,-80.07 392.75,-80.07 392.75,-80.07 950.12,-80.07 1006.27,-80.07 1068.91,-90.79 1115.79,-100.99"/>
<polygon fill="black" stroke="black" points="1114.75,-104.35 1125.27,-103.1 1116.27,-97.52 1114.75,-104.35"/>
<text text-anchor="middle" x="661.88" y="-81.02" font-family="Times,serif" font-size="14.00">begin_automation</text>
<path fill="none" stroke="black" d="M881.97,-286.25C919.42,-286.25 966.1,-286.25 1004.33,-286.25"/>
<polygon fill="black" stroke="black" points="1003.88,-289.75 1013.88,-286.25 1003.88,-282.75 1003.88,-289.75"/>
<text text-anchor="middle" x="948.62" y="-287.2" font-family="Times,serif" font-size="14.00">begin_automation</text>
</g>
<!-- WaitingForOS&#45;&gt;PoweredOff -->
<g id="edge6" class="edge">
<title>WaitingForOS&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M520.53,-103.99C471.03,-102.62 390.94,-103.29 323.5,-117.25 266.23,-129.11 255.1,-143.04 200.5,-164 155.44,-181.3 142.27,-181.38 99.25,-203.25 91.96,-206.95 84.43,-211.34 77.32,-215.77"/>
<polygon fill="black" stroke="black" points="75.74,-212.62 69.21,-220.96 79.52,-218.52 75.74,-212.62"/>
<text text-anchor="middle" x="253" y="-164.95" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- WaitingForOS&#45;&gt;WaitingForHWInfo -->
<g id="edge7" class="edge">
<title>WaitingForOS&#45;&gt;WaitingForHWInfo</title>
<path fill="none" stroke="black" d="M616.16,-122.86C707.79,-155.39 910.9,-227.5 1013.89,-264.07"/>
<polygon fill="black" stroke="black" points="1012.42,-267.26 1023.01,-267.31 1014.76,-260.66 1012.42,-267.26"/>
<text text-anchor="middle" x="814" y="-215.09" font-family="Times,serif" font-size="14.00">os_booted</text>
</g>
<!-- OCTypeDecision -->
<g id="node8" class="node">
<title>OCTypeDecision</title>
<path fill="white" stroke="black" d="M1367.25,-307.25C1367.25,-307.25 1280.75,-307.25 1280.75,-307.25 1274.75,-307.25 1268.75,-301.25 1268.75,-295.25 1268.75,-295.25 1268.75,-283.25 1268.75,-283.25 1268.75,-277.25 1274.75,-271.25 1280.75,-271.25 1280.75,-271.25 1367.25,-271.25 1367.25,-271.25 1373.25,-271.25 1379.25,-277.25 1379.25,-283.25 1379.25,-283.25 1379.25,-295.25 1379.25,-295.25 1379.25,-301.25 1373.25,-307.25 1367.25,-307.25"/>
<text text-anchor="start" x="1276.75" y="-283.07" font-family="Times,serif" font-size="14.00">OCTypeDecision</text>
</g>
<!-- WaitingForHWInfo&#45;&gt;OCTypeDecision -->
<g id="edge20" class="edge">
<title>WaitingForHWInfo&#45;&gt;OCTypeDecision</title>
<path fill="none" stroke="black" d="M1139.47,-287C1175.38,-287.44 1220.78,-288 1257.43,-288.45"/>
<polygon fill="black" stroke="black" points="1256.95,-291.94 1267,-288.56 1257.04,-284.94 1256.95,-291.94"/>
<text text-anchor="middle" x="1203.88" y="-289.31" font-family="Times,serif" font-size="14.00">hwinfo_available</text>
</g>
<!-- RoughMulticoreUndervolt -->
<g id="node9" class="node">
<title>RoughMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1723,-536.25C1723,-536.25 1585.5,-536.25 1585.5,-536.25 1579.5,-536.25 1573.5,-530.25 1573.5,-524.25 1573.5,-524.25 1573.5,-512.25 1573.5,-512.25 1573.5,-506.25 1579.5,-500.25 1585.5,-500.25 1585.5,-500.25 1723,-500.25 1723,-500.25 1729,-500.25 1735,-506.25 1735,-512.25 1735,-512.25 1735,-524.25 1735,-524.25 1735,-530.25 1729,-536.25 1723,-536.25"/>
<text text-anchor="start" x="1581.5" y="-512.08" font-family="Times,serif" font-size="14.00">RoughMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;RoughMulticoreUndervolt -->
<g id="edge8" class="edge">
<title>OCTypeDecision&#45;&gt;RoughMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1351.31,-307.6C1409.89,-348.47 1551.14,-447.01 1617.58,-493.36"/>
<polygon fill="black" stroke="black" points="1615.37,-496.09 1625.58,-498.94 1619.38,-490.35 1615.37,-496.09"/>
<text text-anchor="middle" x="1475.62" y="-445.13" font-family="Times,serif" font-size="14.00">rough_multicore_undervolt</text>
</g>
<!-- PreciseMulticoreUndervolt -->
<g id="node10" class="node">
<title>PreciseMulticoreUndervolt</title>
<path fill="white" stroke="black" d="M1724.5,-362.25C1724.5,-362.25 1584,-362.25 1584,-362.25 1578,-362.25 1572,-356.25 1572,-350.25 1572,-350.25 1572,-338.25 1572,-338.25 1572,-332.25 1578,-326.25 1584,-326.25 1584,-326.25 1724.5,-326.25 1724.5,-326.25 1730.5,-326.25 1736.5,-332.25 1736.5,-338.25 1736.5,-338.25 1736.5,-350.25 1736.5,-350.25 1736.5,-356.25 1730.5,-362.25 1724.5,-362.25"/>
<text text-anchor="start" x="1580" y="-338.07" font-family="Times,serif" font-size="14.00">PreciseMulticoreUndervolt</text>
</g>
<!-- OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt -->
<g id="edge9" class="edge">
<title>OCTypeDecision&#45;&gt;PreciseMulticoreUndervolt</title>
<path fill="none" stroke="black" d="M1379.52,-293.13C1426.16,-297.05 1494.92,-304.22 1554,-316 1563.57,-317.91 1573.57,-320.28 1583.37,-322.84"/>
<polygon fill="black" stroke="black" points="1582.3,-326.18 1592.86,-325.4 1584.12,-319.42 1582.3,-326.18"/>
<text text-anchor="middle" x="1475.62" y="-316.95" font-family="Times,serif" font-size="14.00">precise_multicore_undervolt</text>
</g>
<!-- SingleCoreTuning -->
<g id="node11" class="node">
<title>SingleCoreTuning</title>
<path fill="white" stroke="black" d="M1699.75,-195.25C1699.75,-195.25 1608.75,-195.25 1608.75,-195.25 1602.75,-195.25 1596.75,-189.25 1596.75,-183.25 1596.75,-183.25 1596.75,-171.25 1596.75,-171.25 1596.75,-165.25 1602.75,-159.25 1608.75,-159.25 1608.75,-159.25 1699.75,-159.25 1699.75,-159.25 1705.75,-159.25 1711.75,-165.25 1711.75,-171.25 1711.75,-171.25 1711.75,-183.25 1711.75,-183.25 1711.75,-189.25 1705.75,-195.25 1699.75,-195.25"/>
<text text-anchor="start" x="1604.75" y="-171.07" font-family="Times,serif" font-size="14.00">SingleCoreTuning</text>
</g>
<!-- OCTypeDecision&#45;&gt;SingleCoreTuning -->
<g id="edge10" class="edge">
<title>OCTypeDecision&#45;&gt;SingleCoreTuning</title>
<path fill="none" stroke="black" d="M1379.2,-270.76C1436.66,-251.15 1527.39,-220.19 1588.56,-199.32"/>
<polygon fill="black" stroke="black" points="1589.47,-202.71 1597.81,-196.17 1587.21,-196.08 1589.47,-202.71"/>
<text text-anchor="middle" x="1475.62" y="-263.13" font-family="Times,serif" font-size="14.00">single_core_tuning</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge11" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1616.37,-536.53C1556.69,-564.39 1434.55,-614.25 1325,-614.25 252,-614.25 252,-614.25 252,-614.25 169.87,-614.25 145.06,-578.42 99.25,-510.25 48.41,-434.59 41.3,-322.33 41.01,-269.61"/>
<polygon fill="black" stroke="black" points="44.51,-269.94 41.04,-259.93 37.51,-269.92 44.51,-269.94"/>
<text text-anchor="middle" x="814" y="-615.2" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- RoughMulticoreUndervolt&#45;&gt;POST -->
<g id="edge12" class="edge">
<title>RoughMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1573.32,-518.25C1506.85,-518.25 1409.77,-518.25 1325,-518.25 947.62,-518.25 947.62,-518.25 947.62,-518.25 808.9,-518.25 434.1,-587.99 323.5,-504.25 261.72,-457.48 253.2,-356.98 253.03,-306.89"/>
<polygon fill="black" stroke="black" points="256.53,-307.13 253.12,-297.1 249.53,-307.07 256.53,-307.13"/>
<text text-anchor="middle" x="948.62" y="-520.76" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;PoweredOff -->
<g id="edge13" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1643.61,-362.68C1628.48,-389.56 1596.44,-438.87 1554,-462.25 1540.34,-469.78 1013.25,-536.55 997.75,-538.25 859.21,-553.47 824.62,-564.25 685.25,-564.25 252,-564.25 252,-564.25 252,-564.25 112.29,-564.25 60.65,-349.73 46.26,-269.8"/>
<polygon fill="black" stroke="black" points="49.74,-269.35 44.59,-260.09 42.84,-270.54 49.74,-269.35"/>
<text text-anchor="middle" x="814" y="-564.33" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- PreciseMulticoreUndervolt&#45;&gt;POST -->
<g id="edge14" class="edge">
<title>PreciseMulticoreUndervolt&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1571.64,-344.25C1505.22,-344.25 1409.06,-344.25 1325,-344.25 567.38,-344.25 567.38,-344.25 567.38,-344.25 465.67,-344.25 349.41,-310.08 291.26,-290.55"/>
<polygon fill="black" stroke="black" points="292.45,-287.26 281.85,-287.34 290.19,-293.88 292.45,-287.26"/>
<text text-anchor="middle" x="948.62" y="-345.2" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- SingleCoreTuning&#45;&gt;PoweredOff -->
<g id="edge25" class="edge">
<title>SingleCoreTuning&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M1631.85,-158.86C1581.79,-117.8 1451.67,-22.25 1325,-22.25 252,-22.25 252,-22.25 252,-22.25 171.34,-22.25 152.68,-59.82 99.25,-120.25 75.65,-146.94 59.57,-185.01 50.52,-211.07"/>
<polygon fill="black" stroke="black" points="47.27,-209.75 47.44,-220.34 53.91,-211.95 47.27,-209.75"/>
<text text-anchor="middle" x="814" y="-23.2" font-family="Times,serif" font-size="14.00">hard_shutdown</text>
</g>
<!-- SingleCoreTuning&#45;&gt;POST -->
<g id="edge26" class="edge">
<title>SingleCoreTuning&#45;&gt;POST</title>
<path fill="none" stroke="black" d="M1596.32,-177.25C1530.86,-177.25 1420.17,-177.25 1325,-177.25 813,-177.25 813,-177.25 813,-177.25 613.71,-177.25 380.62,-239.6 291.36,-265.83"/>
<polygon fill="black" stroke="black" points="290.5,-262.44 281.91,-268.64 292.5,-269.15 290.5,-262.44"/>
<text text-anchor="middle" x="948.62" y="-178.2" font-family="Times,serif" font-size="14.00">reboot</text>
</g>
<!-- BootLoop&#45;&gt;PoweredOff -->
<g id="edge21" class="edge">
<title>BootLoop&#45;&gt;PoweredOff</title>
<path fill="none" stroke="black" d="M532.49,-161.55C485.01,-163.65 397.49,-168.66 323.5,-179.25 222.7,-193.68 198.57,-203.78 99.25,-226.25 97.1,-226.74 94.91,-227.24 92.7,-227.75"/>
<polygon fill="black" stroke="black" points="91.98,-224.32 83.05,-230.02 93.59,-231.14 91.98,-224.32"/>
<text text-anchor="middle" x="253" y="-202.61" font-family="Times,serif" font-size="14.00">trigger_cmos_reset</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -8,21 +8,31 @@ resolution = "1920x1080"
fps = "60.000"
[client]
hostname = "10.20.30.48"
hostname = "10.20.30.90"
hwinfo_port = "60000" # Unless you've changed it!
# MAKE SURE YOU USE SINGLE QUOTES, THIS HAS TO BE A LITERAL
ryzen_smu_cli_path = 'C:\Users\rawhide\Downloads\win-x64\ryzen-smu-cli.exe'
ycruncher_path = 'C:\Users\rawhide\Downloads\y-cruncher v0.8.6.9545b\y-cruncher v0.8.6.9545\y-cruncher.exe'
bios_map_path = 'bios-maps/asus/x870-gaming-plus-wifi.gv'
[client.overclocking.common] # Just some ideas of how the settings may work for your system
# "ACPI SRAT L3 Cache As NUMA Domain" = "Enabled"
# "Spread Spectrum" = "Disabled"
# "PBO Limits" = "Motherboard"
# "Precision Boost Overdrive Scalar" = "10X"
# "Max CPU Boost Clock Override(+)" = "200"
# "Auto Driver Installer" = "Disabled"
# "dGPU Only Mode" = "Enabled"
"ACPI SRAT L3 Cache As NUMA Domain" = "Enabled"
"PBO Limits" = "Motherboard"
"Precision Boost Overdrive Scalar" = "10X"
"Max CPU Boost Clock Override(+)" = "200"
"Integrated Graphics" = "Disabled"
"Voltage training" = "Enabled"
"CPU Load-line Calibration" = "Level 8"
"CPU Current Capability" = "140%"
"Fixed CPU VRM Switching Frequency(KHz)" = "700"
"CPU Power Phase Control" = "Extreme"
"VDDSOC Current Capability" = "140%"
"Fixed VDDSOC Switching Frequency(KHz)" = "700"
"VDDSOC Power Phase Control" = "Extreme"
[client.overclocking.cpu]
[client.overclocking.memory]
# "DRAM Profile Setting" = "XMP1-6000"
# "DRAM Performance Mode" = "Aggressive"
# "SOC/Uncore OC Voltage (VDD_SOC)" = "1.1"
"VDDSOC Voltage Override" = "1.2"

View File

@ -1,3 +1,4 @@
from ipkvm import routes
from ipkvm import routes, states
from ipkvm.states import events
__all__ = ["routes"]
__all__ = ["routes", "states", "events"]

View File

@ -0,0 +1,6 @@
from . import states
model = states.Overclocking()
machine = states.MyMachine(model, states=states.State, initial=model.state)
machine.get_graph().draw('my_state_diagram.svg', prog='dot')

View File

@ -1,23 +1,29 @@
from ipkvm.app import ui
from . import model
from ipkvm.util.mkb import esp32_serial
from ipkvm.util.mkb.mkb import GPIO
import time
@ui.on("power_on")
def handle_poweron():
states.model.power_on()
model.power_on()
@ui.on("soft_power_off")
def handle_soft_poweroff():
states.model.soft_shutdown()
model.soft_shutdown()
@ui.on("hard_power_off")
def handle_hard_poweroff():
states.model.hard_shutdown()
model.hard_shutdown()
@ui.on("reboot_into_bios")
def handle_reboot_bios():
states.model.reboot_into_bios()
model.reboot_into_bios()
@ui.on("clear_cmos")
def handle_clear_cmos():
print("clear cmos and restart")
msg = {
"cmos": GPIO.HIGH.value
}
@ -28,11 +34,14 @@ def handle_clear_cmos():
}
esp32_serial.mkb_queue.put(msg)
time.sleep(1)
time.sleep(5)
power_switch(0.2)
spam_delete_until_bios()
@ui.on("test_route")
def handle_test_route():
graphs.test_route()
msg = {
"pwr": GPIO.HIGH.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.2)
msg = {
"pwr": GPIO.LOW.value
}
esp32_serial.mkb_queue.put(msg)

View File

@ -2,10 +2,13 @@ from enum import Enum
import time
from transitions.experimental.utils import with_model_definitions, add_transitions, transition
from transitions.extensions import GraphMachine
from ipkvm.util import esp32_serial
from ipkvm.util.mkb import GPIO, HIDKeyCode
from ipkvm.util.mkb import esp32_serial
from ipkvm.util.mkb.mkb import GPIO
from ipkvm.util.mkb.scancodes import HIDKeyCode
from ipkvm.app import logging, ui
logging.basicConfig(level=logging.INFO)
class State(Enum):
PoweredOff = "powered off"
EnterBIOS = "enter bios"
@ -22,15 +25,24 @@ class State(Enum):
class Overclocking:
state: State = State.IdleWaitingForInput
# wait for power status ig
time.sleep(0.5)
if esp32_serial.usb_status:
state: State = State.IdleWaitingForInput
else:
state: State = State.PoweredOff
_enter_bios_flag = False
_running_automatic = False
_current_BIOS_location = "EZ Mode"
# TRANSITION DEFINITIONS
@add_transitions(transition([State.PoweredOff, State.IdleWaitingForInput], State.POST, after="_power_on",
unless="client_powered"))
@add_transitions(transition(State.PoweredOff, State.POST, unless="client_powered"))
def power_on(self): ...
@add_transitions(transition(State.POST, State.WaitingForOS))
def enter_os(self): ...
def wait_os(self): ...
@add_transitions(transition(State.WaitingForOS, State.WaitingForHWInfo))
def os_booted(self): ...
@ -38,7 +50,7 @@ class Overclocking:
@add_transitions(transition(State.WaitingForHWInfo, State.OCTypeDecision))
def hwinfo_available(self): ...
@add_transitions(transition(State.POST, State.EnterBIOS, after="_enter_bios"))
@add_transitions(transition(State.POST, State.EnterBIOS))
def enter_bios(self): ...
@add_transitions(transition(State.EnterBIOS, State.BIOSSetup))
@ -60,14 +72,13 @@ class Overclocking:
State.PreciseMulticoreUndervolt, State.SingleCoreTuning], State.POST))
def reboot(self): ...
@add_transitions(transition([State.BIOSSetup, State.IdleWaitingForInput, State.BootLoop, State.POST,
State.WaitingForOS, State.RoughMulticoreUndervolt,
State.PreciseMulticoreUndervolt, State.SingleCoreTuning],
State.PoweredOff, after="_hard_shutdown", conditions="client_powered"))
@add_transitions(transition([State.BIOSSetup, State.IdleWaitingForInput, State.POST, State.WaitingForOS,
State.RoughMulticoreUndervolt, State.PreciseMulticoreUndervolt,
State.SingleCoreTuning], State.PoweredOff, after="_hard_shutdown"))
def hard_shutdown(self): ...
@add_transitions(transition(State.IdleWaitingForInput, State.PoweredOff,
after="_soft_shutdown", conditions="client_powered"))
after="_soft_shutdown"))
def soft_shutdown(self): ...
@add_transitions(transition(State.OCTypeDecision, State.RoughMulticoreUndervolt))
@ -79,11 +90,91 @@ class Overclocking:
@add_transitions(transition(State.OCTypeDecision, State.SingleCoreTuning))
def single_core_tuning(self): ...
@add_transitions(transition([State.POST, State.EnterBIOS], State.IdleWaitingForInput))
def go_idle(self): ...
# PROPERTIES GO HERE
@property
def client_powered(self):
return esp32_serial.power_status
return esp32_serial.usb_status
@property
def current_BIOS_location(self):
return self._current_BIOS_location
@current_BIOS_location.setter
def current_BIOS_location(self, value: str):
if type(value) == str:
self._current_BIOS_location = value
else:
raise ValueError("Attempted to set the current BIOS location to a non-string value!")
# STATE ENTRY FUNCTIONS
def on_enter_POST(self):
post_timer = time.time()
# If five minutes passes with no USB availability, something has gone terribly wrong...
while time.time() - post_timer <= 300 and not esp32_serial.usb_status:
pass
if not esp32_serial.usb_status:
self.unsuccessful_post()
else:
if self._enter_bios_flag:
self.enter_bios()
elif self._running_automatic:
self.wait_os()
else:
self.go_idle()
def on_enter_EnterBIOS(self):
# # Wait until the POST has progressed far enough for USB devices to be loaded and options to be imminent
# esp32_serial.notify_code = "45"
# esp32_serial.active_notification_request.set()
# esp32_serial.post_code_notify.wait()
# esp32_serial.post_code_notify.clear()
#
# # Spam delete until the BIOS is loaded
# esp32_serial.notify_code = "Ab"
# esp32_serial.active_notification_request.set()
# while not esp32_serial.post_code_notify.is_set():
spam_timer = time.time()
# Crushed by my lack of consistent access to BIOS post codes, we simply take our time...
while time.time() - spam_timer <= 10:
msg = {
"key_down": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
msg = {
"key_up": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
# esp32_serial.post_code_notify.clear()
# Wait a few seconds for the BIOS to become responsive
time.sleep(5)
self._enter_bios_flag = False
if self._running_automatic:
self.start_bios_setup()
else:
self.go_idle()
# STATE EXIT FUNCTIONS
def on_exit_PoweredOff(self):
self._power_switch(0.2)
# UTILITY FUNCTIONS GO HERE
def _power_switch(self, delay: float):
@ -98,68 +189,30 @@ class Overclocking:
esp32_serial.mkb_queue.put(msg)
# FUNCTIONS TRIGGERED BY STATE CHANGES
def _power_on(self):
self._power_switch(0.2)
# Unknown code definition, but this is the first consistent one indicating POST has started.
while esp32_serial.last_post_code != "FC":
pass
def _hard_shutdown(self):
self._power_switch(5)
while self.client_powered:
pass
def _soft_shutdown(self):
self._power_switch(0.2)
while self.client_powered:
while esp32_serial.usb_status:
pass
def _enter_bios(self):
# Wait until the POST has progressed far enough for USB devices to be loaded and options to be imminent
esp32_serial.notify_code = "45"
esp32_serial.active_notification_request.set()
esp32_serial.post_code_notify.wait()
esp32_serial.post_code_notify.clear()
# Spam delete until the BIOS is loaded
esp32_serial.notify_code = "Ab"
esp32_serial.active_notification_request.set()
while not esp32_serial.post_code_notify.is_set():
msg = {
"key_down": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
msg = {
"key_up": HIDKeyCode.Delete.value
}
esp32_serial.mkb_queue.put(msg)
time.sleep(0.1)
esp32_serial.post_code_notify.clear()
# Wait a few seconds for the BIOS to become responsive
time.sleep(5)
# Wait a few seconds to REALLY be sure we're powered off...
time.sleep(10)
# OTHER FUNCTIONS GO HERE
def reboot_into_bios(self):
if self.client_powered:
if esp32_serial.usb_status:
if self.state is State.IdleWaitingForInput:
self.soft_shutdown()
else:
self.hard_shutdown()
self._enter_bios_flag = True
self.power_on()
self.enter_bios()
@with_model_definitions
class MyMachine(GraphMachine):
pass
model = Overclocking()
machine = MyMachine(model, states=State, initial=model.state)
machine.get_graph().draw('my_state_diagram.svg', prog='dot')

View File

@ -14,7 +14,10 @@ function mkbhandler_load()
function keydown_handler(event)
{
socket.emit('key_down', event.code);
if (event.code != "MetaLeft" && event.code != "MetaRight")
{
socket.emit('key_down', event.code);
}
event.preventDefault();
event.stopPropagation();
}

View File

@ -1,8 +1,9 @@
let code_mirror;
let code_div;
function codemirror_load()
{
const code_div = document.getElementById('codemirror');
code_div = document.getElementById('codemirror');
code_mirror = CodeMirror(code_div, {
lineNumbers: true
@ -11,6 +12,19 @@ function codemirror_load()
socket.emit("get_current_profile", (data) => {
code_mirror.setValue(data)
});
code_div.addEventListener("mouseleave", disable_input);
code_div.addEventListener("mouseenter", enable_input);
}
function disable_input()
{
code_mirror.setOption("readOnly", "nocursor");
}
function enable_input()
{
code_mirror.setOption("readOnly", false);
}
window.addEventListener("load", codemirror_load);

View File

@ -12,9 +12,9 @@ function create_table(data) {
container.innerText = ""
Object.keys(data).forEach((key, index) => {
row_headers.push(key)
col_headers.push(key)
Object.keys(data[key]).forEach((value, subIndex) => {
col_headers.push(value)
row_headers.push(value)
});
});
@ -34,7 +34,7 @@ function update_core_info_table(data) {
hot.batch(() => {
Object.keys(data).forEach((key, index) => {
Object.keys(data[key]).forEach((value, subIndex) => {
hot.setDataAtCell(index, subIndex, data[key][value])
hot.setDataAtCell(subIndex, index, data[key][value])
});
});
});

View File

@ -2,9 +2,9 @@
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/vendor/socketio/socket.io.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/vendor/SegmentDisplay/segment-display.js') }}"></script>
<!-- <script src="{{ url_for('static', filename='js/vendor/SegmentDisplay/segment-display.js') }}"></script> -->
<script src="{{ url_for('static', filename='js/mkb_handler.js') }}"></script>
<script src="{{ url_for('static', filename='js/seven_segment.js') }}"></script>
<!-- <script src="{{ url_for('static', filename='js/seven_segment.js') }}"></script> -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/codemirror.css') }}">
<script src="{{ url_for('static', filename='js/vendor/codemirror/codemirror.js') }}"></script>
<script src="{{ url_for('static', filename='js/vendor/codemirror/toml/toml.js') }}"></script>
@ -46,7 +46,7 @@
<div class="cm-editor">
<div id="codemirror" class="cm-scroller"></div>
</div>
<div id="stats-table" class="ht-theme-main">Waiting for data...</div>
</div>
<div class="right-third">
<div class="row-flex-container">
@ -56,12 +56,13 @@
<button type="button" onclick="socket.emit(`reboot`);">Reboot</button>
<button type="button" onclick="socket.emit(`reboot_into_bios`);">Reboot into BIOS</button>
<button type="button" onclick="socket.emit(`clear_cmos`);">Clear CMOS</button>
<button type="button" onclick="socket.emit(`test_route`);">Test Route</button>
<button type="button" onclick="socket.emit(`apply_current_bios_settings`);">Apply Current BIOS Settings</button>
</div>
<div id="streamview" class="stream-container">
<img src="/video_feed" class="stream-view" />
</div>
<div class="row-flex-container right-third">
<div id="stats-table" class="ht-theme-main">Waiting for data...</div>
<!-- <div class="row-flex-container right-third">
<div id="post-log-container" class="post-log-container"></div>
<div id="displayView" class="topic segment-container">
<div style="padding:20px">
@ -71,7 +72,7 @@
</div>
</div>
</div>
</div>
</div> -->
</div>
</div>
</body>

View File

@ -1,3 +1,5 @@
from . import hwinfo
from .mkb import events
from .profiles import events
__all__ = ["hwinfo", "events"]

View File

@ -1,70 +0,0 @@
import networkx as nx
from networkx import Graph
from typing import Any
from ipkvm.util import esp32_serial
from ipkvm.util.mkb import ASCII2JS
import time
# Type checker lunacy!
type MultiDiGraph = Graph[Any]
key_delay = 0.1
def traverse_path(graph: MultiDiGraph, node_a: str, node_b: str):
path = nx.shortest_path(graph, node_a, node_b)
path_edges = list(zip(path[:-1], path[1:]))
edge_path= [(u, v, graph[u][v]) for u, v in path_edges]
for step in edge_path:
if "initial_keypath" in step[2][0] and step[2][0]["visited"] == "false":
keys = step[2][0]["initial_keypath"].split(',')
# Type checker is simply wrong! This is the correct usage!
graph.edges[step[0], step[1], 0]["visited"] = "true" # type: ignore
else:
keys = step[2][0]["keypath"].split(',')
for key in keys:
time.sleep(key_delay)
esp32_serial.ez_press_key(key)
def apply_setting(graph: MultiDiGraph, setting_node: str, new_value: str):
if graph.nodes[setting_node]["option_type"] == "list":
possible_values = graph.nodes[setting_node]["options"].split(',')
key = graph.nodes[setting_node]["traversal_key"]
time.sleep(key_delay)
esp32_serial.ez_press_key("Enter")
for value in possible_values:
time.sleep(key_delay)
if value == new_value:
esp32_serial.ez_press_key("Enter")
break
else:
esp32_serial.ez_press_key(key)
elif graph.nodes[setting_node]["option_type"] == "field":
for key in new_value:
time.sleep(key_delay)
esp32_serial.ez_press_key(ASCII2JS[key])
time.sleep(key_delay)
esp32_serial.ez_press_key("Enter")
print(f"Changed {setting_node} from {graph.nodes[setting_node]["value"]} to {new_value}!")
graph.nodes[setting_node]["value"] = new_value
def test_route(settings: dict[Any, Any]):
graph: MultiDiGraph = nx.nx_agraph.read_dot("bios-maps/asrock/b650e-riptide-wifi.gv")
current_node = "Main"
for category in settings:
for setting_node in settings[category]:
if graph.nodes[setting_node]["value"] != settings[category][setting_node]:
traverse_path(graph, current_node, setting_node)
current_node = setting_node
apply_setting(graph, setting_node, settings[category][setting_node])

View File

@ -51,7 +51,7 @@ class HWInfoMonitor(threading.Thread):
temp_list.append(round(reading["value"], 2))
elif match.group("core_vid"):
vid_list.append(reading["value"])
vid_list.append(round(reading["value"], 3))
elif match.group("core_mhz"):
mhz_list.append(round(reading["value"], 2))
@ -70,7 +70,8 @@ class HWInfoMonitor(threading.Thread):
ui.emit("update_core_info_table", core_dataframe.to_dict("index"))
except Exception as e:
print(e)
#print(e)
pass
def is_hwinfo_alive(self):
request = requests.get(self.request_url, timeout=1)

View File

@ -1,15 +1,17 @@
from enum import IntEnum
from os import name, listdir
import serial
from ipkvm.app import logger, ui
from ipkvm.app import logger
from ipkvm.util.profiles import profile_manager
import threading
from queue import Queue
import json
import networkx as nx
import time
from collections.abc import Mapping
from .post_codes import POSTTextDef, POSTHex7Segment
from .scancodes import HIDKeyCode
# from .post_codes import POSTTextDef, POSTHex7Segment
from .scancodes import ASCII2JS, HIDKeyCode
from ipkvm.util.types import MultiDiGraph, OverclockingDict
class GPIO(IntEnum):
LOW = 0
@ -18,13 +20,17 @@ class GPIO(IntEnum):
class Esp32Serial(threading.Thread):
def __init__(self):
super().__init__()
self.post_code_queue: Queue[str] = Queue()
# self.post_code_queue: Queue[str] = Queue()
self.mkb_queue: Queue[Mapping[str, int | str | Mapping[str, int]]] = Queue()
self._power_status = False
self._last_post_code = "00"
self.notify_code: str
self.active_notification_request = threading.Event()
self.post_code_notify = threading.Event()
# self._power_status = False
self._usb_status = False
self._last_usb_status = False
# self._last_post_code = "00"
# self.notify_code: str
# self.active_notification_request = threading.Event()
# self.post_code_notify = threading.Event()
self._key_delay = 0.2
self.start()
@ -48,19 +54,29 @@ class Esp32Serial(threading.Thread):
try:
line = json.loads(ser.readline().decode().strip())
if "pwr" in line:
self._power_status = line["pwr"]
# self._power_status = line["pwr"]
self._usb_status = line["usb"]
elif "post_code" in line:
self._last_post_code = POSTHex7Segment[line["post_code"]]
if self._usb_status != self._last_usb_status:
if self._usb_status:
logger.info("Client machine cleared POST.")
else:
logger.info("Client machine powered off.")
ui.emit("update_seven_segment", POSTHex7Segment[line["post_code"]])
ui.emit("update_post_log", f"{POSTTextDef[line["post_code"]]}: {POSTHex7Segment[line["post_code"]]}")
self._last_usb_status = self._usb_status
if self.active_notification_request.is_set():
if self._last_post_code == self.notify_code:
self.post_code_notify.set()
self.active_notification_request.clear()
# elif "post_code" in line:
# self._last_post_code = POSTHex7Segment[line["post_code"]]
#
# ui.emit("update_seven_segment", POSTHex7Segment[line["post_code"]])
# ui.emit("update_post_log", f"{POSTTextDef[line["post_code"]]}: {POSTHex7Segment[line["post_code"]]}")
#
# if self.active_notification_request.is_set():
# if self._last_post_code == self.notify_code:
# self.post_code_notify.set()
# self.active_notification_request.clear()
#
# print(f"{POSTTextDef[line["post_code"]]}: {POSTHex7Segment[line["post_code"]]}")
except json.JSONDecodeError:
continue
@ -77,7 +93,7 @@ class Esp32Serial(threading.Thread):
bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE)
else:
raise RuntimeError("Your OS is unsupported!")
raise RuntimeError("Your OS is unsupported at this time!")
def ez_press_key(self, key: str):
msg = msg = {
@ -100,11 +116,72 @@ class Esp32Serial(threading.Thread):
serial_devices = []
return serial_devices
def _traverse_path(self, graph: MultiDiGraph, node_a: str, node_b: str):
path = nx.shortest_path(graph, node_a, node_b)
path_edges = list(zip(path[:-1], path[1:]))
edge_path= [(u, v, graph[u][v]) for u, v in path_edges]
@property
def power_status(self):
return self._power_status
for step in edge_path:
if "initial_keypath" in step[2][0] and step[2][0]["visited"] == "false":
keys = step[2][0]["initial_keypath"].split(',')
# Type checker is simply wrong! This is the correct usage!
graph.edges[step[0], step[1], 0]["visited"] = "true" # type: ignore
else:
keys = step[2][0]["keypath"].split(',')
for key in keys:
time.sleep(self._key_delay)
self.ez_press_key(key)
def _apply_setting(self, graph: MultiDiGraph, setting_node: str, new_value: str):
if graph.nodes[setting_node]["option_type"] == "list":
possible_values = graph.nodes[setting_node]["options"].split(',')
key = graph.nodes[setting_node]["traversal_key"]
time.sleep(self._key_delay)
self.ez_press_key("Enter")
for value in possible_values:
time.sleep(self._key_delay)
if value == new_value:
self.ez_press_key("Enter")
break
else:
self.ez_press_key(key)
elif graph.nodes[setting_node]["option_type"] == "field":
for key in new_value:
time.sleep(self._key_delay)
self.ez_press_key(ASCII2JS[key])
time.sleep(self._key_delay)
self.ez_press_key("Enter")
logger.info(f"Changed {setting_node} from {graph.nodes[setting_node]["value"]} to {new_value}!")
graph.nodes[setting_node]["value"] = new_value
def apply_all_settings(self, settings: OverclockingDict, graph: MultiDiGraph, current_node: str):
for category in settings:
for setting_node in settings[category]:
if graph.nodes[setting_node]["value"] != settings[category][setting_node]:
self._traverse_path(graph, current_node, setting_node)
current_node = setting_node
self._apply_setting(graph, setting_node, settings[category][setting_node])
return current_node
# @property
# def power_status(self):
# return self._power_status
@property
def last_post_code(self):
return self._last_post_code
def usb_status(self):
return self._usb_status
# @property
# def last_post_code(self):
# return self._last_post_code

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
import tomlkit
from ipkvm.app import ui
from . import profile_manager
from ipkvm.util.mkb import esp32_serial
from ipkvm.states import model
@ui.on("get_current_profile")
def handle_current_profile():
@ -12,4 +14,9 @@ def handle_save_profile(data: str):
@ui.on("save_profile_as")
def handle_save_profile_as(data: str, name: str):
profile_manager.save_profile(tomlkit.parse(data), name) # type: ignore
profile_manager.save_profile(tomlkit.parse(data), name) # type: ignore
@ui.on("apply_current_bios_settings")
def handle_bios_settings():
model.current_BIOS_location = esp32_serial.apply_all_settings(profile_manager.profile["client"]["overclocking"],
profile_manager.bios_map, model.current_BIOS_location)

View File

@ -1,26 +1,10 @@
from networkx import nx_agraph
from os import listdir
from os.path import exists
import threading
import tomlkit
from ipkvm.app import logger, ui
from typing import TypedDict
class VideoDict(TypedDict):
friendly_name: str
resolution: str
fps: str
class ServerDict(TypedDict):
esp32_serial: str
video_device: VideoDict
class ClientDict(TypedDict):
hostname: str
hwinfo_port: str
overclocking: dict[str, dict[str, str]]
class ProfileDict(TypedDict):
server: ServerDict
client: ClientDict
from ipkvm.app import logger
from ipkvm.util.types import MultiDiGraph, ProfileDict
class ProfileManager():
def __init__(self):
@ -29,6 +13,7 @@ class ProfileManager():
self.restart_hwinfo = threading.Event()
self._cur_profile_name: str = ""
self._profiles = listdir("profiles")
self._bios_map: MultiDiGraph
if len(self._profiles) == 0:
logger.info("No profiles found, loading default profile.")
@ -50,6 +35,9 @@ class ProfileManager():
with open(f"profiles/{name}", 'r') as file:
self._cur_profile_name = name
self._profile = tomlkit.parse(file.read()) # type: ignore
if exists(self._profile["client"]["bios_map_path"]):
self._bios_map = nx_agraph.read_dot(self._profile["client"]["bios_map_path"])
self.notify_all()
def save_profile(self, new_profile: ProfileDict, name: str = ""):
@ -94,3 +82,7 @@ class ProfileManager():
@property
def profile(self):
return self._profile
@property
def bios_map(self):
return self._bios_map

View File

@ -0,0 +1,31 @@
from networkx import Graph
from typing import Any, TypedDict
# Type checker lunacy!
type MultiDiGraph = Graph[Any]
class VideoDict(TypedDict):
friendly_name: str
resolution: str
fps: str
class ServerDict(TypedDict):
esp32_serial: str
video_device: VideoDict
class OverclockingDict(TypedDict):
common: dict[str, str]
cpu: dict[str, str]
memory: dict[str, str]
class ClientDict(TypedDict):
hostname: str
hwinfo_port: str
ryzen_smu_cli_path: str
ycruncher_path: str
bios_map_path: str
overclocking: OverclockingDict
class ProfileDict(TypedDict):
server: ServerDict
client: ClientDict