From my mid-grade understanding of battery chemistry and longevity issues, I would choose to keep a single constant moderate charge level, versus constantly cycling up and down 20%.
This is awesome work!
Excited to see if there’s any possibility for more advanced keyboard remapping. Would love to use the fn key as a modifier.
Unfortunately, it looks like the Fn key mappings are compiled in (today) and can’t be changed. You can change what the key labelled Fn does by mapping it to a different scancode and assigning different behaviors to it in the OS, but you won’t be able to treat it like a “layer” in the classical keyboarding sense.
@DHowett - thank you for building this, I’m enjoying poking around at things a bit. I noted on your page that the power led does not support blue (fyi for those reading, if you enter an incorrect color, in my case orange, you are presented with valid values - red green blue yellow white amber). When testing the different values, I found that when I entered blue as the color, the led appeared to turn off. While the ability at a glance to see if the power is on is lost, those who find the power led too bright may find this to be a reasonable temporary workaround to turn it off when so desired.
I’ve pushed a minor update to the page documenting host command 3E02
, some Fn key combinations, VBAT RAM, and that fanduty
/autofanctrl
works (thanks @D.H!)
3E02 (more info)
This command seems to disable the FN/Power keys. When you call it with 0x01
, it remaps them to send scancodes e016
and e025
(respectively). When you call it with 0x5A
it resets some local configuration in the EC (charge limit, keyboard backlight, etc.)
Keys (more info)
Fn+B is Ctrl+Break, Fn+P is Pause, and Fn+K is Scroll Lock.
Using blue to turn off the power button LED is pretty clever, actually!
Alright! I’ve pushed an update to fw-ectool
that fixes reading mapped memory; now commands like battery
and temps
work properly.
$ ectool temps all
--sensor name -------- temperature -------- fan speed --
F75303_Local 303 K (= 30 C) 0%
F75303_CPU 303 K (= 30 C) 0%
F75303_DDR 301 K (= 28 C) 0%
Battery 296 K (= 23 C) 0%
PECI 306 K (= 33 C) 0%
$ ectool battery
EC returned error result code 3
Battery info:
OEM name: NVT
Model number: Framewo
Chemistry : LION
Serial number: 00CD
Design capacity: 3572 mAh
Last full charge: 3560 mAh
Design output voltage 15400 mV
Cycle count 37
Present voltage 16625 mV
Present current 0 mA
Remaining capacity 2896 mAh
Flags 0x0b AC_PRESENT BATT_PRESENT CHARGING
In addition, I’ve documented a few more host commands:
3E09 - Chassis Intrusion Data (more info)
This host command reports whether the chassis has ever been opened and if so, how many times.
3E0F - Chassis Status
Reports whether the chassis is open right now. Does not include historical data.
3E04 - Get Fan 0 RPM
Returns the RPM of the system fan as a 32-bit integer:
3e04(...0 bytes...)
Read 4 bytes
ff 06 00 00 |....| #<< 1791 RPM
Operates very similarly to pwmgetfanrpm 0
, which returns Fan 0 RPM: 1789
Undocumented Interactions
You can reboot the EC by holding power for 20 seconds. The charge LEDs will flash to indicate that you’ve done so.
Since I’m no longer on holiday from real life, updates are going to slow down… but I still hope to write a Windows driver/userland application pair that will let you control the charge limit (among other things) without getting your hands too dirty. We’ll see!
Jan 7 Update:
Linux Kernel Support
I’ve submitted a patch series to add support to the kernel for the Framework EC. It’s a small change to the ChromeOS EC driver to make it suitable for Framework, and the ChromeOS person who owns that code (1) is in support of the patch and (2) is a fan of the Framework Laptop!
When this merges, I can remove the code from fw-ectool
that supports --interface=fwk
since all communication can be delegated to the existing kernel interface. Upstream ectool
(which should be available in your distributor’s repository) will work without modification!¹
¹ Caveat being that it won’t do anything Framework-specific.
Windows Support
I’m currently working on a Windows driver that is compatible (or mostly compatible) with the Linux cros_ec
device driver, and have ported ectool
to use it².
This is, of course, going to be open-source . . . but I need to assign an appropriate license and write up some documentation before I do so. Eventually, I’d like to pursue code signing so that you all don’t need to enable test mode (which disables driver signature enforcement and slaps a watermark on your desktop) on your computers.
² Also, got ectool building on Windows. It has surprisingly few Linuxisms, but there were a couple.
How does this affect the fwk command words you added earlier? Do we have to go back to the raw command hex codes?
Good on you for bringing this to more platforms and hopefully more distros/repos, to make it even easier for end users to find and implement…
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 ectool
did 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?
Steps
- Unlock flash
ectool --interface=fwk raw 0x3e01 b00
- Read the region of interest
ectool --interface=fwk flashread 0x3c040 16 dump.bin
- Re-lock flash
ectool --interface=fwk raw 0x3e01 b03
- Print the contents of the dump to the screen
-
hexdump dump.bin
(orod -t x1 dump.bin
orxxd dump.bin
)
-
My answers:
00000000: 0610 2100 0000 0000 0000 0000 0000 0000 ..!.............
I think I booted my laptop for the first time on 2021-10-06.
That appears to be correct. Mine matches the delivery date of the package which would have been the first time that I booted the machine.
Same here; mine is the date of my first boot.
0000000 01 12 21 00 00 00 00 00 00 00 00 00 00 00 00 00
0000020
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.
Much appreciated!
EDIT: This is now published!
@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”.
I would power-use the ▒▒▒ out of this.
@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.