On Thu, Feb 09, 2023 at 09:20:10PM +0300, Mikhail wrote:
> >Synopsis:    wrong ECDT EC_ID handling
> >Category:    acpi
> >Environment:
>       System      : OpenBSD 7.2
>       Details     : OpenBSD 7.2-current (GENERIC.MP) #1021: Sun Feb  5 
> 09:52:50 MST 2023
>                        
> [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> 
>       Architecture: OpenBSD.amd64
>       Machine     : amd64
> >Description:
>       Currently the kernel doesn't check if EC_ID presented in
>       ECDT is correct, it looks like wrong EC_ID is fairly common
>       mistake in (at least) Lenovo firmware. As consequences -
>       CapsLock LED, brightness keys and apm battery status doesn't
>       work. Similar problem affects at least one more person:
>       https://marc.info/?l=openbsd-tech&m=166654588612920&w=2 [he is cc'ed]
> 
>       I asked for BIOS update from semi-official support forum
>       forums.lenovo.com and from official [email protected] - in first case
>       there no meaningful answer for about 4 months and second one sent to
>       partner's service-center for assistance.
> 
>       I think it's hopeless to wait for ECDT correction, or ECDT
>       removal from the vendor, so I decided to propose a patch for the
>       OS.
> 
> >How-To-Repeat:
>       Test on Lenovo IdeaPad 3 14itl05, BIOS GCCN32WW
> >Fix:
>       I propose to add a check for wrong EC_ID, and if the check fails - do
>       not attach ECDT, we still will attach EC after that, but with another
>       procedure, inlined patch makes my CapsLock LED, brightness buttons and
>       apm battery status work.
> 
> diff /usr/src
> commit - b7cf571f83522f53df8a14fa01dcbeff8df0f02a
> path + /usr/src
> blob - 5ef24d5179de52d5321e578b3b73dd9524e7c1de
> file + sys/dev/acpi/acpiec.c
> --- sys/dev/acpi/acpiec.c
> +++ sys/dev/acpi/acpiec.c
> @@ -429,6 +429,14 @@ acpiec_getcrs(struct acpiec_softc *sc, struct acpi_att
>  
>       /* Check if this is ECDT initialization */
>       if (ecdt) {
> +             /* Get devnode from header */
> +             sc->sc_devnode = aml_searchname(sc->sc_acpi->sc_root,
> +                 ecdt->ec_id);
> +             if (sc->sc_devnode == NULL) {
> +                     printf("acpiec wrong ECDT EC_ID, broken BIOS\n");
> +                     return (1);
> +             }
> +
>               /* Get GPE, Data and Control segments */
>               sc->sc_gpe = ecdt->gpe_bit;
>  
> @@ -444,10 +452,6 @@ acpiec_getcrs(struct acpiec_softc *sc, struct acpi_att
>                       sc->sc_data_bt = sc->sc_acpi->sc_memt;
>               sc->sc_ec_data = ecdt->ec_data.address;
>  
> -             /* Get devnode from header */
> -             sc->sc_devnode = aml_searchname(sc->sc_acpi->sc_root,
> -                 ecdt->ec_id);
> -
>               goto ecdtdone;
>       }

ping

Reply via email to