Exploring the Embedded Controller

That’s unusual, dare I say unlikely, as batteries wear even when not used.

Have you tried a full discharge and recharge to reset the battery read out.

Whereas the Embedded controller does control it doesn’t read the state of the battery. The battery info is pushed from the battery and if that isn’t calculating over a range it will not have a lot to work on.

Coulomb counting is one thing but measuring coulombs from 0 to 100 is a base measurement for wear.

That’s based on my limited understanding of course :slight_smile:

I have daily measurements and after a year I have managed to find a reading that says there is no wear but on average there seems to be less than 2% given the 3.4% wear upon receipt.

I have a limit of 78% max and run mostly plugged in

Sorry it is less than 3 years. I’ve got the battery in December 2021.

tlp-stat -b reports a loss of 10 mwh against the design capacity. So the loss is very small in that time frame. I’m most of the time on AC, but I can take the laptop on battery for some time and the charge would go from 80 % to 70 % but when plugged in it will not charge back to 80 %. I think this saves on battery cycle.

See the tlp-stat -b report below

--- TLP 1.3.1 --------------------------------------------

+++ Battery Features: Charge Thresholds and Recalibrate
natacpi    = active (data, thresholds)
tpacpi-bat = active (recalibrate)
tp-smapi   = inactive (ThinkPad not supported)

+++ ThinkPad Battery Status: BAT0 (Main / Internal)
/sys/class/power_supply/BAT0/manufacturer                   = LGC
/sys/class/power_supply/BAT0/model_name                     = 45N1029
/sys/class/power_supply/BAT0/cycle_count                    = (not supported)
/sys/class/power_supply/BAT0/energy_full_design             =  93240 [mWh]
/sys/class/power_supply/BAT0/energy_full                    =  93230 [mWh]
/sys/class/power_supply/BAT0/energy_now                     =  72400 [mWh]
/sys/class/power_supply/BAT0/power_now                      =      0 [mW]
/sys/class/power_supply/BAT0/status                         = Not charging

/sys/class/power_supply/BAT0/charge_start_threshold         =     40 [%]
/sys/class/power_supply/BAT0/charge_stop_threshold          =     80 [%]
tpacpi-bat.BAT0.forceDischarge                              =      0

Charge                                                      =   77.7 [%]
Capacity                                                    =  100.0 [%]

1 Like

@DHowett @Kieran_Levin
Are there any plans to get a signed version at some point?
Even though personally I’m exclusively a Linux user, my SO is on Windows, and it would be very nice to be able to use a Windows version without the need to go through Bitlocker or to switch into test mode!

thanks for making this ec tool, @DHowett !

i was able to set the charge limit without rebooting, and it was wonderful!

however, now i’ve set it back down to 50% after traveling, and the battery is staying at 100% charge. ectool reports that the charge limit is set to 50, but upower says it’s at 96%. do i need to do something other than just
sudo $(which ectool) fwchargelimit 50
to get it do go back down to 50%?

side note: i’d really like to learn how to write firmware like this. i know c, and i checked out the commit Add fwchargelimit and the framework OEM header 679cc25c4. how did you know to write that code? where would i go to learn how to do that? my experience with c is that i’ve written a couple implementations of malloc. i feel pretty comfortable with the c part, but not figuring out what bits to set to make the hardware do something.


i’d totally like to help out with the project! let me know if there’s any task(s) on your TODO list. i did not see one in the repo.

I would love to have a way to lift the TDP limits. I haven´t had 12gen in my hands yet, but I can confirm that 11gen is limited in a way - TDP is first unlimited, then after a few seconds 28W hard limit kicks in and no amount of playing around in Throttlestop will lift that. I read that it is because EC overrules Throttlestop, which brought me to this topic, hoping someone more capable looked at this.

I want to experiment with water cooling or other cooling improvements, for use in my FW Tablet Lite project. The idea is that the tablet will be good as a tablet or laptop with a keyboard folio, but especially a gaming PC when plugged into an eGPU. But the performance could just be so much better. With the 28W power limit, we are looking at about 3.3 GHz sustained. WIthout the limit, the 1165g7 should be doing about 4.2 GHz all core. Now, the stock cooling can´t handle it at full power, it can hit 3.5-3.6 GHz but in my tablet there is some room so I wanted to experiment with water cooling strapped to the heatpipes that would be possible to plug in when you get home and use it as a desktop.

But why would I do it if there is nothing to gain, as the CPU is (after several seconds) limited to 28W? Do you guys think it would be possible to make it work on Windows?

I am also thinking about the new Ryzen boards, the 8-core makes little sense if it gets the same cooling and power limits as the 6-core. But if those limits could be unlocked, having a 10.5" device that weighs under 1kg and features desktop performance under certain circumstances, that would be very pleasant.

1 Like

Might there be a good reason that ectool doesn’t work on the new AMD Ryzen based Framework laptops yet? I get “Unable to establish host communication” for every --interface option I try.

I received mine just a couple days ago, I’ve installed firmware (bios) 3.03, and I’m running Arch linux with kernel 6.5.9, and have installed “fw-ectool” from aur, the build script basically just clones the latest from Dhowett/framework-ec and does make utils.

By default, the modules cros_ec and cros_ec_lpcs are loaded. I’ve tried modprobing a bunch more, including cros_ec_sysfs, cros_ec_dev, cros_ec_chardev, and cros_ec_i2c, they load but do nothing. Secure boot is off, lockdown is “[none]”. I’m flailing at this point (more generously, looking for a quick and easy clue about what key piece I’m missing).

$ sudo fw-ectool version
Missing Chromium EC memory map.
Unable to establish host communication
Couldn't find EC

$ sudo fw-ectool --interface=lpc version
Missing Chromium EC memory map.
Unable to establish host communication
Couldn't find EC


Sure seems like default or lpc should work. Any hints? Laptop too new?

EDIT: found a hint in dmesg:

[    2.950398] cros_ec_lpcs cros_ec_lpcs.0: EC ID not detected

Yeah, The EC on the AMD board is different and uses a different branch of the ChromeOS EC, and the communication interface changed - @DHowett went into detail here:


Much thanks for that link. After looking at the proposed linux kernel patches, I was able to build a working ectool from DHowett’s repo, with just this tweak (I am a bit surprised this was sufficient):

--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -120,7 +120,7 @@ extern "C" {
 #define EC_LPC_CMDR_SCI                BIT(5)  /* SCI event is pending */
 #define EC_LPC_CMDR_SMI                BIT(6)  /* SMI event is pending */
-#define EC_LPC_ADDR_MEMMAP       0x900
+#define EC_LPC_ADDR_MEMMAP       0xE00
 #define EC_MEMMAP_SIZE         255 /* ACPI IO buffer max is 255 bytes */
 #define EC_MEMMAP_TEXT_MAX     8   /* Size of a string in the memory map */
$ make utils PREFIX=/usr
  VERSION ec_version.h
  HOSTCC  util/ectool

$ sudo ./build/bds/util/ectool version
RO version:    azalea_v3.4.113237-ec:66fc84,os
RW version:    azalea_v3.4.113237-ec:66fc84,os
Firmware copy: RO

I’m, uh, not sure if there was a more obvious/intended way I should have known about, if this is old news or bad advice, my apologies :sweat_smile:

(I first tried using the upstream framework repo branch “lotus-zephyr” which he mentioned is used for the AMD model, and I could not figure out how to just compile ectool, with appropriate board config includes …)


@pierce interesting, have you noticed any incompatibility with that? Do commands such as ectool led power off and ectool fwchargelimit 60 work?

The changes in the kernel patch set were quite minimal, but I’m surprised changing the port was enough. Maybe @DHowett could elaborate?

Many commands do not work on my AMD Framework, but I suspect that some of those never worked on framework models, having been designed for chromebooks?

fwchargelimit works fully.

led is a bit weird, I could only get the power button to full brightness or off, color and level don’t seem to work, and it stays on even when the laptop is otherwise fully off, and I seemingly couldn’t fix it back to normal behavior without resetting/rebooting the EC. Partly due to my limited understanding, probably.

Also working:

  • version
  • uptimeinfo
  • battery
  • temps all
  • console
  • pwmgetfanrpm
  • fanduty
  • autofanctrl

I haven’t found working “typec” or “pd” related commands yet …


Sorry I’ve been distracted from this thread lately!

So! The only meaningful EC differences between the AMD Framework Laptop 13 and the earlier models are:

  1. It is using the more common Chrome EC protocol …
  2. … with a different base port for memory-mapped I/O.

Because of [1], most of the drivers already supported it. Because of [2], though, they just didn’t know it. :person_shrugging:

Absolutely true! The Framework Laptop doesn’t use any of the EC’s type C port management / port controller capabilities, for example.

Thank you for doing this!

I’ve updated my primary fork of ectool with a similar (albeit, more backwards-compatible!) change.

I suspect that rather a few people aren’t over on the new repository, so that could pose a bit of a problem… :smile:

… I’ve also finally pushed the patches for my UEFI EC toolkit …


Thank you @DHowett for this!
I get an error while building ectool from your gitlab repo on archlinux:

 ~/Desktop/ectool-main/build/: make ectool                                                                                          ✔ 
[  6%] Building CXX object src/CMakeFiles/ectool.dir/ec_flash.cc.o
[ 12%] Building CXX object src/CMakeFiles/ectool.dir/ec_panicinfo.cc.o
[ 18%] Building CXX object src/CMakeFiles/ectool.dir/ectool.cc.o
/home/foer/Desktop/ectool-main/src/ectool.cc:966:1: cc: not implemented: non-trivial marked Initializations not supported
  966 | };
      | ^
/home/foer/Desktop/ectool-main/src/ectool.cc:966:1: not implemented: non-trivial marked Initializations not supported
/home/foer/Desktop/ectool-main/src/ectool.cc:966:1: not implemented: non-trivial marked Initializations not supported
/home/foer/Desktop/ectool-main/src/ectool.cc:966:1: not implemented: non-trivial marked Initializations not supported
/home/foer/Desktop/ectool-main/src/ectool.cc:966:1: not implemented: non-trivial marked Initializations not supported
/home/foer/Desktop/ectool-main/src/ectool.cc:966:1: not implemented: non-trivial marked Initializations not supported
make[2]: *** [src/CMakeFiles/ectool.dir/build.make:104: src/CMakeFiles/ectool.dir/ectool.cc.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:116: src/CMakeFiles/ectool.dir/all] Errors 2
make: *** [Makefile:91: all] Errors 2

I’m not a programmer so i have no idea what caused this…maybe you have a hint for me?

The build is working now…i choosed the wrong compiler. The tool works fine now on AMD 7480U. Thank you!


Thanks for this! I’ve packaged it up as Nix Flake at tlvince/ectool.nix and can confirm it works fine on a Framework 13 AMD 7640U.


I also tried building from the new ectool repo, also ran into this compiler error using gcc (typical linux default, in my case very recent gcc-13.2.1)

src/ectool.cc:966:1: sorry, unimplemented: non-trivial designated initializers not supported

It’s an easy fix though:

--- a/src/ectool.cc
+++ b/src/ectool.cc
@@ -955,6 +955,7 @@ static const char *const ec_feature_names[] = {
                "Refined tablet mode hysteresis",
        [EC_FEATURE_EFS2] = "Early Firmware Selection v2",
+       [EC_FEATURE_SCP] = "System Companion Processor",
        [EC_FEATURE_ISH] = "Intel Integrated Sensor Hub",
        [EC_FEATURE_TYPEC_CMD] = "TCPMv2 Type-C commands",

I’m not sure if it would be appropriate to create an account on DHowett’s Gitlab instance to open a PR, this seems to be from upstream anyway? Actually, how was I able to compile from the old github framework-ec repo, it seems to have the same array? … is it just because in the old repo it was C, and in the new one it’s .cc aka c++? hmm …

EDIT: Yeah, it’s because it’s being compiled in C++ mode in the new ectool repo. Designated initializers are a C99 feature, and much more recent and a bit more limited in standard C++.


Thx that actually helped.

I do hope the cors_ec chages get merged upstream soon so that’ll work out of the box.

I wonder if that would also make charge limits work with tlp and stuff.

Sorry about that, and the delay in fixing it. The upstream project may have missed this when they moved to C++. I pushed a fix in 3ebe7b8.


@DHowett what is the status of your fork of EmbeddedController?

I’m asking because I see that your main branch is 710 commits ahead and 10098 commits behind the forked project and your last commit is from a year ago. What I’d like to do is use the fwchargelimit, has there been any interest in pushing your changes upstream?

– Wink

Thriving! I use it to submit pull requests to Framework.

If you’re asking about the build of ectool from that repository, however: it is not undergoing active development, as the bulk of the work has moved to a different repository with a much less annoying build system and more support for Windows, which also by chance tracks upstream¹ much better.

Unfortunately, that’s a bit of storytelling on GitHub’s part. My main branch tracks Framework’s hx20-hx30 branch (or the old hx20 branch), but GitHub believes it should be tracking Framework’s main branch. Well, unfortunately, Framework’s main branch is a point-in-time snapshot of Google’s upstream EC repository’s main branch.

This means that any work based on Framework’s code is already wildly out of date with Google’s as they forked the EC nearly three years ago. But also, that’s not a problem because it is tracking just fine against Framework’s hx20-hx30 branch.

But also, that doesn’t matter since ectool doesn’t change all that much. The version of ectool in that repository is entirely acceptable for the hx20 and hx30 (Intel 11th and 12th generation) as well as the AMD Framework Laptops (with the requisite kernel patches.)

I’m not intending on upstreaming fwchargelimit to either Framework or Google, for a couple reasons:

  • ectool is really just a diagnostic utility. It’s a veritable swiss army knife, but it is not an API and it is not a contract.
  • fwchargelimit is specific to a single OEM, and is built on the embedded controller’s support for OEM “host commands.” It would do unpredictable things on the majority of machines that ectool supports.

The right path forward is to use system-specific support libraries like this one from Framework Computer themselves, or device-specific kernel modules that integrate things like charge limits and LED control into the parts of the system where they actually belong.

Now, in the meantime… Dustin L. Howett / ectool · GitLab ships binaries for Linux-x64 and Windows

Hope that helps!

¹ Google, not Framework.


Are you planning to submit this to platform x86 after your other patch series lands?

@DHowett, txs for the info!

Since I happen to like and use Rust for my own programming it seems I should be able to easily clone and build framework_tool are there any gotchas I should worry about?