cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

chromeos_privacy_screen.c (4539B)


      1// SPDX-License-Identifier: GPL-2.0
      2
      3/*
      4 *  ChromeOS Privacy Screen support
      5 *
      6 * Copyright (C) 2022 Google LLC
      7 *
      8 * This is the Chromeos privacy screen provider, present on certain chromebooks,
      9 * represented by a GOOG0010 device in the ACPI. This ACPI device, if present,
     10 * will cause the i915 drm driver to probe defer until this driver registers
     11 * the privacy-screen.
     12 */
     13
     14#include <linux/acpi.h>
     15#include <drm/drm_privacy_screen_driver.h>
     16
     17/*
     18 * The DSM (Device Specific Method) constants below are the agreed API with
     19 * the firmware team, on how to control privacy screen using ACPI methods.
     20 */
     21#define PRIV_SCRN_DSM_REVID		1	/* DSM version */
     22#define PRIV_SCRN_DSM_FN_GET_STATUS	1	/* Get privacy screen status */
     23#define PRIV_SCRN_DSM_FN_ENABLE		2	/* Enable privacy screen */
     24#define PRIV_SCRN_DSM_FN_DISABLE	3	/* Disable privacy screen */
     25
     26static const guid_t chromeos_privacy_screen_dsm_guid =
     27		    GUID_INIT(0xc7033113, 0x8720, 0x4ceb,
     28			      0x90, 0x90, 0x9d, 0x52, 0xb3, 0xe5, 0x2d, 0x73);
     29
     30static void
     31chromeos_privacy_screen_get_hw_state(struct drm_privacy_screen
     32				     *drm_privacy_screen)
     33{
     34	union acpi_object *obj;
     35	acpi_handle handle;
     36	struct device *privacy_screen =
     37		drm_privacy_screen_get_drvdata(drm_privacy_screen);
     38
     39	handle = acpi_device_handle(to_acpi_device(privacy_screen));
     40	obj = acpi_evaluate_dsm(handle, &chromeos_privacy_screen_dsm_guid,
     41				PRIV_SCRN_DSM_REVID,
     42				PRIV_SCRN_DSM_FN_GET_STATUS, NULL);
     43	if (!obj) {
     44		dev_err(privacy_screen,
     45			"_DSM failed to get privacy-screen state\n");
     46		return;
     47	}
     48
     49	if (obj->type != ACPI_TYPE_INTEGER)
     50		dev_err(privacy_screen,
     51			"Bad _DSM to get privacy-screen state\n");
     52	else if (obj->integer.value == 1)
     53		drm_privacy_screen->hw_state = drm_privacy_screen->sw_state =
     54			PRIVACY_SCREEN_ENABLED;
     55	else
     56		drm_privacy_screen->hw_state = drm_privacy_screen->sw_state =
     57			PRIVACY_SCREEN_DISABLED;
     58
     59	ACPI_FREE(obj);
     60}
     61
     62static int
     63chromeos_privacy_screen_set_sw_state(struct drm_privacy_screen
     64				     *drm_privacy_screen,
     65				     enum drm_privacy_screen_status state)
     66{
     67	union acpi_object *obj = NULL;
     68	acpi_handle handle;
     69	struct device *privacy_screen =
     70		drm_privacy_screen_get_drvdata(drm_privacy_screen);
     71
     72	handle = acpi_device_handle(to_acpi_device(privacy_screen));
     73
     74	if (state == PRIVACY_SCREEN_DISABLED) {
     75		obj = acpi_evaluate_dsm(handle,
     76					&chromeos_privacy_screen_dsm_guid,
     77					PRIV_SCRN_DSM_REVID,
     78					PRIV_SCRN_DSM_FN_DISABLE, NULL);
     79	} else if (state == PRIVACY_SCREEN_ENABLED) {
     80		obj = acpi_evaluate_dsm(handle,
     81					&chromeos_privacy_screen_dsm_guid,
     82					PRIV_SCRN_DSM_REVID,
     83					PRIV_SCRN_DSM_FN_ENABLE, NULL);
     84	} else {
     85		dev_err(privacy_screen,
     86			"Bad attempt to set privacy-screen status to %u\n",
     87			state);
     88		return -EINVAL;
     89	}
     90
     91	if (!obj) {
     92		dev_err(privacy_screen,
     93			"_DSM failed to set privacy-screen state\n");
     94		return -EIO;
     95	}
     96
     97	drm_privacy_screen->hw_state = drm_privacy_screen->sw_state = state;
     98	ACPI_FREE(obj);
     99	return 0;
    100}
    101
    102static const struct drm_privacy_screen_ops chromeos_privacy_screen_ops = {
    103	.get_hw_state = chromeos_privacy_screen_get_hw_state,
    104	.set_sw_state = chromeos_privacy_screen_set_sw_state,
    105};
    106
    107static int chromeos_privacy_screen_add(struct acpi_device *adev)
    108{
    109	struct drm_privacy_screen *drm_privacy_screen =
    110		drm_privacy_screen_register(&adev->dev,
    111					    &chromeos_privacy_screen_ops,
    112					    &adev->dev);
    113
    114	if (IS_ERR(drm_privacy_screen)) {
    115		dev_err(&adev->dev, "Error registering privacy-screen\n");
    116		return PTR_ERR(drm_privacy_screen);
    117	}
    118
    119	adev->driver_data = drm_privacy_screen;
    120	dev_info(&adev->dev, "registered privacy-screen '%s'\n",
    121		 dev_name(&drm_privacy_screen->dev));
    122
    123	return 0;
    124}
    125
    126static int chromeos_privacy_screen_remove(struct acpi_device *adev)
    127{
    128	struct drm_privacy_screen *drm_privacy_screen =	acpi_driver_data(adev);
    129
    130	drm_privacy_screen_unregister(drm_privacy_screen);
    131	return 0;
    132}
    133
    134static const struct acpi_device_id chromeos_privacy_screen_device_ids[] = {
    135	{"GOOG0010", 0}, /* Google's electronic privacy screen for eDP-1 */
    136	{}
    137};
    138MODULE_DEVICE_TABLE(acpi, chromeos_privacy_screen_device_ids);
    139
    140static struct acpi_driver chromeos_privacy_screen_driver = {
    141	.name = "chromeos_privacy_screen_driver",
    142	.class = "ChromeOS",
    143	.ids = chromeos_privacy_screen_device_ids,
    144	.ops = {
    145		.add = chromeos_privacy_screen_add,
    146		.remove = chromeos_privacy_screen_remove,
    147	},
    148};
    149
    150module_acpi_driver(chromeos_privacy_screen_driver);
    151MODULE_LICENSE("GPL v2");
    152MODULE_DESCRIPTION("ChromeOS ACPI Privacy Screen driver");
    153MODULE_AUTHOR("Rajat Jain <rajatja@google.com>");