From 813fd7484e707e72a179e46a37259fbc96ef942f Mon Sep 17 00:00:00 2001 From: pocopico <67732101+pocopico@users.noreply.github.com> Date: Wed, 28 Dec 2022 18:28:29 +0200 Subject: [PATCH] feat: update power status in I2C (#5) Signed-off-by: Jim Ma Signed-off-by: Jim Ma Co-authored-by: Jim Ma --- Makefile | 2 +- shim/bios/bios_psu_status_shim.c | 61 ++++++++++++++++++++++++++++++++ shim/bios/bios_psu_status_shim.h | 23 ++++++++++++ shim/bios_shim.c | 7 +++- 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 shim/bios/bios_psu_status_shim.c create mode 100644 shim/bios/bios_psu_status_shim.h diff --git a/Makefile b/Makefile index 4c8f526..5db649e 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ SRCS-y += compat/string_compat.c \ \ shim/storage/smart_shim.c shim/storage/sata_port_shim.c \ shim/bios/bios_hwcap_shim.c shim/bios/bios_hwmon_shim.c shim/bios/rtc_proxy.c \ - shim/bios/bios_shims_collection.c shim/bios_shim.c \ + shim/bios/bios_shims_collection.c shim/bios/bios_psu_status_shim.c shim/bios_shim.c \ shim/block_fw_update_shim.c shim/disable_exectutables.c shim/pci_shim.c shim/pmu_shim.c shim/uart_fixer.c \ \ redpill_main.c diff --git a/shim/bios/bios_psu_status_shim.c b/shim/bios/bios_psu_status_shim.c new file mode 100644 index 0000000..fb9e0ca --- /dev/null +++ b/shim/bios/bios_psu_status_shim.c @@ -0,0 +1,61 @@ +/** + * Overrides HWMONGetPSUStatusByI2C to provide fake psu status for SA6400 + */ +#include "bios_psu_status_shim.h" +#include "../../common.h" +#include "../shim_base.h" +#include "../../internal/override/override_symbol.h" //overriding HWMONGetPSUStatusByI2C +#include "../../config/platform_types.h" //hw_config, platform_has_hwmon_* +#include //CAPABILITY_*, CAPABILITY + +#define SHIM_NAME "mfgBIOS HWMONGetPSUStatusByI2C" + +static const struct hw_config *hw_config = NULL; +static override_symbol_inst *HWMONGetPSUStatusByI2C_ovs = NULL; + +static int HWMONGetPSUStatusByI2C_shim(void) +{ + return 1; +} + +int register_bios_psu_status_shim(const struct hw_config *hw) +{ + shim_reg_in(); + + if (unlikely(HWMONGetPSUStatusByI2C_ovs)) + shim_reg_already(); + + hw_config = hw; + override_symbol_or_exit_int(HWMONGetPSUStatusByI2C_ovs, "HWMONGetPSUStatusByI2C", HWMONGetPSUStatusByI2C_shim); + + shim_reg_ok(); + return 0; +} + +int unregister_bios_psu_status_shim(void) +{ + shim_ureg_in(); + + if (unlikely(!HWMONGetPSUStatusByI2C_ovs)) + return 0; //this is deliberately a noop + + int out = restore_symbol(HWMONGetPSUStatusByI2C_ovs); + if (unlikely(out != 0)) { + pr_loc_err("Failed to restore HWMONGetPSUStatusByI2C - error=%d", out); + return out; + } + HWMONGetPSUStatusByI2C_ovs = NULL; + + shim_ureg_ok(); + return 0; +} + +int reset_bios_psu_status_shim(void) +{ + shim_reset_in(); + put_overridden_symbol(HWMONGetPSUStatusByI2C_ovs); + HWMONGetPSUStatusByI2C_ovs = NULL; + + shim_reset_ok(); + return 0; +} \ No newline at end of file diff --git a/shim/bios/bios_psu_status_shim.h b/shim/bios/bios_psu_status_shim.h new file mode 100644 index 0000000..00c412d --- /dev/null +++ b/shim/bios/bios_psu_status_shim.h @@ -0,0 +1,23 @@ +#ifndef REDPILL_BIOS_PSU_STATUS_SHIM_H +#define REDPILL_BIOS_PSU_STATUS_SHIM_H + +#include //bool + +struct hw_config; +int register_bios_psu_status_shim(const struct hw_config *hw); + +/** + * This function should be called when we're unloading cleanly (=mfgBIOS is alive, we're going away). If the bios went + * away on its own call reset_bios_psu_status_shim() + */ +int unregister_bios_psu_status_shim(void); + +/** + * This function should be called when we're unloading because mfgBIOS went away. If the unload should be clean and + * restore all mfgBIOS elements to its original state (i.e. the mfgBIOS is still loaded and not currently unloading) + * call unregister_bios_psu_status_shim() instead. + */ +int reset_bios_psu_status_shim(void); + + +#endif //REDPILL_BIOS_HWCAP_SHIM_H diff --git a/shim/bios_shim.c b/shim/bios_shim.c index a7f32f8..db4a835 100644 --- a/shim/bios_shim.c +++ b/shim/bios_shim.c @@ -55,6 +55,7 @@ #include "../internal/helper/symbol_helper.h" //kernel_has_symbol() #include "bios/bios_shims_collection.h" //shim_bios_module(), unshim_bios_module(), shim_bios_disk_leds_ctrl() #include "bios/bios_hwcap_shim.h" //register_bios_hwcap_shim(), unregister_bios_hwcap_shim(), reset_bios_hwcap_shim() +#include "bios/bios_psu_status_shim.h" //register_bios_psu_status_shim(), unregister_bios_psu_status_shim(), reset_bios_psu_status_shim() #include //module notification #include //struct module @@ -103,6 +104,7 @@ static int bios_module_notifier_handler(struct notifier_block * self, unsigned l enable_symbols_capture(); reset_bios_shims(); reset_bios_hwcap_shim(); + reset_bios_psu_status_shim(); return NOTIFY_OK; } @@ -125,8 +127,10 @@ static int bios_module_notifier_handler(struct notifier_block * self, unsigned l bios_shimmed = true; pr_loc_inf("%s BIOS *fully* shimmed", mod->name); } else { //MODULE_STATE_COMING or MODULE_STATE_UNFORMED [but most likely actually MODULE_STATE_COMING] - if (likely(state == MODULE_STATE_COMING)) + if (likely(state == MODULE_STATE_COMING)){ register_bios_hwcap_shim(hw_config); + register_bios_psu_status_shim(hw_config); + } pr_loc_inf("%s BIOS *early* shimmed", mod->name); } @@ -274,6 +278,7 @@ int unregister_bios_shim(void) unshim_disk_leds_ctrl(); //this will be noop if nothing was registered unregister_bios_hwcap_shim(); //this will be noop if nothing was registered + unregister_bios_psu_status_shim(); //this will be noop if nothing was registered hw_config = NULL;