summaryrefslogtreecommitdiff
path: root/src/southbridge/intel/bd82x6x/me.h
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2019-11-21 21:47:31 +0300
committerAngel Pons <th3fanbus@gmail.com>2021-02-07 23:06:52 +0000
commit833e9bad4762e0dca6c867d3a18dbaf6d5166be8 (patch)
tree3e5ad211109146671cfd1efae96e64989d901727 /src/southbridge/intel/bd82x6x/me.h
parent20a609f0f77ef84ef7f4f5e487000347c361a29e (diff)
sb/intel/bd82x6x: Support ME Soft Temporary Disable Mode
- Add support for ME Soft Temporary Disable Mode. In this mode, ME doesn't load its kernel and freezes at Bring UP (BUP) phase. This mode is saved in ME NVRAM (and thus will remain for next reboots and poweroffs). - Add support of new CMOS option for Sandy Bridge and Ivy Bridge ThinkPads. HOW TO USE To disable ME: 1. nvramtool -w me_state=Disabled 2. reboot To enable it back: 1. nvramtool -w me_state=Normal 2. reboot To check current status: intelmetool -m Tested on ThinkPad X230 and ThinkPad X220. BACKGROUND There's no Intel documentation that would explain how this should be implemented, in public. Working binary sequence for MKHI command to put ME in Soft Temporary Disable Mode, as well as a way to bring ME out of it (by writing to H_GS register), was found and published by researchers from PT Security: 1. To disable ME, BIOS issues the disable command (before End of Post) and reboots. ME is supposed to be disabled on the next boot after DID (DRAM Init Done). My numerous tests show that issuing the command and rebooting is not enough. If we reboot too early, ME will not be disabled. Apparently, it is doing something in background after receiving the command. It works with a delay of 500-1000 ms. I also tried to dump all known (documented) registers, such as GMES and HFS, before and during the next 2 seconds after execution of the disable command to find a possible indication that something's changed in ME and we're ready to reboot. Found nothing unfortunately. 2. To enable ME back, host writes value 0x20000000 to H_GS. PT slides don't contain any more information on it, but my tests show, that after writing this value, GMES[31:28] is changing from 0x01 (BUP phase) to 0x03 (Policy Module) to 0x06 (Host Communication). Then, after some more time, fw_init_complete bit of HFS becomes 1. This means that ME starts loading its kernel immediately, without reboot. On the other hand, Lenovo BIOS clearly perform a reboot after enabling it (one reboot after saving the settings, then ThinkPad logo appears, and then one more reboot). I'm assuming we have to reset too. Change-Id: Ic01526c9731cbef4e8552bbc352133a2415787c2 Signed-off-by: Evgeny Zinoviev <me@ch1p.io> Reviewed-on: https://review.coreboot.org/c/coreboot/+/37115 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com> Reviewed-by: Nico Huber <nico.h@gmx.de>
Diffstat (limited to 'src/southbridge/intel/bd82x6x/me.h')
-rw-r--r--src/southbridge/intel/bd82x6x/me.h20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/southbridge/intel/bd82x6x/me.h b/src/southbridge/intel/bd82x6x/me.h
index 014fc1d9ea..d99c452669 100644
--- a/src/southbridge/intel/bd82x6x/me.h
+++ b/src/southbridge/intel/bd82x6x/me.h
@@ -171,6 +171,22 @@ struct mei_header {
#define MKHI_GLOBAL_RESET 0x0b
#define MKHI_FWCAPS_GET_RULE 0x02
+#define MKHI_FWCAPS_SET_RULE 0x03
+
+#define MKHI_DISABLE_RULE_ID 0x06
+
+#define CMOS_ME_STATE(state) ((state) & 0x1)
+#define CMOS_ME_CHANGED(state) (((state) & 0x2) >> 1)
+#define CMOS_ME_STATE_NORMAL 0
+#define CMOS_ME_STATE_DISABLED 1
+#define CMOS_ME_STATE_CHANGED 2
+
+#define ME_ENABLE_TIMEOUT 20000
+
+struct me_disable {
+ u32 rule_id;
+ u16 data;
+} __packed;
#define MKHI_MDES_ENABLE 0x09
@@ -228,6 +244,10 @@ void mei_write_dword_ptr(void *ptr, int offset);
#ifndef __SIMPLE_DEVICE__
void pci_read_dword_ptr(struct device *dev, void *ptr, int offset);
+bool enter_soft_temp_disable(void);
+void enter_soft_temp_disable_wait(void);
+void exit_soft_temp_disable(struct device *dev);
+void exit_soft_temp_disable_wait(struct device *dev);
#endif
void read_host_csr(struct mei_csr *csr);