Updating Librem-EC on your Librem 14

Seems there is a new version.

Purism_Librem14-EC v1.12 (2023-02-20-64b01ec9)
2023-02-20

  • Set PL4 again when CPU resumes from a sleep state to address sudden shutoffs
1 Like

Just updated EC to version 12… hoping to address some of the strange charging behavior I’ve been dealing with. I’m still trying to figure out how to consistently reproduce this, but is anyone else out there have their Librem abruptly power off when you disconnect the barrel jack to the power supply? It seems like it happens to me when the battery power is high (above 90%).

1 Like

My Librem14 does not abruptly power off at any time, however i will test like disconnecting the barrel jack power supply above 90% just to checking…

1 Like

This has been happening to me as well. It usually happens after the laptop has entered and is exiting sleep mode, where it shouldn’t have lost much power at all.

I flashed this back in March 2024 but it’s still acting funky. The charge_max_design sysfs attribute is like 8 million units, while charge_full is dipping as low as 2 mil. As charge_now goes up, sometimes the charge_full does, too.

I learned this with a simple watch script:

watch -n 5 cat /sys/class/power_supply/BAT0/charge_now /sys/class/power_supply/BAT0/charge_full

At present, it sometimes stops charging at weird intervals; 40-something%, 60-something%, and expected behavior in the 90s (I put the threshold between 90% and 100%) But when I unplug it, both charge_now and charge_full go down, when it’s really only one of them that should be going down, unless I somehow have a rapidly deteriorating battery… That doesn’t make sense because I’ve only used the official barrel charger…

I’m going to try another EC flash today to see if maybe it just got into a loop of confused state. dmesg notes numerous unhandled ACPI 80 and 81 codes coming from battery, but all I could find on those events were on- and off-battery, and normal. Sorry to bump a dead thread but this seems to be an on-going problem.

I’m on Gentoo running kernel 6.6.21, but this happened on 5.10.212 as well. I have tried calibrating the battery by letting it die and leaving it on the charger overnight, to no success.

EDIT: Last night, capacity started going back up to around the 6700000 mark. I put it to sleep overnight, but when I woke it up, it turned off as if it were losing power, and did so again when I tried to boot it without plugging it in. When I plugged it in and booted, it showed 60% battery and has been charging rather normally since.

I’m using acpid and laptop-mode-tools, and have scripts mapped to only the lid and sleep button. Both end in the echo "mem" > /sys/power/state and, when on power, resume just fine.

1 Like

This has been perplexing me for quite a while, still struggling with battery oddities. I have re-flashed the EC using Purism’s official ISO for it, and verified purism_ectool could see it. My Gentoo system cannot appear to see the EC, even with librem_ec_acpi built and installed. It seems like it’s looking in the wrong place for something.

Seeing as this is Gentoo, I’m not afraid to get my hands dirty if I need to compile something, but every attempt thus far had led to the same results of an inconsistently reporting battery that factually has the 6-8 hours advertised, but has issues communicating charge to the OS.

I took it further this time… Charge started at 89%, and reported around 3.8M out of 4.2M. When it hit 50%, charge_now and charge_max dropped, to roughly 1.89M out of 2421000, which is barely over a quarter of the battery’s actual capacity! This continued until it reported 38%, when the 2421000 became 4843000 and the charge_now stayed around 1.89M . charge_now steadily went down at this point, until the 1000 mark. It reported 0% for over 3 hours of runtime after this point, left open and idling. I went to bed, and by the time I woke up, it was dead.

I charged and left it alone all day, then turned it on. The date was in 1970, so I set the hwclock, rebooted, things worked. Battery reported 54% and a charge_max currently at 4048000, which is roughly half what it should be and factually incorrect compared to the total runtime.

When I attempt to run purism_ectool info as root, I get this:

failed to connect to EC: Io(Os { code: 2, kind: NotFound, message: "No such file or directory" })

To reiterate, the EC is correctly installed and reports as such via the flashing ISO. I’ve built and installed the librem_ec_acpi module via dkms, and it must work to some degree because my thresholds show up, where they didn’t before.

Currently on kernel 6.6.47. Perhaps @nicole.faerber or another EC dev can help me isolate the cause here?

1 Like

@jonathon.hall

It’s been a while and I’m still experiencing strange battery level reporting, kernel 6.6.67. I attempted a newer kernel as well, 6.12.21, and it has issues in the acpi_driver struct’s “.owner” field, so I assume there’s been an API change between those versions. I’ll accept 6.6.67 being the latest supported (for now), no worries there.

The problem is purism_ectool still isn’t recognizing the EC, seemingly can’t see the device it’s looking for in tool/src/main.rs. I’ve tried both lpc-linux and hid methods to try to detect it. So I’m wondering now if I need a specific driver enabled in the kernel for the EC that I may have missed. I diffed against the kconfig I found via the PureOS kernel config package and it seemed like I had everything important there…

I don’t know where I should put my kernel config for people to look at, but I can provide it if necessary. I need to overcome this so Portage-based systems like Gentoo can support this laptop more easily.

So far, it’s not clear what the source of weird levels changing is, and without a way to check the EC and verify or test things, I’ve reached the edge of my knowledge.

The device in get_ec under the hid method is Vendor 3384, Device 0001. System76 Launch Configurable Keyboard (launch_1)

That’s a System76 keyboard device. Is the same in the Purism 14?

1 Like

Mostly:

1 Like

Indeed, that’s the repo I searched and pointed out the get_ec function in. Sorry that I forgot to link it.

I have more time to work on this today. I tried using a paste service and the kconfig is too big, so I uploaded it to my server directly:

https://zlg.space/misc/kconfig-librem14_2025-06-03.txt

I’ll be spending some time today reading kernel docs to make sure I didn’t mess something up somewhere, but I’ll share my process here while I’m at it: Here’s what I do to make a kernel for this laptop currently (TLDR version, full is below):

  • make menuconfig
  • make
  • make modules_prepare
  • cd to librem_ec dir
  • dkms build
  • dkms install
  • cd back to kernel dir
  • make modules_install
  • make install
  • generate initramfs with dracut
  • ???
  • Profit…?

Complete version:

#!/bin/bash
#
# make-kernel.sh
# by zlg <zlg@zlg.space>
#
# make a kernel for a Gentoo system, while also generating an initramfs that
# contains the contents of /lib/firmware and appropriate kernel modules.

JOBS="8"
TARGET_KVER="$(eselect --brief kernel show | cut -d'/' -f4)"
KVER="$(echo $TARGET_KVER | cut -d'-' -f2)"

set -e
set -x

clean_kernel_space() {
	cd /usr/src/linux
	make clean
}

prompt_menuconfig() {
	read -rp "Do you want make changes with menuconfig? [Y/n] " mc
	case "$mc" in
		y|Y)
			make menuconfig
			;;
		*)
			echo "Prepping existing config..."
			make oldconfig
			;;
	esac
}

build_kernel() {
	make -j${JOBS}
	make modules_prepare
}

install_librem_ec() {
	pushd /root/librem-ec-acpi-dkms
	make clean
	dkms build librem_ec_acpi/0.9.2 -k ${KVER}-gentoo-x86_64 --force
	dkms install librem_ec_acpi/0.9.2 -k ${KVER}-gentoo-x86_64 --force
	popd
}

install_kernel_and_modules() {
	make modules_install
	make install
}

install_initramfs() {
	dracut /boot/initramfs-${KVER}-gentoo-x86_64.img --kver=${KVER}-gentoo-x86_64 --force --include /lib/firmware/ /lib/firmware/
}

main() {
	if [ -z $1 ] || [ $1 -ne "continue" ]; then
		clean_kernel_space
		prompt_menuconfig
	fi
	build_kernel
	install_librem_ec
	install_kernel_and_modules
	install_initramfs
	echo "Finished! Yay!"
}

main "$@"
1 Like

You may or may not want to add checks for required tools and/or before cleaning up the kernel space:

check_tools() {
    for tool in eselect dkms dracut make; do
        if ! command -v $tool &> /dev/null; then
            echo "Error: $tool is not installed."
            exit 1
        fi
    done
}

clean_kernel_space() {
    cd /usr/src/linux
    read -rp "Are you sure you want to clean the kernel space? [Y/n] " confirm
    case "$confirm" in
        y|Y)
            make clean
            ;;
        *)
            echo "Skipping clean."
            ;;
    esac
}
1 Like

Yeah, the script itself is still a work in progress. It’s not my best work, aiming for MVP first right now and we’ll refine it later. I’m focused mostly on getting the order of building operations correct, then I can refactor and add the smart guardrails. Those are great suggestions, though, and do belong in whatever this thing becomes. Thanks for pointing it out!

1 Like