Safeguard
Supply Chain Security•

BMS Firmware Explained: Cell Balancing, Fuel Gauges, SMBus, Updates

A BMS measures every cell, cuts power when limits are crossed, balances cells and estimates charge. Here is how its firmware works and is updated safely.

Safeguard Security Team
42 min read

A battery management system (BMS) is the electronics and firmware that keep a lithium ion pack inside its safe limits. It measures every cell's voltage, the pack current and several temperatures, opens protection MOSFETs when a limit is crossed, balances cells so they stay matched, and estimates state of charge and state of health for the device it powers.

The firmware lives in up to four places: a fuel gauge chip with its own configuration flash, an optional pack microcontroller, the host's embedded controller, and the operating system driver that turns register reads into a battery percentage. This post covers each layer, the arithmetic a fuel gauge runs, balancing thresholds, the Smart Battery Data Specification over SMBus, the Linux power supply class, secure updates, the EU Batteries Regulation and UN 38.3, and a hands-on routine for reading your own battery.

For how cells are made, read how lithium ion batteries are made. For the laptop chip that talks to the battery, read embedded controller firmware explained. For a pack in a vehicle, read how an e-bike is made. For why heat ages a cell, read the Arrhenius equation explained.

Key takeaways

  • A BMS measures, protects, balances, estimates and reports. Protection must never fail; the rest can degrade gracefully.
  • The hardware is an analog front end that measures cells, a current sense resistor, thermistors, back to back protection MOSFETs, a fuel gauge, and in larger packs a microcontroller.
  • Fuel gauges combine coulomb counting (integrating current) with open circuit voltage lookups and, in more capable parts, impedance tracking. They drift because of current offset, temperature, ageing and long stretches without a rest or a full charge.
  • Passive balancing burns charge from the highest cells through resistors; active balancing moves charge between cells. Most consumer packs use passive balancing with thresholds in the tens of millivolts.
  • Laptop packs commonly speak the Smart Battery Data Specification 1.1 (dated 11 December 1998) over SMBus. CycleCount() is command 0x17 and counts discharge roughly equal to DesignCapacity().
  • Linux reports batteries through the power supply class under /sys/class/power_supply, in microvolts, microamps, microamp hours, microwatt hours and tenths of a degree Celsius.
  • BMS firmware updates need the same controls as any platform firmware: signed images, rollback protection, a recovery path, and protection limits that an update cannot widen without a second check.
  • The EU Batteries Regulation (EU) 2023/1542 adds state of health data access and a digital battery passport for larger batteries. UN 38.3 testing is the gate for shipping lithium cells and packs.

A dated timeline of the specifications and rules behind BMS firmware

DateEventWhy it matters for BMS firmwareSource
11 Dec 1998Smart Battery Data Specification Revision 1.1Defines the command set (voltage, current, capacity, cycle count, alarms) most laptop packs still exposeSBS Implementers Forum
10 Dec 1999SMBus Control Method Interface Specification 1.0Lets ACPI firmware reach an SMBus segment in a hardware independent waySMBus specifications page
3 Aug 2000SMBus Specification 2.0 postedThe long lived baseline many battery and charger parts were designed againstSMBus specifications page
Apr 2011NIST SP 800-147, BIOS Protection GuidelinesSets out authenticated update as the core control against unauthorized firmware modificationNIST
16 Jan 2015SMBus Specification 3.0 postedAdds higher bus speeds and updated electrical rulesSMBus specifications page
May 2018NIST SP 800-193, Platform Firmware Resiliency GuidelinesProtect, detect and recover principles that apply to any firmware that can brick a deviceNIST
May 2020NIST IR 8259A, IoT device cybersecurity capability core baselineLists software update as a baseline device capabilityNIST
12 Jul 2023Regulation (EU) 2023/1542 on batteries adopted; in force 17 Aug 2023, applies from 18 Feb 2024Safety, labelling, state of health data and battery passport rulesRegulation text; European Commission
18 Aug 2024Article 14 of the regulation appliesState of health and lifetime data must sit in the BMS of LMT, EV and stationary storage batteriesRegulation (EU) 2023/1542
20 Oct 2024SMBus Specification 3.3.1Current release at the time of writing (3.3 was 12 May 2024)SMBus specifications page
10 Dec 2024EU Cyber Resilience Act enters into forceProducts with digital elements, which can include connected battery systems, get security duties; main obligations apply from 11 Dec 2027European Commission
18 Feb 2027Battery passport (Article 77) and portable battery replaceability (Article 11) applyPassport for EV, LMT and industrial batteries above 2 kWh; users must be able to replace portable batteriesRegulation (EU) 2023/1542

What does a battery management system do?

A battery management system watches a lithium ion pack and acts on what it sees. Lithium ion cells are safe and long lived inside a narrow window of voltage, current and temperature, and unforgiving outside it. The BMS exists to keep every cell inside that window and to tell the rest of the system how much energy is left.

Measure

The BMS measures each series cell group's voltage, the pack current and a few temperatures. Voltage is per cell group because a pack average hides the one cell about to be overcharged. Current comes from a sense resistor of a few milliohms; temperature from thermistors on the cells and MOSFETs.

Protect

Protection is the job that must never fail. The BMS compares every measurement with limits and opens the charge path, the discharge path or both when a limit is crossed. The classic set is cell overvoltage, cell undervoltage, overcurrent in charge, overcurrent in discharge, short circuit in discharge, and over or under temperature in charge and in discharge. Charging below freezing is a specific danger because lithium can plate on the anode, so most packs refuse to charge in the cold even though they will still discharge.

The following values are illustrative of a common nickel manganese cobalt (NMC) cell family. Real limits come from the cell maker's datasheet, and a pack designer narrows them further.

ProtectionIllustrative threshold (NMC cell)Typical delay before actingTypical response
Cell overvoltage4.25 V to 4.30 V per cellabout 1 sOpen charge FET
Cell undervoltage2.50 V to 3.00 V per cellabout 1 sOpen discharge FET
Overcurrent in dischargePack rating plus marginmilliseconds to secondsOpen discharge FET
Short circuit in dischargeSeveral times pack ratingmicrosecondsOpen discharge FET in hardware
Overtemperature in chargeabout 45 °C to 50 °CsecondsOpen charge FET
Undertemperature in chargeabout 0 °CsecondsOpen charge FET
Overtemperature in dischargeabout 60 °C to 70 °CsecondsOpen discharge FET
Secondary overvoltageHigher than the primary limitsecondsBlow a fuse, permanent

The last row matters. Good packs have two independent layers: a primary BMS with firmware configured, recoverable limits, and a fixed function secondary protector that blows a fuse at a higher limit if the primary fails. A pack that has been overcharged should be permanently dead.

Balance

Cells differ slightly in capacity and self discharge, the differences grow with cycling, and in a series string the weakest cell limits the pack. Balancing pulls cells back to the same state of charge.

Estimate

The BMS estimates state of charge (SoC), the percentage of the currently available capacity that remains, and state of health (SoH), how much of the original capacity or power capability the pack still has. Neither can be measured directly. Both are estimates, and later sections show why they drift.

Report

Finally the BMS reports, over SMBus in a laptop, I2C or a single wire link in a phone, UART or CAN in an e-bike, and the vehicle network in an EV. The charger uses the report to decide how hard to push.

What hardware is inside a BMS, and where does the firmware sit?

A BMS is a small set of parts with firmware spread across several of them.

PartWhat it doesFirmware or configuration it holds
Analog front end (AFE)Measures each cell voltage through a multiplexer and ADC, drives balancing switches, often drives the protection MOSFETs and detects short circuit in hardwareRegister configuration, sometimes one time programmable thresholds
Current sense resistorConverts pack current to a small voltage for the coulomb counterNone
ThermistorsReport temperatures at cells and FETsNone
Protection MOSFETsTwo FETs back to back so charge and discharge can be blocked independentlyNone
Fuel gauge ICIntegrates current, models the cell, computes SoC, SoH and time to empty, answers the hostROM algorithm plus a data flash of chemistry tables, limits and learned values
Pack microcontrollerRuns the BMS state machine in bigger packs, coordinates multiple AFEs, talks CAN or UARTFull application firmware and a bootloader
Secondary protector and fuseIndependent overvoltage protection, blows a chemical or thermal fuseFixed thresholds, no update path
Host embedded controller or PMICReads the pack, controls the charger, presents the battery to the operating systemEC or PMIC firmware

A single cell phone battery often has no microcontroller: fixed function protection and gauge chips are set by factory configuration data. A laptop pack has a gauge configured through a data flash image. E-bike, storage and vehicle packs daisy chain several AFEs under a microcontroller running substantial firmware. So "BMS firmware" can mean a few kilobytes of gauge configuration, a microcontroller application, a host EC image, or all three, each with its own update path and ways to fail.

The data path runs from cell to screen: the AFE samples cells, the gauge applies protection limits and updates its model, the host controller reads registers, ACPI or a kernel driver turns them into a battery device, and a desktop daemon shows a percentage. A fault anywhere shows up as a wrong number on screen. Only a fault in the measuring and protecting layers can start a fire.

How do fuel gauges estimate state of charge?

A fuel gauge estimates state of charge by combining two imperfect signals. Coulomb counting integrates current over time and is accurate in the short term but drifts. Open circuit voltage is anchored to chemistry but only readable at rest. Better gauges add an impedance model of usable capacity at the present load and temperature.

Coulomb counting

The gauge measures the voltage across the sense resistor, converts it to current, and adds up charge in small time steps:

Q(t) = Q(0) − ∫ I dt

with discharge current positive. State of charge is then the remaining charge divided by full charge capacity.

Worked example 1: coulomb counting a laptop discharge. A pack has a learned full charge capacity of 5,000 mAh and starts at 100 percent. It discharges at an average 1.2 A for 90 minutes.

  • Charge removed: 1.2 A × 1.5 h = 1.8 Ah = 1,800 mAh
  • Remaining: 5,000 − 1,800 = 3,200 mAh
  • Relative state of charge: 3,200 ÷ 5,000 = 64 percent

If the same pack has aged so that the gauge has learned a full charge capacity of 4,000 mAh, the same 90 minutes leaves 2,200 mAh, or 55 percent. The percentage you see is always relative to the latest learned capacity, which is why an old laptop's battery bar moves faster.

Why coulomb counting drifts

The integral is only as good as the current measurement, and a small constant error accumulates for as long as the pack is in use or sitting idle.

Worked example 2: offset drift. Suppose the current measurement has an uncorrected offset of 1 mA, a plausible figure for a cheap design. Over a 30 day period on a shelf or in sleep:

  • Accumulated error: 1 mA × 24 h × 30 = 720 mAh
  • On a 5,000 mAh pack, that is 720 ÷ 5,000 = 14.4 percentage points

Better gauges calibrate the offset, ignore currents inside a small dead band, and model self discharge, which the counter cannot see. Sense resistor gain error, temperature and ageing add more drift. The Smart Battery Data Specification gives a gauge a way to admit this: MaxError() (command 0x0C) returns the expected error in percent, and the specification says it should grow until the battery sees a condition that raises its confidence, such as a full charge from a fully discharged state.

Open circuit voltage tables

After a cell has rested long enough for its voltage to relax, the open circuit voltage maps to state of charge through a curve that depends on chemistry. The gauge stores that curve as a table and re anchors its count after a long enough rest, often tens of minutes or more.

Worked example 3: why chemistry changes the error. Take an illustrative measurement error of 5 mV.

  • On an NMC cell in its mid range, the curve might slope about 8 mV per percent of state of charge. A 5 mV error is about 0.6 percentage points.
  • On a lithium iron phosphate (LFP) cell's flat plateau the slope might be closer to 1 mV per percent. The same 5 mV error is about 5 percentage points.

The slopes are illustrative, but the lesson holds: LFP gauges lean on coulomb counting and the occasional full charge.

Impedance tracking and model based gauges

Voltage under load is lower than open circuit voltage by roughly the current times the cell's internal resistance. Resistance rises with age and in the cold. A gauge that tracks resistance predicts when loaded voltage will hit the device's cut off, which is the capacity a user can actually get. It learns maximum chemical capacity from pairs of rested readings with known charge between them, and resistance from voltage drops under load.

Why gauges still get it wrong

  • No learning events. A laptop that lives on a dock between 40 and 80 percent never gives the gauge a full charge or a deep rest, so learned values go stale.
  • Wrong chemistry table. A replacement pack configured with a table for a different cell will be confidently wrong.
  • Cold. Usable capacity at minus 10 °C can be much lower than at 25 °C, and the gauge has to model it.
  • Imbalance. If one cell reaches the cut off first, the pack is empty while the average still says otherwise.

The fix is occasional calibration: full charge, rest, steady discharge to shutdown, rest. Follow the device maker's routine where one exists.

What are passive and active balancing, and what do the firmware thresholds look like?

Balancing equalises state of charge across series cells. Passive balancing bleeds charge from cells that are ahead through resistors. Active balancing moves charge from cells that are ahead to cells that are behind, using capacitors, inductors or small transformers.

Passive balancing

Each cell has a resistor and a switch across it, usually inside or beside the AFE. When firmware decides a cell is ahead, it closes the switch and the cell discharges into the resistor as heat. It is simple, cheap and reliable. Its limits are wasted energy, heat inside the pack, and small currents, usually tens of milliamps, so it fixes small daily drifts rather than a badly mismatched pack.

Worked example 4: how long passive balancing takes and how much heat it makes. A cell is 100 mAh ahead of its neighbours. The bleed resistor is 68 ohms and the cell sits at 4.1 V.

  • Bleed current: 4.1 V ÷ 68 Ω ≈ 60 mA
  • Time to remove 100 mAh: 100 ÷ 60 ≈ 1.7 hours
  • Heat: V² ÷ R = 4.1² ÷ 68 ≈ 0.25 W per balancing cell

Balancing three cells at once adds about 0.75 W of heat inside a sealed pack, which is why firmware often balances alternate cells, limits how many cells balance together, or pauses balancing when the pack is warm.

Active balancing

Active balancing transfers energy instead of burning it, through switched capacitors between neighbouring cells, inductors, or transformers between a cell and the pack. It is faster and more efficient but costs more and has more parts that can fail.

FactorPassive balancingActive balancing
How it worksBleed resistor across each cellCapacitor, inductor or transformer moves charge
Typical balancing currentTens of milliamps up to a few hundredHundreds of milliamps to several amps
EnergyWasted as heatMostly conserved
Complexity and costLowHigher
Where it fitsPhones, laptops, most e-bike and power tool packsLarge stationary storage, some EV and high cycle packs, second life packs with mismatched cells
Firmware loadThresholds and timersControl loops, current limits, fault detection for the converter

What balancing firmware decides

Firmware decides when to balance and when to stop. These values are illustrative, not recommendations for any cell.

# Illustrative BMS balancing configuration (not for a real product)
balancing:
  mode: passive
  start_delta_mv: 20         # begin when a cell is 20 mV above the lowest cell
  stop_delta_mv: 5           # stop when within 5 mV
  min_cell_voltage_mv: 3900  # only balance near the top of charge
  allow_during: [charge, rest]
  max_simultaneous_cells: 2  # limit heat, and avoid adjacent cells on some AFEs
  max_pack_temp_c: 45        # pause if the pack is warm
  timeout_minutes: 240       # give up and flag a fault if it never converges
  fault_delta_mv: 150        # imbalance this large is a pack fault, not a balancing job
  • Balancing near the top. On an NMC curve the voltage difference between cells is easiest to read near full charge, so many packs balance during the constant voltage phase or after charge.
  • A fault threshold. A difference of more than a hundred millivolts or so usually points to a failing cell, a bad connection or a sensing fault. Balancing should not hide it; the BMS should report it.
  • A timeout. A cell that never converges is a cell with high self discharge, and repeated balancing just drains its neighbours to match it.

How do laptops and packs talk to the host?

Most laptop packs talk to the host over the System Management Bus (SMBus) using the Smart Battery Data Specification (SBS), and the host presents the result to the operating system through ACPI.

SMBus

SMBus is a two wire bus, clock and data, derived from I2C with tighter timing and electrical rules and an optional packet error check byte. The System Management Interface Forum lists version 3.3.1 (20 October 2024) as current, and describes version 1.0's purpose as a 2 wire interface through which the battery can communicate with the charger, a system host or other power related components.

The Smart Battery Data Specification

SBS 1.1 defines a pack as an SMBus device that answers numbered commands. A host reads a word from a command code and gets a value with defined units. The table lists commands you will meet most often.

CommandCodeWhat it returnsUnits
ManufacturerAccess()0x00Manufacturer specific; no functional requirement in the specificationVendor defined
BatteryMode()0x03Capability and mode flags, including whether capacity is reported in mAh or 10 mWhBit flags
Temperature()0x08Pack temperature0.1 K
Voltage()0x09Pack voltagemV
Current()0x0AInstantaneous current, positive when chargingmA
MaxError()0x0CExpected error in the state of charge estimatepercent
RelativeStateOfCharge()0x0DRemaining capacity as a percent of FullChargeCapacity()percent
RemainingCapacity()0x0FPredicted remaining capacitymAh or 10 mWh
FullChargeCapacity()0x10Predicted capacity when fully chargedmAh or 10 mWh
ChargingCurrent()0x14Current the pack asks the charger formA
ChargingVoltage()0x15Voltage the pack asks the charger formV
BatteryStatus()0x16Alarm and status flags such as over temperature and terminate dischargeBit flags
CycleCount()0x17Cycles experiencedcycles
DesignCapacity()0x18Capacity of a new packmAh or 10 mWh
DeviceChemistry()0x22Chemistry stringText

Two definitions are worth reading closely. CycleCount() counts "an amount of discharge approximately equal to the value of DesignCapacity", so two half discharges make one cycle, and the specification notes that cycle count times design capacity gives an approximate odometer of total charge delivered. Temperature() is in tenths of a kelvin, so a raw value of 2,982 is 298.2 K, or 25.05 °C.

The smart part of a Smart Battery is that the pack, not the host, decides how it wants to be charged. It sends ChargingCurrent() and ChargingVoltage() to a Smart Battery Charger and raises AlarmWarning() messages when a limit is near. So the pack's configuration data directly controls how hard the charger pushes.

ManufacturerAccess and the parts the specification leaves open

Command 0x00, plus extended commands above the standard set, is where gauge makers put sealing and unsealing, detailed status, firmware update entry and authentication. Those extensions live in each gauge maker's reference manual, not in SBS, so the security of configuration access depends on the gauge, the pack maker's access keys and whether the pack left the factory sealed.

ACPI and the embedded controller

On a typical x86 laptop the operating system does not talk SMBus to the battery itself. The embedded controller reads the pack and the platform firmware exposes ACPI control methods. The Linux ACPI battery driver evaluates _BIF or its extended form _BIX for static information such as design capacity and cycle count, _BST for live status, and _BTP to set a trip point that triggers a notification. A wrong value on screen can therefore come from the gauge, the EC firmware's translation or the ACPI tables, and the fix may be an EC or BIOS update rather than a new battery.

How Linux exposes batteries: the power supply class

Linux represents batteries, adapters and UPS units through the power supply class, a core attribute set "applicable to (almost) every power supply" exposed via sysfs and uevent. Units are fixed: µV, µA, µAh, µWh, seconds and tenths of a degree Celsius. The documentation warns not to mix CHARGE_* (µAh) with ENERGY_* (µWh); CAPACITY is a percentage.

sysfs attributeMeaningSBS source on an SBS driver
statusCharging, Discharging, Full, Not chargingBatteryStatus()
capacityState of charge in percentRelativeStateOfCharge()
current_nowCurrent in µACurrent()
charge_full or energy_fullLast learned full capacityFullChargeCapacity()
charge_full_design or energy_full_designDesign capacityDesignCapacity()
cycle_countCycles; 0 means not availableCycleCount()
tempTemperature in 0.1 °CTemperature() converted from 0.1 K
authentic1 if the platform judged the supply authentic, 0 if notDriver specific
charge_control_end_thresholdStop charging at this percent, where supportedPlatform specific

The kernel's sbs-battery driver shows the mapping directly: its register table maps command 0x0D to the capacity property, 0x10 to full charge, 0x17 to cycle count and 0x18 to design capacity, among others. I2C phone class gauges have their own drivers, such as bq27xxx.

The sysfs ABI documentation adds two attributes that matter for longevity. charge_control_end_threshold sets the percentage at which charging stops on hardware that supports it, and charge_behaviour accepts values such as auto, inhibit-charge and force-discharge where the platform allows it.

How is BMS firmware updated and authenticated?

BMS firmware is updated through whichever layer holds it, and each layer needs authentication, a rollback rule and a recovery path. The risks are concrete: a bricked pack, a protection limit set wider than the cells can tolerate, or a counterfeit pack accepted as genuine.

The update paths

LayerHow it is typically updatedWho signs or controls it
Fuel gauge data flashFactory programming; occasionally a field update from the device maker's toolPack or device maker, behind gauge access keys
Fuel gauge ROM algorithmNot updatable; fixed in siliconChip maker
Pack microcontrollerBootloader over SMBus, I2C, UART or CAN; dealer or service tool; companion appPack or vehicle maker, with signed images where implemented
Host embedded controllerBIOS or UEFI capsule update, vendor update tool, or the Linux Vendor Firmware ServiceDevice maker
Vehicle BMSWorkshop tool or over the air updateVehicle maker under its software update process

On Linux, the Linux Vendor Firmware Service (LVFS) describes itself as a secure web service that OEMs use to upload firmware archives and that users use to securely download update metadata and, optionally, the updates. The fwupd daemon applies them. Whether your laptop's EC or battery is covered depends on whether the maker publishes it there.

What secure updating looks like

NIST SP 800-147 was written for PC BIOS, but its core rule maps directly onto BMS firmware: only authenticated updates, verified with a digital signature against a key the device trusts, should be able to change the firmware. NIST SP 800-193 extends that into three principles: protect the firmware and its critical data from unauthorized change, detect when a change has happened, and recover to a known good state. Its abstract warns that an attack could render a system inoperable, perhaps permanently, which describes a pack that will not charge. NIST IR 8259A (May 2020) lists software update in its IoT device baseline, relevant to app updated e-bike and home storage packs.

Put together, a defensible BMS update design has these properties:

  1. Signed images. The bootloader verifies a signature over the full image before switching to it. A checksum alone only catches corruption.
  2. Rollback protection. A monotonic counter or version floor stops an older image with a known flaw from being reinstalled.
  3. Dual banks or a protected recovery image. An update interrupted by a power loss falls back to the previous image instead of bricking the pack.
  4. Protection limits outside the update's reach. The secondary protector's fixed thresholds and fuse still work whatever the firmware does. Where primary limits live in data flash, the update tool should check them against a cell specific allowed range before writing.
  5. Sealed configuration. Gauges ship sealed so that configuration and calibration cannot be rewritten over the bus without a key. Default or shared keys undo this.
  6. Update preconditions. The pack should be at a safe temperature, above a minimum state of charge, not charging at high current, and on external power where the host needs it.

Failure modes that matter

  • Bricked packs. Many gauges have a permanent failure state that latches after a serious fault, such as a blown fuse or a cell imbalance beyond limit. A bad update or configuration can trigger it. Recovery usually needs the maker's service tooling or a new pack.
  • Unsafe thresholds. An image that raises the overvoltage limit or the charge temperature window can make a pack charge outside its cell's safe range. The secondary protector is the backstop, which is why it must not be configurable from the same path.
  • Supply chain substitution. A pack built with untested cells but configured to report the expected identity defeats both safety and authentication.

Pack authentication against counterfeits

Device makers authenticate packs to protect users from counterfeit cells without proper protection and to enforce charging profiles tuned to known cells. The common category is a challenge response: the host sends a random challenge, the pack's gauge computes a keyed hash or a signature using a secret stored inside it, and the host checks the answer. Per pack asymmetric keys beat a shared secret, because one extracted key does not unlock every pack.

Linux has a place for the result: the power supply class AUTHENTIC attribute reports whether the connected battery or charger is authentic (1) or not (0). Devices then warn, limit charge current or refuse to charge. Done well, authentication protects users without locking out a properly made replacement.

What does the EU Batteries Regulation require, and what is UN 38.3?

Regulation (EU) 2023/1542 covers sustainability, safety, labelling, due diligence and end of life; its state of health data and passport rules reach into BMS firmware. UN 38.3 is separate: transport tests lithium cells and batteries must pass before shipping.

State of health data and the BMS (Article 14)

Article 14 applies from 18 August 2024. It requires that up to date data for the state of health and expected lifetime parameters in Annex VII be held in the BMS of stationary battery energy storage systems, light means of transport (LMT) batteries and electric vehicle batteries. Read only access to that data through the BMS must be given, on a non discriminatory basis, to whoever legally bought the battery and to third parties acting for them, so that the battery can be offered to independent aggregators, its residual value assessed, or it can be prepared for reuse, repurposing or remanufacturing.

Annex VII names the parameters. For electric vehicle batteries it is the state of certified energy. For stationary storage and LMT batteries the state of health parameters are remaining capacity and, where possible, remaining power capability, round trip efficiency and ohmic resistance, plus the evolution of self discharge rates. The expected lifetime parameters include date of manufacture, energy and capacity throughput, the number of full equivalent cycles, and tracking of harmful events such as deep discharges and time spent charging at extreme temperatures.

Two consequences for firmware stand out. First, the gauge's internal estimates and event counters become data the owner has a right to read, so a design where only the maker's service tool can see health no longer fits. Second, Article 14(3) requires a software reset function so that operators preparing a battery for reuse or repurposing can load different BMS software. That is a regulated update path, and it needs the same signing, rollback and limit checks as any other. A reset function that accepts any image would let a careless or malicious refurbisher widen protection limits.

The battery passport (Article 77)

From 18 February 2027, each LMT battery, each industrial battery above 2 kWh and each electric vehicle battery placed on the market needs an electronic record, the battery passport. It holds information on the battery model and information specific to the individual battery, including information resulting from its use, with some fields public and others restricted to notified bodies, market surveillance authorities and the Commission. The health data in it comes from the BMS, so its accuracy and resistance to tampering now feed resale and repurposing decisions.

Replaceability of portable batteries (Article 11)

From 18 February 2027, Article 11 requires that portable batteries in products be readily removable and replaceable by the end user during the product's lifetime, with derogations set out in Article 11(2) and Commission guidelines on how to apply them. That interacts with pack authentication: a device that refuses every replacement pack works against the intent of the rule.

UN 38.3

UN 38.3 is sub-section 38.3 of Part III of the UN Manual of Tests and Criteria. In the United States, 49 CFR 173.185 requires each lithium cell or battery to be of a type proven to meet its criteria, regardless of whether the cells inside were already tested. The IATA lithium battery guidance for 2026 adds that makers and distributors of cells and batteries manufactured after 30 June 2003 must make a test summary available, as specified in paragraph 38.3.5, listing the tests conducted and their results. The series is numbered T.1 onwards and subjects a design to environmental, mechanical and electrical stress, including shock (the guidance discusses the T.4 test). Electrical abuse cases exercise the BMS directly, so a firmware change that alters protection behaviour can raise the question of whether an existing test summary still describes the shipped design. Ask that before changing limits in the field.

Phone, laptop, e-bike and EV battery management compared

FactorPhoneLaptopE-bikeElectric vehicle
Typical series cell count1S, sometimes 2S for fast charging2S to 4S10S (36 V) to 13S (48 V), 14S for some 52 V packsabout 96S for 400 V class, about 192S for 800 V class
Host interfaceI2C or single wire to the PMICSMBus with SBS, through the EC and ACPIUART, CAN or proprietary, plus Bluetooth to an appCAN or CAN FD, increasingly automotive Ethernet; isolated daisy chain between AFEs
BalancingNot needed for 1SPassivePassive, sometimes activePassive or active, model based
Update pathOperating system updateBIOS or EC update, LVFS on Linux where publishedDealer tool or companion appWorkshop or over the air under the maker's update process
Health shown to userOS battery screen; Android's BatteryManager exposes health states and EXTRA_CYCLE_COUNTsysfs, UPower, vendor toolsApp, displayVehicle display, dealer report, passport data in the EU from 2027
Safety standard familyIEC 62133-2 for portable lithium cells and batteriesIEC 62133-2Light electric vehicle battery standards, IEC 62133-2 for cellsVehicle battery safety regulations and functional safety standards
EU Batteries Regulation categoryPortablePortableLMT batteryEV battery

The cell counts follow from nominal voltages near 3.6 V to 3.7 V per NMC cell: 10 × 3.6 V = 36 V, 13 × 3.7 V ≈ 48 V, 96 × 3.7 V ≈ 355 V. Treat them as typical, not fixed.

Step by step: read your battery's data on Linux and check firmware updates

These commands only read data except where a step says otherwise. None of them erase or rewrite firmware.

1. Find your battery devices

ls /sys/class/power_supply/
# Typical output: AC  BAT0

Laptops usually show BAT0 and AC or ADP1.

2. Dump everything the kernel knows

cat /sys/class/power_supply/BAT0/uevent

This prints every property as POWER_SUPPLY_*=value. Look for TECHNOLOGY, CYCLE_COUNT, CHARGE_FULL_DESIGN or ENERGY_FULL_DESIGN, CHARGE_FULL or ENERGY_FULL, MANUFACTURER, MODEL_NAME and SERIAL_NUMBER.

3. Compute state of health from design and full charge capacity

cd /sys/class/power_supply/BAT0
if [ -r energy_full ]; then
  full=$(cat energy_full); design=$(cat energy_full_design); unit="µWh"
else
  full=$(cat charge_full); design=$(cat charge_full_design); unit="µAh"
fi
echo "full=$full design=$design ($unit)"
awk -v f="$full" -v d="$design" 'BEGIN { printf "Health: %.1f%%\n", 100*f/d }'
echo "Cycles: $(cat cycle_count 2>/dev/null || echo n/a)"

Worked example 5: interpreting the result. Suppose the output shows energy_full=41230000 and energy_full_design=56000000, with 612 cycles.

  • Health: 41,230,000 ÷ 56,000,000 ≈ 73.6 percent
  • Delivered energy odometer, using the SBS idea of cycles times design capacity: 612 × 56 Wh ≈ 34,272 Wh, about 34 kWh delivered over the pack's life

Health in the 70s after several hundred cycles is ordinary wear. The same figure after fewer than 50 cycles suggests a pack kept hot or full, a gauge that has not learned recently, or a pack that is not what it claims. A reported cycle count of 0 means not available, according to the sysfs ABI documentation, not a new pack.

4. Read the same data through UPower

upower -e
upower -i /org/freedesktop/UPower/devices/battery_BAT0

The UPower command line tool's --enumerate lists device object paths and --show-info shows one. Its output includes energy-full, energy-full-design, capacity (a health percentage; the UPower docs call below 75 percent usually a sign to renew) and charge-cycles (-1 if unknown).

5. Set a charge limit, if your hardware supports it

This step writes a setting. It does not touch firmware.

cat /sys/class/power_supply/BAT0/charge_control_end_threshold 2>/dev/null \
  || echo "Not supported on this machine"
echo 80 | sudo tee /sys/class/power_supply/BAT0/charge_control_end_threshold

Many platforms reset it on reboot.

6. Check firmware update channels for the EC and battery

fwupdmgr get-devices
fwupdmgr refresh
fwupdmgr get-updates

get-devices lists what fwupd can see, including the system firmware and, on some models, the embedded controller or battery. get-updates shows what LVFS offers for them. If your battery or EC is not listed, updates come from the maker's own tool or a BIOS package.

7. Before applying any EC, BIOS or battery firmware update

Firmware updates can leave a device unbootable or a pack unable to charge if interrupted. Before you install:

# Confirm you are updating the device you think you are
fwupdmgr get-devices | grep -A6 -i -E "battery|embedded controller|system firmware"
cat /sys/class/power_supply/AC/online   # 1 means on mains power
cat /sys/class/power_supply/BAT0/capacity

Confirm the device name, current version and target version match the maker's release notes, the adapter is connected (online is 1), and the battery is above the maker's minimum, often 25 to 50 percent. Do not interrupt the update or close the lid. If anything does not match, stop.

fwupdmgr update

Common mistakes

  • Reading capacity as health. In sysfs, capacity is state of charge. Health is full charge capacity divided by design capacity.
  • Mixing charge and energy. charge_* is µAh and energy_* is µWh. Dividing one by the other gives nonsense.
  • Trusting a gauge that never learns. A machine that lives on a dock needs an occasional full cycle for the gauge to update.
  • Balancing as a fix for a bad cell. Large or growing imbalance is a pack fault. Raising balancing current or time hides it.
  • Widening protection limits in firmware to get more runtime. The extra capacity above the datasheet maximum voltage costs cycle life and safety margin.
  • Shipping gauges unsealed or with a default access key. Anyone with bus access can rewrite calibration and limits.
  • Blaming the pack for a wrong number. EC or BIOS updates can fix reporting faults.

FAQ

What does a BMS do in a lithium ion battery?

It measures cells, current and temperature, disconnects the pack when a limit is crossed, balances cells, estimates charge and health, and reports to the device and charger.

How accurate is a battery percentage?

It depends on the gauge and on how recently it learned. The SBS MaxError() command exists to report the uncertainty, and a gauge's error grows between full charges and rests. A few percentage points is typical for a well configured gauge; a gauge that has not learned for months can be off by much more.

What is the difference between state of charge and state of health?

State of charge is how full the battery is now, as a percentage of its present full capacity. State of health is how much of its original capacity or power capability it still has, often full charge capacity divided by design capacity.

What is a battery cycle count?

The Smart Battery Data Specification defines a cycle as an amount of discharge approximately equal to design capacity. Two discharges from 100 to 50 percent count as one cycle.

Why does my laptop battery percentage jump suddenly?

The gauge corrected itself after a rest showed its coulomb count was wrong, or the voltage hit cut off earlier than its model expected. A full calibration cycle usually helps.

Is passive or active cell balancing better?

Neither is better everywhere. Passive suits well matched packs with small drift; active suits large, high cycle or mismatched packs.

How do I check battery health on Linux?

Read /sys/class/power_supply/BAT0/energy_full and energy_full_design (or the charge_ equivalents), divide the first by the second, and read cycle_count. upower -i with the battery's object path shows the same data.

Can battery firmware be updated?

Partly. Pack microcontrollers and host embedded controllers usually can, through the maker's tool, a BIOS update or LVFS. A gauge's ROM algorithm cannot.

What does the EU battery passport contain?

An electronic record, reachable by QR code, with information about the battery model and the individual battery, including state of health data. It applies from 18 February 2027 to LMT batteries, industrial batteries above 2 kWh and electric vehicle batteries.

Where Safeguard fits, honestly

Safeguard does not analyse battery hardware, read BMS data, scan firmware images or test protection limits. Nothing in this post about cells, gauges or balancing is something Safeguard does.

The fit is with the software around a battery programme. Pack and device makers build update servers, companion apps for e-bikes and home storage, fleet health dashboards, battery passport data services and factory test tooling. Those are ordinary repositories and container images built on open source. Safeguard scans them (safeguard scan --dir ., --image <name>, or --sbom <file> for an SBOM a supplier provides), matches components against vulnerability databases, ranks findings with reachability analysis, shows which projects contain a given component and version, and evaluates policies and gates. Autonomous remediation can open fix pull requests and ships switched off. Fixes inside the pack's firmware still come from the pack or device maker.

A battery programme rebuilds its update service, companion app and passport data pipeline with every release, and each rebuild pulls open source dependencies again. The BMS firmware and the host's embedded controller can also carry open source components such as bootloaders, RTOS kernels and cryptographic libraries, but those are fixed by the maker, so the steps below apply to the software your team builds and ships around the battery.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.

3. Gold Registry: start from components that are already fixed

Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingSafeguard policies and gates in CI
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The first demo is a real Safeguard CLI session asked to fix a lodash CVE: it reads the finding and advisory, asks before any command that changes something, edits package.json to lodash 4.17.21, runs npm install and npm test with approval, and pushes nothing. The same flow fits the web dashboard of an e-bike or home storage companion app, or the service that publishes battery passport data.

Click through it at your own pace, or open it full screen.

The second demo sets up the Safeguard runner on your own machine, approves it with its device code and scans from the terminal. That suits a firmware or test tooling team that builds its update server and factory tools on its own hosts and wants scans to run beside that build.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and shows how you choose which tools Claude can use. An engineer reviewing a battery fleet service can ask about its findings in a chat while keeping control over what the assistant may call.

Click through it at your own pace, or open it full screen.

To try it on your own repositories, download Safeguard and follow the CLI documentation.

Quick check

In the Linux power supply class, is the capacity attribute the battery's health?

No. capacity is the state of charge in percent. Health is energy_full divided by energy_full_design, or the charge_ equivalents, which are in different units and must not be mixed.

A pack's cell is 100 mAh ahead and its bleed current is 60 mA. Roughly how long does passive balancing take?

About 1.7 hours, because 100 mAh divided by 60 mA is about 1.67 hours, assuming the firmware balances continuously and does not pause for temperature.

Sources

Last reviewed: 25 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.