Jump to content

Skylake Toshiba laptop: Battery Status (working but not working) OpenCore assistance?


23 posts in this topic

Recommended Posts

I'll try and be as succinct/organized as possible, I have a tendency to be -v. 

 

Summary:

I'm using a Skylake (100 series chipset) Laptop (Toshiba Z50-C) with everything working ALMOST perfectly except the battery indicator. It works until it hits 100% and then stops updating. If it never hits 100%, it'll work fine though updates (unplugging or plugging) take ~30-60 seconds before the indicator updates. There are some other small issues like the backlight keys not working, but I haven't bothered to remap the ACPI key inputs yet. 

 

My setup:
OpenCore 0.7.3 (With all relative kexts/drivers up to date) 

Big Sur 11.5.2

 

My ACPI's: 

  • SSDT-EC-USBX
  • SSDT-GPI0
  • SSDT-MouseAsTrackpad
  • SSDT-PLUG
  • SSDT-PNLF
  • SSDT-SBUS-MCHC

 

My kexts:

  • AirportBrcmFixup (I'm using a broadcom 4331 Wifi module)
  • AppleALC
  • BrightnessKeys (The smooth transition for the slider works, the backlight keys don't - I'll address the ACPI key mappings later, no biggie)
  • IntelMausi (Intel ethernet)
  • Lilu
  • SMCBatteryManager (This is where the problem is I'm guessing)
  • SMCLightSensor (I believe this is redundant, I'm 99% sure my hardware doesn't have this, and I might have even turned it off in the config.plist)
  • SMCProcessor
  • SMCSuperIO
  • VirtualSMC
  • VoodooPS2Controller (Mouse/keyboard won't work without it)
  • WhateverGreen
  • Z50C-USB-Map (I made my own USB Mapping for this laptop, all USB ports working properly now including power)

 

Issue in detail:

The preamble: I've attempted to build a custom battery SSDT, however all of the guides I've seen imply some sort of EC somewhere. My computer doesn't have one, so I can't follow the guides. There's also only a single battery, so I'd think it's a hopefully a mostly-straightforward problem to fix. 

 

Using the SMCBatteryManager, the battery DOES WORK. It shows in the status bar, it shows the current state. It shows charging and discharging, time left. 

 

What doesn't work: When the charge hits 100%, the status completely stops updating. If I unplug the laptop, it'll show charging until the laptop dies completely. If I restart however (Even with the status at 100% but NOT charging) the status will update accordingly until I plug it back in and the status hits 100% again. 

 

I did see a patch from RehabMan which had described this issue, but the patch he's applying doesn't work for my DSDT since I have no FBST object. (guide-how-to-patch-dsdt-for-working-batt)

For reference, the patch he discusses is below:

into method label FBST code_regex If\s\(CHGS\s\(Zero\)\)[\s]+\{[\s]+Store\s\(0x02,\sLocal0\)[\s]+\}[\s]+Else[\s]+\{[\s]+Store\s\(One,\sLocal0\)[\s]+\} replaceall_matched begin
If (CHGS (Zero))\n
{\n
     Store (0x02, Local0)\n
}\n
Else\n
{\n
     Store (Zero, Local0)\n
}
end;

There's another issue, which is the polling rate which seems to be quite slow. I don't know what the expected behavior is using SMCBatteryManager, but it takes 30-60 seconds before my battery status will update when plugging/unplugging the charger. This is less an issue, but I wanted to know if there's a way to increase it (or perhaps if it IS a bug with SMCBatteryManager, an SSDT patch may correct the issue) 

 

Sidenote: 
I did have this hackintosh running previously using FakeSMC and Rehabman's ACPI Battery kext, running on Sierra and the battery was working correctly then, but I'm hesitant to use these kexts as many of them are depreciated and I don't know how happily they'll work with OpenCore. 

 

I've attached my EFI (without the extra kexts and bloat files, but keeping other relevant files) as well as my IORegExplorer output for my current setup. 

 

I can address anything else that isn't working (Like the backlight keys) since they're minor issues and should be an easy fix. This is the last major thing that's bothering me, and it doesn't truly affect the usability of the machine. If, however, there's a possible problem with the SMCBatteryManager that might affect other people down the road, I wanted to at least bring it up. 

 

TL;DR: 
Everything is generally working except the battery indicator, and it only stops working once it hits 100% with the charger plugged in. It also takes a good 30-60 seconds before the indicator changes showing it's running on battery or is charging. What troubleshooting steps could I take to try and resolve this issue? Any guides I've followed for creating a custom SSDT for the battery don't seem to apply and while I'm somewhat familiar with the ACPI programming spec (I've read the manual several times, I get the principal behind the language) I don't know exactly what the SMCBatteryManager is looking for in terms of inputs from the ACPI to pass battery information along. 

Any ideas, suggestions or help would be appreciated, and if there's anything in addition to what's been provided that might be required, let me know and I'll get it as soon as I can. 

 

 

 

 

 

 

Latest Working EFI Sept 16, 2021.zip IORegOutput.zip

Thanks Allan, 

 

I absolutely have tried ECEnabler - no difference. When I looked at the SSDT, it's referencing fields that don't exist in my DSDT, so I assumed it did nothing and have since removed it but I did have it for a period. No behavioral change since having removed it however. 

Okay, reporting back after the update. 

By "Reset NVRam" I assume you meant you wanted me to use the ClearNVRAM tool I put in my Tools directory, so I did that and rebooted using the updated config.plist you provided. 

 

So far, no change. The battery status is still 'stuck' after hitting 100%. 

I'm definitely not opposed! I did use clover back in the Sierra days, but I used RehabMan's stuff and it did work properly then. Obviously a lot has changed since. 

 

For using clover I'll put together the same Kexts, and keep as much as possible the same, however the config.plist has to change for compatibility reasons. 

 

Are you aware of any specific plist converters to alternate between OpenCore and Clover or has Clover been updated enough to be able to read OpenCore config files? 

It's fine to use AcpiBatteryManager instead of SMCBatteryManager with OpenCore. AcpiBatteryManager doesn't depend on FakeSMC so no other replacements are needed.
Next thing to do is to probably see if your getting errors (I usually do "log show --last boot | grep -i ACPI"). If your not getting errors, you could try AcpiBatteryManager.
Could look to see if there is anything that is supposed to notify the battery, though I'd think that even just polling would work even faster then what your seeing.

1 hour ago, enigmahack said:

Are you aware of any specific plist converters to alternate between OpenCore and Clover or has Clover been updated enough to be able to read OpenCore config files? 

Yes, now Clover uses "Quirks" and OpenRuntime, look:

 

But as I said, it's just a test. If it not work, well we need to go deeper 😬

Okay, I have some updates after some testing. 

 

1 - I tried to substitute using RehabMan's ACPIBatteryManager. The battery status showed up but it was completely locked up. No status changes whatsoever. 

2 - I followed the instructions to use Clover instead. I verified that the settings were correct, used the validator to make sure my config was correct (It was stated that it was) and I also updated the quirks using CloverConfigurator. When I attempted to boot from the USB stick with the Clover configuration, I ended up with a verbose output with "Failed to detect super IO chip" amongst other errors. More info below. 

3 - Regarding checking the errors from the ACPI logs, there's only one error that shows: 

2021-08-31 14:54:38.714969-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: sleep states S3 S4 S5
2021-08-31 14:54:38.716265-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.716272-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.716276-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.716684-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.716690-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.716695-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.717090-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.717096-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.717100-0300 0x71       Default     0x0                  0      0    kernel: (AppleACPIPlatform) ACPI: cannot translate ACPI object 14
2021-08-31 14:54:38.744605-0300 0x74       Default     0x0                  0      0    kernel: PMRD: PMTrace found PCI host bridge PCI0->AppleACPIPCI
2021-08-31 14:54:38.969328-0300 0x65       Default     0x0                  0      0    kernel: (AppleACPIPlatform)  found RTC service


Everything else seems to be working minus the battery indicator as outlined above. 

 

I'll keep poking away at the Clover configuration to see if I can get things booting, and I DO have a picture from my phone that I've attached. (This is the clover boot that was failing)

There was obviously other errors, like something about my audio device and backlight control (DPMicro) but as mentioned, I'm going to keep poking away at it until I can get Clover booting hopefully. 

 

 

IMG_20210916_234525.jpg

Small progress with Clover: I was dumb. I forgot to check FuzzyMatch, which resolved a bunch of errors in the verbose boot log. 

I'm still not able to boot using clover, lots of errors now surrounding APFS and keybag init. I'm looking into that to see if I can get Clover booting, and once I do, see if that changes anything with the battery situation. 

Okay, last update for now. 

 

Clover - no luck. Simply won't boot. I'm sure it's something simple I'm missing but just doesn't progress past the Keybag 2037 error. 

 

I've gone back to troubleshooting in OpenCore, and the most success I have is currently with the SMCBatteryManager, but it's still not working correctly (As the behavior mentioned above is the current state)

@enigmahack First order of business would be to generate a fake SSDT-EC.aml for Laptops using SDSDTTime. Then your custom Battery.aml might work alongside SMCBatteryManager.kext. But usually, having a Battery ACPI is not enough and additional binary renames are required.

 

For my Notebook I needed about 15 additional binary renames to get the Battery status indicator working, before ECEnabler.kext existed ­ - you have none in your config. So therefore, I would try the combination of SSDT-EC, ECEnabler and SMCBatteryManager.kext  first (ECEnabler does not work with FakeSMC and VoodooBatterySMC.kext, btw.). If that still doesn't work you have to do it the hard way and find these binary renames.

Edited by 5T33Z0

Thanks @5T33Z0

 

I actually have the code that's generated by the SSDT-EC in my SSDT-EC-USBX.aml file. I wanted to see what SSDTTime was outputting when using various aml files, and it's precisely the same code, so I DO have that enabled already. I'm tempted to actually turn it off entirely just to see what happens but I suspect that it's a required mapping. 

 

I actually don't mind manually finding the binary renames, and in fact I think I'd prefer it so I can understand how to get additional information statuses working based off of the information provided by the _BIF and _BST. The problem is that I don't have a deeper understanding of what ECEnabler actually does since my DSDT doesn't contain any EC whatsoever, so I don't know how to redirect the ACPI information into some meaningful handler. 

 

Also, rehabman's directions are excellent, but don't directly apply to my situation for a few reasons and I'm having a hard time figuring out where to go next. 

 

**edit**
And just as a sidenote, when I'm looking at the code for what ECEnabler actually does, it seems to allow the MacOS to read the size of any EC field which prevents the need for EC byte patching. It doesn't actually generate a fake EC as far as I can tell. 

Edited by enigmahack

@enigmahack Here's a pretty extensive battery patching guide I found when I was looking to fix my battery. It's auto translated from Chinese into English but still very readable: https://zyhilf44myghbg23imr2whblly--xstar-dev-github-io.translate.goog/hackintosh_advanced/Guide_For_Battery_Hotpatch.html

 

Here's some background info on how ECEnabler works:

 

Thanks @5T33Z0

 

I've actually read through that Chinese-translated site before, and they're mostly manually patching the >8bit fields. I spoke with 1Revenger1 and he actually stated directly that ECEnabler ONLY addresses the larger bit fields. It doesn't do anything else so if your DSDT doesn't have 16bit (or larger) fields related to the controller, it's redundant or unnecessary. 

 

I think this is starting to get to the crux of the issue - The 'usual' problems people have with the battery don't seem to apply to my hardware. My DSDT doesn't have an Embedded Controller, a PNP0C09 device, H_EC, multi-bit controllers, nothing. It's a relatively simple DSDT with a BAT1 device (PNP0C0A) and only 3 methods: _STA for the existence state, _BIF for the battery info and _BST for the power/state. 

 

Even the Chinese guide is suggesting the dependency of H_EC or similar under the _SB.PCI0.LPCB but there's no controller there either. It looks like the battery is directly connected to the _SB bus. 

 

I'd love to be able to figure out how to manually read values from the ACPI directly using some application, just so I could debug what's being returned by the BAT1 device. Maybe it's not a problem with the SMCBatteryManager necessarily, but it could be that the ACPI is returning a bad value that isn't handled by SMCBatteryManager and an SSDT could correct for that. (But then I don't know how to read what SMCBatteryManager is handing off to the ACPI to get it's values either.)

 

Or perhaps I'm just overcomplicating things too and maybe there's a MUCH simpler answer. Personally what I'd LIKE to do is just write my own SSDT to provide the info straight to SMCBatteryManager in a meaningful way, but there aren't any guides on setups closer to my own hardware that I can piggyback off of. 

 

I'm going to start looking at older RehabMan patches of the past to see if there are laptops with similar hardware and try and figure out what kinds of things he did with those too, unless someone here is quite familiar with ACPI programming? 

 

You can check these Laptop Clover Configs. They are sorted by Intel Graphics of the used CPU. But the the contain Battery Patches and the form of the config is out dated (deprecated features, no quirks, etc). https://github.com/RehabMan/OS-X-Clover-Laptop-Config

 

I have some patches on the OC Little repo which I translated a while back: https://github.com/5T33Z0/OC-Little-Translated/tree/main/05. Laptop-specific Patches. Maybe there's something useful in there.

Oh sweet - Thanks @5T33Z0 - I'm going to check those patches out and see if I can muck about and make something happen. 

 

Ideally, I wouldn't need the SMCBatteryManager whatsoever, but I don't know how realistic that is. (Or is it possible that a proper SSDT would be able to completely replace SMCBatteryManager?)

 

As an aside, what's the purpose of renaming _STA to XSTA generally? 

 

Thanks for the link, I'm going to dive in and see if I can repurpose/understand what's going on with these and see if I can muck about with my own. 

 

@Hervé - My DSDT is posted in my original post, in the EFI zip file. 

Edited by enigmahack

Just a quick update. 

 

I've been working with @1Revenger1 and troubleshooting my setup. It doesn't seem like it's a problem with SMCBatteryManager (yet) though quick polling doesn't work for my machine. Looking at the source code, it seems when an ACPI event happens, quickPolling is enabled for 60 seconds, and then goes back to a once-per-minute polling cycle. 

 

Well, my hardware is: 
A- Not broadcasting ACPI events; 

B- Broadcasting events that SMCBatteryManager isn't handling;

C- Not broadcasting ACPI change events.

 

A is unlikely, this hardware works fine for Windows and Linux with no issues. 

B is unlikely, it works fine for other computers. 

C... This would explain the slow polling cycle. (Why it takes up to 60 seconds for me to see the adapter is present and battery is now charging, or not)

 

Further investigation: 

SMCBatteryManager has code that shows once your battery is full AND you're charging, it's likely not polling anymore. I haven't dug in deeper yet, but what I don't know is if it just skips this polling cycle or if it won't poll anymore UNTIL another state change event occurs. 

 

	if (externalPowerConnected && batteriesAreFull) {
		DBGLOG("bmgr", "no poll");
		return;
	}

This means that SMCBatteryManager relies on ACPI change state notification... Which isn't working yet. Le sigh. 

 

So anyway, some progress is being made. I just need to figure out what ACPI event is being sent and what it's called when the state changes, and then throw that at SMCBatteryManager. 

 

I *THINK* if I can get that part figured out, I might just be able to rename the state change data to something SMC_BM is expecting and it'll fix both issues at the same time. 

 

I'm half tempted to compile my own version which doesn't disable polling ever, and will just always check regardless. 

The better solution here is just to figure out why SMC_BM isn't getting my state changes. 

 

Edited by enigmahack
54 minutes ago, enigmahack said:

Just a quick update. 

 

I've been working with @1Revenger1 and troubleshooting my setup. It doesn't seem like it's a problem with SMCBatteryManager (yet) though quick polling doesn't work for my machine. Looking at the source code, it seems when an ACPI event happens, quickPolling is enabled for 60 seconds, and then goes back to a once-per-minute polling cycle. 

 

Well, my hardware is: 
A- Not broadcasting ACPI events; 

B- Broadcasting events that SMCBatteryManager isn't handling;

C- Not broadcasting ACPI change events.

 

A is unlikely, this hardware works fine for Windows and Linux with no issues. 

B is unlikely, it works fine for other computers. 

C... This would explain the slow polling cycle. (Why it takes up to 60 seconds for me to see the adapter is present and battery is now charging, or not)

 

Further investigation: 

SMCBatteryManager has code that shows once your battery is full AND you're charging, it's likely not polling anymore. I haven't dug in deeper yet, but what I don't know is if it just skips this polling cycle or if it won't poll anymore UNTIL another state change event occurs. 

 




	if (externalPowerConnected && batteriesAreFull) {
		DBGLOG("bmgr", "no poll");
		return;
	}

This means that SMCBatteryManager relies on ACPI change state notification... Which isn't working yet. Le sigh. 

 

So anyway, some progress is being made. I just need to figure out what ACPI event is being sent and what it's called when the state changes, and then throw that at SMCBatteryManager. 

 

I *THINK* if I can get that part figured out, I might just be able to rename the state change data to something SMC_BM is expecting and it'll fix both issues at the same time. 

 

I'm half tempted to compile my own version which doesn't disable polling ever, and will just always check regardless. 

The better solution here is just to figure out why SMC_BM isn't getting my state changes. 

 

Normally ACPI events aren't sent every time battery data changes. I think usually the expectation is that it's polled. You should be getting events though when the cable is plugged in or taken out. So C is my guess.

 

Edit: also, the IOTimerEventSource only fires once. It has to be setup and enabled every time you want it to fire. So to continually have it fire every second, you need to set the timeout and enable it every second. This is usually done in the method that's called by the timer.

Edited by 1Revenger1
6 minutes ago, 1Revenger1 said:

Normally ACPI events aren't sent every time battery data changes. I think usually the expectation is that it's polled. You should be getting events though when the cable is plugged in or taken out. So C is my guess.

@1Revenger1 Right - I should have been more specific - I mean when the cable is plugged or unplugged is when it should fire an event, not necessarily when any information on the battery changes. Either way, that's the part that I think is missing which could explain the behavior. 

 

 

  • Like 1

Okay, I thought I was making progress. I mean, I have learned a *LOT* about ACPI and programming in it, which is good. 

 

So there's a little new info but nothing significant: 

 

The battery works. The information IN the battery (Voltages, capacity, etc. is being handed off to SMCBatteryManager) as they show up in IORegistryExplorer. This is good news. 

When I drain the battery, low capacity limits and power-down limits work. This is also good news. I've been able to patch the battery info via SSDT to inject information *I* want to see, so I know enough to know I can do a thing.

As soon as the battery hits "FullyCharged" in the OS, SMCBatteryManager stops polling.  

 

What still isn't working at a deeper level: 
ACPI State Changes aren't being seen by SMCBatteryManager, which means as soon as polling is turned off, it'll never turn back on. This explains why QuickPolling doesn't work, and why I only get updates every 60 seconds. 

 

I was looking at the ACPI spec, which shows that a battery can send an OS notification when a change happens. Specifically, when AC is removed or added. 

0x80 Battery Status Changed. Used to notify OSPM that the Control Method Battery device status has changed.

Troubleshooting further, I notice that when the laptop goes to sleep and wakes back up the battery state is updated so it seems like a method called TGPE (\_GPE.TGPE) which contains notify commands that revive the battery state. 

Working backwards, I wanted to see what else will use TGPE, which points to _L62 Method. Contained in this method is the conditional method call to TGPE listed above. 

 

Relevant: I know the ACPI code itself works since updates work fine in Windows/Linux. 

 

Where I'm stuck is trying to figure out how to get state changes to SMCBatteryManager. I've looked at the source code and obviously it's working as well, so I assume the state changes are being sent from ACPI to SMCBatteryManager in a way that doesn't make sense, or using a name that isn't being looked at. 

 

I am trying to diagnose what's getting called by making patches in SSDT including code that sends debug code to the console, but none of it shows up in the logs or console (Even with the variety of debug logging enabled in the NVRAM boot arguments)

 

I'm completely stuck and thought I had a clue on where to go next but am hoping someone can nudge me in the next direction on where to look. I COULD make a workaround (not a fix) that is to just never send the FullyCharged signal from ACPI but that's not a fix to the root cause and I don't want to do that. 

 

Help please?

 

×
×
  • Create New...