I want to access the embedded controller of my (windows) laptop to control the fan speed. Currently I am doing this manually using RW Everything - how can I access the embedded controller e.g. using C? Thanks for any hint!
Please note: I am aware that RW Everything can be used from the commandline, but calling it every second to read some register isn't that nice...
If your fan speed can be managed manually, you can typically adjust fan speeds in the BIOS/UEFI or using a third-party utility like SpeedFan within Windows.
First of all, open the notification area and select the power icon. Now click on “More power options” > “Change plan settings” > “Change advance power settings.” Now the processor power management submenu will appear, here you might see the “System Cooling Policy” option only if your laptop has built-in heat sensors.
If you're using RWEverything to simply change bits at physical memory addresses, you can always map physical memory to process local memory space using MmMapIoSpace or any of the other windows api functions that give you RW access to physical memory. After mapping the section of space that you need access to, you can directly address and alter it.
I've only ever used this method for writing to the parallel port on windows, but I've used similar solutions for other projects in linux.
Programmatically, you'd need to create a kernel mode driver that uses MmMapIoSpace and handles IOCTLs off the IRP_MJ_CONTROL major function and then call StartServiceManager, CreateService and StartService on it and then send IOCTLs using DeviceIoControl to perform tasks which manipulate underlying physical memory / IO space / MSRs. See: https://stackoverflow.com/a/40449498/7194773. You can no longer program the fan. Note Margaret's answer:
It's worth noting that 9y later the SuperIOs are gone in laptop systems, replaced by the ECs. ECs have their firmware and use the PECI interface to read the DTS of the CPU. The EC's PWM HW is accessible only from the EC, the OS has no longer control over the CPU FAN if not by setting the CPU throttling policy.
You used to be able to select a SuperIO logical device by writing 07h to I/O port 2Eh (Index register) which cause the southbridge to generate LPC cycles which cause the SIO to select the LDN register (at offset 07h in the generic space: offsets 00h–30h) and then write the LDN to port 2Fh (data register) to generate LPC cycles that cause the SIO to select that LDN. This would cause the configuration space of the LDN at offset 30h–FFh to be mapped in at the ports, which can then be accessed using the index and then read/writing to the data register. A bit in the LPC bridge on the PCH is used to select whether to expose ports 2F/2E or 4F/4E.
With the ECs, the registers have been separated into host view and an EC view. All of the PWM and PECI registers are no longer logical devices and their registers are only mapped into the MMIO space of the on board EC CPU, leaving only a few generic registers in the regular IO space visible to the host. Some LDNs expose IO base address registers in their own space (offset 30h–FFh) which allow extra registers to be mapped in. The EC's firmware uses the PECI bus to read the DTSs of the CPU and adjust fan speeds accordingly at known register offsets in its MMIO space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With