1 WARNING: NO WARRANTIES, USE AT YOUR OWN RISK!
2 DONT SUE US WHEN YOUR BATTERY, MACBOOK, HOUSE OR ANYTHING ELSE
5 Potentially unbricking e.g. Apple MacBook batteries with
6 too low of a safety voltage and permanent failure bit set.
7 By unsealing and clearing the Permanent Failure Status bit!
9 1st: for this to have an effect and work you need to first
10 open the battery without damaging the cells, check that
11 they are ok, not expanded, burned, ... and pre-charge them
12 with a lab power supply until they have an initial high
13 enough minimal cell voltage.
15 Only then run this modifed ACPI code to reset the bit.
16 (if you run this without pre-charging the battery pack
17 will likely instantly go back into fail mode due to
18 stil being below the minimal safety voltage.
20 The pack I test this with did not instantly start charging,
21 but had to be ejected from the MacBook and inserted again.
23 Please let ms know if and when you try this and your result!
24 Outputs will be in the system dmesg.
26 - René Rebe <rene@rebe.name>
28 --- linux-5.0/drivers/acpi/sbs.c.vanilla 2019-04-02 12:52:24.448537687 +0200
29 +++ linux-5.0/drivers/acpi/sbs.c 2019-04-02 12:56:38.944548238 +0200
34 +static const char* mfg_status[16] = {
41 + "Charge termination",
43 + "Fault charge terminate",
44 + "Permanent failure",
53 +static const char* fet_status[4] = {
60 +static const char* pf_status[4] = {
61 + "Fuse blown (if failure)",
69 static int acpi_battery_add(struct acpi_sbs *sbs, int id)
72 printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
73 ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
74 battery->name, battery->present ? "present" : "absent");
76 + /* RxR wild hacking */
77 + u16 value = 0x0006; /* ManufacturerStatus */
78 + result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
80 + printk(KERN_INFO "error: %d\n", result);
82 + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value);
83 + printk(KERN_INFO "result: %d %04x %s\n", result, value, mfg_status[(value >> 8) & 0xf]);
84 + printk(KERN_INFO "result: FETs: %s, PF: %s\n", fet_status[(value >> 14) & 0x3], pf_status[(value >> 12) & 0x3]);
85 + bool wasPF = ((value >> 8) & 0xf) == 0x9;
88 + acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
89 + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value);
90 + printk(KERN_INFO "PFStatus: %d %04x\n", result, value);
92 + acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
93 + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value);
94 + printk(KERN_INFO "OpStatus: %d %04x\n", result, value);
99 + result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
101 + result |= acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
102 + printk(KERN_INFO "Unseal: %d\n", result);
104 + /* clear permanent failure */
106 + result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
108 + result |= acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
109 + printk(KERN_INFO "clear pf: %d\n", result);
113 + result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, 0x0, (u8 *)&value, 2);
114 + printk(KERN_INFO "re-sealed: %d\n", result);