So, the plan is that the kernel device only replaces the “communication” layer–how the commands are sent to the EC and how responses are received–in ectool. The commands ectool offers (and an eventual standalone user-mode application!) will remain, and I’ll continue maintaining fw-ectool until there’s a better option for both communication and sending specific commands.
In working on this, I learned that the Linux kernel already had support for speaking the specific version of the protocol the Framework Laptop uses. I suspect that this is why ectooldid not: if they added support in the kernel, they wouldn’t need a user-mode implementation of it at all.
Switching to a supported kernel driver obviates the need to turn off Secure Boot and disable lockdown, as there will no longer be a user-mode application interacting directly with hardware I/O resources. It’ll be an important part of achieving broad availability.
On the Windows side, the hardest part is going to be code signing. Kernel-mode drivers must be signed with an EV certificate (typically only granted to company entities, and I do not have one of those at the moment ) and cross-signed by Microsoft before they will work outside of test mode and with Secure Boot enabled. The second part is easy… the first part, not so much. If you have any ideas, I am all ears!
I’m trying to figure out the purpose of the value stored in flash at 0x3C040, and I could use a little help! To that end, I’ve got a couple questions:
Would any of you be willing to share the contents of that region? If so, can you run the following commands? Also, do you remember the date when you first booted your laptop?
Thanks all! Coupled with me learning that I/O port 0x70/0x71 is for the CMOS/RTC, it seems pretty certain that that’s what this is for.
I’ll update the page with that info later. By default, I’ll include links back to your forum profiles as attribution. Please let me know if you don’t want this.
@DHowett Great writeup and tools! And really great job RE the firmware. What is your RE tool of choice? My go to tool lately is Ghidra.
EC flash from 0x3C000 to 0x3D000 is for factory tooling to write a mix of status and some info to.
The power button is RGW, so that is why you dont get blue.
We are going to post the EC source soon. So you should get a lot of questions answered.
Some of the commands are for factory use like 3E02 is used to remap some of the keyboard keys so that we can complete keyboard functional testing in the OS during manufacturing by having them emit normal scan codes.
The laptop has 2 power buttons. There is one on the mainboard in the upper right corner. If you hold it for about 10 seconds it will perform a battery disconnect sequence to safely put the battery into ship mode. The main power button does not do this.
If you hold the main power button for about 20 seconds it will reboot the EC as you noted.
If you have any questions I am happy to answer them.
@Kieran_Levin I’ve been wondering if it’s possible to get the details about the USB PD negotiations and state. My main goal is to programmatically determine the wattage of the currently-attached power source.
@Sean_Greenslade I am not sure if I enabled some of the host commands for the charge manager. But if they are enabled you should be able to get the per port current/voltage that is negociated using the result data from HC
EC_CMD_USB_PD_POWER_INFO 0x0103
hc_pd_power_info.
A lot of the PD commands wont work because our design uses a PD controller instead of a TCPC, so we dont care about populating the data to the PD policy manager engine.
Thanks so much! I’ve been using Ghidra as well, with the ghidra-firmware-utils plugin. It maps known UEFI protocols/guids/types and scans the target for them. Really takes the hassle out.
This is all excellent stuff, and I appreciate it! I do have a couple questions and notes
I’m planning on releasing (and hopefully getting signed) the CrosEC driver [DISCLOSURE: GPLv2!] and a cross-platform userland tool for setting up things like the charge limit/keyboard mapping. Please don’t let its existence stop you from changing how these host commands work–it’s supposed to be informative, not normative, and I’m happy to adapt¹ it–as it’s your firmware at the end of the day.
What does the high bit in 3E03’s flags do? I saw that it propagates something to the charge limit value (High bit + charge limit 80 => 0xD0), but I can’t figure out what it does with that bit afterwards.
What’s the “ME Lock” (3E06 possibly toggles it?)
Do you actually read the chassis intrusion counters into a TPM PCR? That would be super cool from a platform security perspective, but I might have made it up!
Is the UEFI configured not to load DriverOrder/Driver#### entries? I wrote FrameworkKeyMapDriver [MIT] which, right now, remaps Caps to Esc, but it only works with a bootloader that loads auxiliary drivers.
This is a feature idea, not a question, which you are free to ignore. If the Fn key toggled the use of a different matrix->scancode map² instead of a hardcoded post-scancode lookup, folks could add additional Fn mappings . . . which might be a really neat power user feature.
¹ Especially if you’d be willing to coordinate updates but that’s a hope, not a request.
² Probably three maps, since it looks like there’s a table for “fn locked/always”, “fn held only” and “something after fn held, but I can’t figure out why it’s not part of the second lookup”.
@DHowett thanks again for the reverse-engineering! I have a question:
cross-platform userland tool for setting up things like the charge limit/keyboard [
Specifically for charge limits, do your upstream kernel driver changes enable the standard threshold API under /sys/class/power_supply/...? If so then tlp should also work as a charge threshold tool, correct?
Unfortunately, no. Since this EC uses a custom implementation of charge limiting, additional driver support would be required to expose it to the threshold API.
The proposed patch set only adds support for communicating with the EC to the existing EC driver.
I would also be interested in this, and keeping it GPLv2. If you want to coordinate/collaborate we could build on your work. I don’t have much experience with windows driver development. But would be interested in some collaboration as this is really useful. If you need help getting it signed we could do a code review and get some CI running on it, and release signed builds (I think we would need to clone the repo under the Framework org and setup some code review process for pull requests).
The high bit allows you to set a limit but allow the laptop to charge to 100%. The idea with this is if we had an os utility we could trigger a 1 time override to the limit. Eg if you knew you had a long day of meetings you could charge up the battery once to 100%.
ME lock sets the ME region CPU strap pin to lock or unlock the ME region on boot.
We don’t load them into the TPM. This only drives bios password behavior. Eg trigger a bios password on boot.
I will need to check on this.
I would like to add an additional layer to the keyboard that could remap any key. But I think it would be better to map a different scancode to this, as the Fn key has some behavior that mixes with Fn lock. Eg Fn+Esc triggers Fn lock, and this only applies to the top row keys on the keyboard layer. But there is also Fn+ keys in the character section which need to only be active when Fn is held down, even if Fn Lock is active. Eg
Fn+ Delete = Insert
Fn+K = Scroll Lock
Fn+S = Sysreq
Fn+Left,right, up, down = Home, End, PageUp, PageDown
The second function for Fn+ Mapping is for the following keys, and is separate because these keys require multiple scancodes to send the command to the host. Eg Pause is actually 8 bytes. If you look up scanset 2, these are kind of special multibyte key codes so they have a separate function PS2 Keyboard Scan Codes | Online Documentation for Altium Products.
Fn+B = Break
Fn+P = Pause
I’m really looking forward to having any way to adjust the charge level / one shot 100% on screen in windows.
Love that you are “slogging” through this, and the FW support of it. Every time I check the forum and see the progress going on, I am so happy I bought a Framework Laptop.
I’ve updated the post linked above to be true to the actual upstream code (yay!), and archived the original reverse engineered info. It also includes a section on ongoing work, which contains a blurb about the patches and the Windows CrosEC driver.
Thanks. The 80% charge setting will help extend the usable life of the battery for those who use the laptop plugged in more often than they do on battery. It’s a lot more flexible than the BIOS “battery disconnect” option, which requires a working AC adapter to revert back to normal operation, so if you happen to lose power, you’re shift out of luck. Still a useful option in some cases, maybe for a slightly expanded battery that you want to keep from getting worse until you can get to a better place to take it apart (i.e. if you’re on a trip but still able to get by with it only on plug power, not using the battery, but you don’t have a good place to unscrew the laptop and take the battery out until you’re done with the trip)
A “charge threshold” adjustment in the BIOS would have been better (so it would be in effect even when the computer was shut down but still plugged into power) i.e. still charging up to 100%, only if the battery has fallen below (insert threshold here) since you won’t be drawing power from it when you are using it plugged in, so the only reduction would be self-discharge.
Also, how about a simple “cooling mode” option, without having to adjust a whole curve but there were 2 predefined options, one of which was called “quiet/default” and the second being “Performance cooling” where the fan defaults to a higher value in idle as well as kicking up higher at a lower temperature, so the CPU could spend more time doing it’s “Mobile Turbo” thing. Suggestion for next Framework model?
This is already available, in Linux at least. Look higher up in this thread for details and exact commands to use for direct control of the fans or to restore automatic mode.
I’m unsure of the status of Winblows support for this at the moment, because I refuse to allow that degenerate OS within 100m of my framework but @DHowett said he was working on such a thing.