feat: update power status in I2C (#5)

Signed-off-by: Jim Ma <majinjing3@gmail.com>

Signed-off-by: Jim Ma <majinjing3@gmail.com>
Co-authored-by: Jim Ma <majinjing3@gmail.com>
This commit is contained in:
pocopico 2022-12-28 18:28:29 +02:00 committed by GitHub
parent 89f524913a
commit 813fd7484e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 2 deletions

View File

@ -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

View File

@ -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 <linux/synobios.h> //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;
}

View File

@ -0,0 +1,23 @@
#ifndef REDPILL_BIOS_PSU_STATUS_SHIM_H
#define REDPILL_BIOS_PSU_STATUS_SHIM_H
#include <linux/types.h> //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

View File

@ -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 <linux/notifier.h> //module notification
#include <linux/module.h> //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;