Skip to content

Commit

Permalink
atkbc: Better test for old chromebooks
Browse files Browse the repository at this point in the history
Older Chromebooks have issues in their embedded controller (EC) firmware
which need working around in atkbd and atkbdc. On these systems, rather
than use a standard EC, Google used their own arm-based EC. For a while,
its firmware incorrectly implemented the i8042, requiring workaroundsd
in the driver.

Implement a heuristic recommended by MrChromebox <[email protected]>
to detect them: If the bios.version starts with Google_, or the maker is
either Google or GOOGLE, assume that it's a chromebook with the affected
bios. While this isn't strictly true, the number of updated systems
without the bug is very small and this will exclude all the non-Google
coreboot user that use a standard EC. There's no simple way to test the
hardware to see if it's implemented with the buggy EC.

Sponsored by:		Netflix
Reviewed by:		[email protected], MrChromebox
Differential Revision:	https://reviews.freebsd.org/D40789
  • Loading branch information
bsdimp committed Jun 29, 2023
1 parent b5b9eaa commit 319d2bf
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 11 deletions.
6 changes: 6 additions & 0 deletions UPDATING
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 14.x IS SLOW:
world, or to merely disable the most expensive debugging functionality
at runtime, run "ln -s 'abort:false,junk:false' /etc/malloc.conf".)

20230629:
The heuristic for detecting old chromebooks with an EC bug that requires
atkbdc driver workarounds has changed. There should be no functional
change, but if your old chromebook's keyboard stops working, please
file a PR and assign it to imp.

20230623:
OpenSSL has been updated to version 3.0, including changes throughout
the base system. It is important to rebuild third-party software
Expand Down
40 changes: 29 additions & 11 deletions sys/dev/atkbdc/atkbdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,21 +109,37 @@ struct atkbdc_quirks {
const char *bios_vendor;
const char *maker;
const char *product;
const char *version;
int quirk;
};

/* Old chromebooks running coreboot with i8042 emulation quirks */
#define CHROMEBOOK_WORKAROUND \
(KBDC_QUIRK_KEEP_ACTIVATED | KBDC_QUIRK_IGNORE_PROBE_RESULT | \
KBDC_QUIRK_RESET_AFTER_PROBE | KBDC_QUIRK_SETLEDS_ON_INIT)

static struct atkbdc_quirks quirks[] = {
{"coreboot", "System76", NULL, 0},
{"coreboot", "Purism", NULL, 0},
{"coreboot", NULL, NULL,
KBDC_QUIRK_KEEP_ACTIVATED | KBDC_QUIRK_IGNORE_PROBE_RESULT |
KBDC_QUIRK_RESET_AFTER_PROBE | KBDC_QUIRK_SETLEDS_ON_INIT},
/*
* Older chromebooks running coreboot have an EC that imperfectly emulates
* i8042 w/o fixes to its firmware. Since we can't probe for the problem,
* include all chromebooks by matching 'Google_' in the bios version string
* or a maker of either 'Google' or 'GOOGLE'. This is imperfect, but catches
* all chromebooks while omitting non-Google systems from System76 and
* Purism.
*/
{"coreboot", NULL, NULL, "Google_", CHROMEBOOK_WORKAROUND},
{"coreboot", "GOOGLE", NULL, NULL, CHROMEBOOK_WORKAROUND},
{"coreboot", "Google", NULL, NULL, CHROMEBOOK_WORKAROUND},
/* KBDC hangs on Lenovo X120e and X121e after disabling AUX MUX */
{NULL, "LENOVO", NULL, KBDC_QUIRK_DISABLE_MUX_PROBE},
{NULL, "LENOVO", NULL, NULL, KBDC_QUIRK_DISABLE_MUX_PROBE},
};

#define QUIRK_STR_MATCH(s1, s2) (s1 == NULL || \
(s2 != NULL && !strcmp(s1, s2)))
#define QUIRK_STR_EQUAL(s1, s2) \
(s1 == NULL || \
(s2 != NULL && strcmp(s1, s2) == 0))
#define QUIRK_STR_MATCH(s1, s2) \
(s1 == NULL || \
(s2 != NULL && strncmp(s1, s2, strlen(s1)) == 0))

static int
atkbdc_getquirks(void)
Expand All @@ -132,11 +148,13 @@ atkbdc_getquirks(void)
char *bios_vendor = kern_getenv("smbios.bios.vendor");
char *maker = kern_getenv("smbios.system.maker");
char *product = kern_getenv("smbios.system.product");
char *version = kern_getenv("smbios.bios.version");

for (i = 0; i < nitems(quirks); i++)
if (QUIRK_STR_MATCH(quirks[i].bios_vendor, bios_vendor) &&
QUIRK_STR_MATCH(quirks[i].maker, maker) &&
QUIRK_STR_MATCH(quirks[i].product, product))
if (QUIRK_STR_EQUAL(quirks[i].bios_vendor, bios_vendor) &&
QUIRK_STR_EQUAL(quirks[i].maker, maker) &&
QUIRK_STR_EQUAL(quirks[i].product, product) &&
QUIRK_STR_MATCH(quirks[i].version, version))
return (quirks[i].quirk);

return (0);
Expand Down

0 comments on commit 319d2bf

Please sign in to comment.