if ARM
source "drivers/platform/arm/Kconfig"
endif
+
+config CHROMEOS
+ bool
+ depends on ARM_CHROMEOS_FIRMWARE || (NVRAM && ACPI_CHROMEOS)
+
+ ---help---
+ Provides abstracted interfaces to the firmware features provided on
+ ChromeOS devices. It depends on a lowlevel driver to implement the
+ firmware interface on the platform.
#
obj-$(CONFIG_ARM) += arm/
obj-$(CONFIG_X86) += x86/
+obj-$(CONFIG_CHROMEOS) += chromeos.o
if ARM_PLATFORM_DEVICES
config ARM_CHROMEOS_FIRMWARE
- tristate "ChromeOS firmware interface driver"
+ bool "ChromeOS firmware interface driver"
select CHROMEOS
---help---
This driver provides an interface to ChromeOS firmware.
Say Y here if you are building for a ChromeOS device.
-config CHROMEOS
- bool
- depends on ARM_CHROMEOS_FIRMWARE
-
- ---help---
- This driver provides abstracted interfaces to the firmware features
- provided on ChromeOS devices. It depends on a lowlevel driver to
- implement the firmware interface on the platform.
-
endif # CROS_PLATFORM_DEVICES
# arm Platform-Specific Drivers
#
obj-$(CONFIG_ARM_CHROMEOS_FIRMWARE) += chromeos_arm.o
-obj-$(CONFIG_CHROMEOS) += chromeos.o
+++ /dev/null
-/*
- * ChromeOS platform support code. Glue layer between higher level functions
- * and per-platform firmware interfaces.
- *
- * Copyright (C) 2011 The Chromium OS Authors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This module isolates ChromeOS platform specific behavior. In particular,
- * it uses calls from chromeos_acpi.c to control the boot flow, and exports some
- * helper functions for kernel-side consumers of platform configuration, such
- * as nvram flags.
- */
-
-#include <linux/chromeos_platform.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-
-u64 phys_window_base;
-EXPORT_SYMBOL(phys_window_base);
-
-int chromeos_set_need_recovery(void)
-{
- return -1;
-}
-
-static int __init get_mem_base(char *p)
-{
- char *endptr; /* local pointer to end of parsed string */
- u64 base = simple_strtoull(p, &endptr, 0);
-
- /* rudimentary sanity check */
- if (base & ((1 << 20) -1)) {
- pr_err("chromeos: unaligned window base 0x%llx\n", base);
- return -1;
- }
-
- phys_window_base = base;
- return 0;
-}
-
-early_param("cros_shared_mem", get_mem_base);
-
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/ide.h>
+#include "../chromeos.h"
/* TODO:
* replace the shared memory block with FDT
static struct dentry *debugfs_entry;
static struct shared_data *firmware_shared_data;
+static u64 phys_window_base = 0x3ff00000;
/* location where the nvram data blends into the sector on the MMC device */
static u16 nv_offset, nv_size;
if ((nv_offset > SECTOR_SIZE) ||
!nv_size ||
- ((nv_offset + nv_size) > SECTOR_SIZE)) {
+ ((nv_offset + nv_size) > SECTOR_SIZE) ||
+ (nv_size > MAX_NVRAM_BUFFER_SIZE)) {
/* nvram block won't fit into a sector */
pr_err(MODULE_NAME ": bad nvram location: %d:%d!\n",
nv_offset, nv_size);
/*
- * This function excpects exactly nv_size bytes to be passed in for writing.
- * It reads the appropriate mmc one sector block, blends in the new nvram
- * contents and then writes the sector back. If successful, the cached nvram
- * in the shared memory is also updated.
+ * This function accepts a buffer with exactly nv_size bytes. It reads the
+ * appropriate mmc one sector block, blends in the new nvram contents and then
+ * writes the sector back. If successful, the cached nvram in the shared
+ * memory is also updated.
*/
-static int chromeos_write(struct file *unused1, const char __user *data,
- size_t len, loff_t *unused2)
+static int _chromeos_write(const u8 *data)
{
struct page *page;
char *virtual_addr;
int rv;
- if (!access_ok(VERIFY_READ, data, len))
- return -EFAULT;
-
- if (len != nv_size) {
- pr_err(MODULE_NAME ": %d != %d, invalid block size\n",
- len, nv_size);
- return -EINVAL;
- }
-
page = alloc_page(GFP_NOIO);
if (!page) {
pr_err(MODULE_NAME ": page allocation failed\n");
if (rv)
goto unwind;
- /* as a sanity check, lets' confirm that what we read is indeed the
- * sector containing the NVRAM. Note that on a running system the
- * NVRAM block will include its CRC.
+ /* As a sanity check, let's confirm that what we read is indeed the
+ * sector containing the NVRAM. Note that on a running system the
+ * NVRAM block will include its CRC.
*/
if (memcmp(virtual_addr + nv_offset,
firmware_shared_data->nvcxt_cache, nv_size)) {
* Sector has been read, lets blend in nvram data and write the sector
* back.
*/
- if (copy_from_user(virtual_addr + nv_offset, data, len)) {
- pr_err(MODULE_NAME ": copy failed!\n");
- rv = -EFAULT;
- goto unwind;
- }
+ memcpy(virtual_addr + nv_offset, data, nv_size);
rv = chromeos_write_nvram_block(page, firmware_shared_data->nvcxt_lba);
if (!rv) {
/* Write was successful, now update the local cache */
memcpy(firmware_shared_data->nvcxt_cache,
virtual_addr + nv_offset,
- len);
- rv = len;
+ nv_size);
+ rv = nv_size;
}
unwind:
return rv;
}
+static int chromeos_write(struct file *unused1, const char __user *data,
+ size_t len, loff_t *unused2)
+{
+ u8 local_copy[MAX_NVRAM_BUFFER_SIZE];
+
+ if (!access_ok(VERIFY_READ, data, len))
+ return -EFAULT;
+
+ if (len != nv_size) {
+ pr_err(MODULE_NAME ": %d != %d, invalid block size\n",
+ len, nv_size);
+ return -EINVAL;
+ }
+
+ if (copy_from_user(local_copy, data, len)) {
+ pr_err(MODULE_NAME ": copy failed!\n");
+ return -EFAULT;
+ }
+ return _chromeos_write(local_copy);
+}
+
static const struct file_operations dbg_fops = {
.open = debugfs_open,
.read = seq_read,
.release = single_release,
};
-static void chromeos_arm_exit(void)
+
+/*
+ * Read the nvram buffer contents into the user provided space.
+ *
+ * retrun number of bytes copied, or -1 on any error.
+ */
+int chromeos_platform_read_nvram(u8 *nvram_buffer, int buf_size)
+{
+ if (!firmware_shared_data) {
+ pr_err(MODULE_NAME ": %s NVRAM not configured!\n", __func__);
+ return -1;
+ }
+
+ if (buf_size < nv_size) {
+ pr_err(MODULE_NAME
+ ": not enough room to read nvram (%d < %d)\n",
+ buf_size, nv_size);
+ return -1;
+ }
+
+ memcpy(nvram_buffer, firmware_shared_data->nvcxt_cache, nv_size);
+ return nv_size;
+}
+
+int chromeos_platform_write_nvram(u8 *nvram_buffer, int buf_size)
+{
+ if (!firmware_shared_data) {
+ pr_err(MODULE_NAME ": %sw NVRAM not configured!\n", __func__);
+ return -1;
+ }
+
+ if (buf_size != nv_size) {
+ pr_err(MODULE_NAME ": wrong write buffer size (%d != %d)\n",
+ buf_size, nv_size);
+ return -1;
+ }
+
+ return _chromeos_write(nvram_buffer);
+}
+
+static void __init chromeos_arm_shutdown(void)
{
if (debugfs_entry) {
debugfs_remove(debugfs_entry);
iounmap(firmware_shared_data);
firmware_shared_data = NULL;
}
- pr_debug(MODULE_NAME ": removed\n");
}
-int chromeos_arm_init(void)
+static int __init chromeos_arm_init(void)
{
if (!phys_window_base) {
pr_err(MODULE_NAME ": memory window base undefined\n");
nv_offset = firmware_shared_data->vbnv[0];
nv_size = firmware_shared_data->vbnv[1];
- if (verify_shared_memory())
- goto error_exit;
+ if (verify_shared_memory()) {
+ chromeos_arm_shutdown();
+ return -EINVAL;
+ }
+
debugfs_entry = debugfs_create_file(MODULE_NAME, S_IRUGO | S_IWUSR,
NULL, NULL, &dbg_fops);
if (!debugfs_entry) {
pr_err(MODULE_NAME ": failed to create a debugfs file!\n");
- goto error_exit;
+ chromeos_arm_shutdown();
+ return -EINVAL;
}
pr_debug(MODULE_NAME ": firmware cookie lba = %llx\n",
firmware_shared_data->nvcxt_lba);
return 0;
-
- error_exit:
- chromeos_arm_exit();
- return -ENODEV;
}
+subsys_initcall(chromeos_arm_init);
+
+static int __init get_mem_base(char *p)
+{
+ char *endptr; /* local pointer to end of parsed string */
+ u64 base = simple_strtoull(p, &endptr, 0);
-MODULE_AUTHOR("ChromiumOS Authors");
-MODULE_LICENSE("GPL");
+ /* rudimentary sanity check */
+ if (base & ((1 << 20) - 1)) {
+ pr_err("chromeos: unaligned window base 0x%llx\n", base);
+ return -1;
+ }
+
+ phys_window_base = base;
+ return 0;
+}
-module_init(chromeos_arm_init);
-module_exit(chromeos_arm_exit);
+early_param("cros_shared_mem", get_mem_base);
--- /dev/null
+/*
+ * ChromeOS platform support code. Glue layer between higher level functions
+ * and per-platform firmware interfaces.
+ *
+ * Copyright (C) 2010 The Chromium OS Authors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This module isolates ChromeOS platform specific behavior. In particular,
+ * it uses calls from chromeos_acpi.c to control the boot flow, and exports some
+ * helper functions for kernel-side consumers of platform configuration, such
+ * as nvram flags.
+ */
+
+#include <linux/types.h>
+#include <linux/chromeos_platform.h>
+#include <linux/module.h>
+#include "chromeos.h"
+
+static int chromeos_read_nvram(u8 *nvram_buffer, int buf_size);
+static int chromeos_write_nvram_byte(unsigned offset, u8 value);
+
+/* the following defines are copied from
+ * vboot_reference:firmware/lib/vboot_nvstorage.c.
+ */
+#define RECOVERY_OFFSET 2
+#define VBNV_RECOVERY_RW_INVALID_OS 0x43
+
+int chromeos_set_need_recovery(void)
+{
+ if (!chromeos_legacy_set_need_recovery())
+ return 0;
+
+ return chromeos_write_nvram_byte(RECOVERY_OFFSET,
+ VBNV_RECOVERY_RW_INVALID_OS);
+}
+
+/*
+ * Lifted from vboot_reference:firmware/lib/vboot_nvstorage.c and formatted.
+ *
+ * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A table-based
+ * algorithm would be faster, but for only 15 bytes isn't worth the code size.
+ */
+static u8 crc8(const u8 *data, int len)
+{
+ unsigned crc = 0;
+ int i, j;
+
+ for (j = len; j; j--, data++) {
+ crc ^= (*data << 8);
+ for (i = 8; i; i--) {
+ if (crc & 0x8000)
+ crc ^= (0x1070 << 3);
+ crc <<= 1;
+ }
+ }
+ return (u8)(crc >> 8);
+}
+
+static int chromeos_write_nvram_byte(unsigned offset, u8 value)
+{
+ u8 nvram_buffer[MAX_NVRAM_BUFFER_SIZE];
+
+ int size = chromeos_read_nvram(nvram_buffer, sizeof(nvram_buffer));
+
+ if (size <= 0)
+ return -EINVAL;
+
+ if (offset >= (size - 1))
+ return -EINVAL;
+
+ if (nvram_buffer[offset] == value)
+ return 0;
+
+ nvram_buffer[offset] = value;
+ nvram_buffer[size - 1] = crc8(nvram_buffer, size - 1);
+
+ return chromeos_platform_write_nvram(nvram_buffer, size);
+}
+
+/*
+ * Read nvram buffer contents and verify it. Return 0 on success and -1 on
+ * failure (uninitialized subsystem, corrupted crc8 value, not enough room in
+ * the buffer, etc.).
+ *
+ * If everything checks out - return number of bytes in the NVRAM buffer, -1
+ * on any error.
+ */
+static int chromeos_read_nvram(u8 *nvram_buffer, int buf_size)
+{
+ int size = chromeos_platform_read_nvram(nvram_buffer, buf_size);
+
+ if (size <= 0)
+ return -1;
+
+ if (nvram_buffer[size - 1] != crc8(nvram_buffer, size - 1)) {
+ pr_err("%s: NVRAM contents corrupted\n", __func__);
+ return -1;
+ }
+ return size;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 The Chromium OS Authors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This module isolates ChromeOS platform specific behavior. In particular,
+ * it uses calls from chromeos_acpi.c to control the boot flow, and exports some
+ * helper functions for kernel-side consumers of platform configuration, such
+ * as nvram flags.
+ */
+#ifndef _DRIVERS_PLATFORM_CHROMEOS_H
+#define _DRIVERS_PLATFORM_CHROMEOS_H
+
+#define MAX_NVRAM_BUFFER_SIZE 64 /* Should be enough for anything. */
+
+#ifdef CONFIG_ACPI_CHROMEOS
+extern int chromeos_legacy_set_need_recovery(void);
+#else
+static inline int chromeos_legacy_set_need_recovery(void) { return -ENODEV; }
+#endif
+
+extern int chromeos_platform_read_nvram(u8 *nvram_buffer, int buf_size);
+extern int chromeos_platform_write_nvram(u8 *nvram_buffer, int buf_size);
+
+#endif /* _DRIVERS_PLATFORM_CHROMEOS_H */
This driver provides the firmware interface for the services exported
through the CHROMEOS interfaces when using ChromeOS ACPI firmware.
-config CHROMEOS
- bool
- depends on NVRAM
- depends on ACPI_CHROMEOS
- ---help---
- This driver provides abstracted interfaces to the firmware features
- provided on ChromeOS devices. It depends on a lowlevel driver to
- implement the firmware interface on the platform.
-
config IBM_RTL
tristate "Device driver to enable PRTL support"
depends on X86 && PCI
obj-$(CONFIG_SAMSUNG_Q10) += samsung-q10.o
obj-$(CONFIG_APPLE_GMUX) += apple-gmux.o
obj-$(CONFIG_ACPI_CHROMEOS) += chromeos_acpi.o
-obj-$(CONFIG_CHROMEOS) += chromeos.o
+++ /dev/null
-/*
- * ChromeOS platform support code. Glue layer between higher level functions
- * and per-platform firmware interfaces.
- *
- * Copyright (C) 2010 The Chromium OS Authors
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This module isolates ChromeOS platform specific behavior. In particular,
- * it uses calls from chromeos_acpi.c to control the boot flow, and exports some
- * helper functions for kernel-side consumers of platform configuration, such
- * as nvram flags.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/nvram.h>
-#include <linux/types.h>
-#include <linux/chromeos_platform.h>
-
-#include "chromeos_acpi.h"
-
-static bool chromeos_inited;
-static bool chromeos_nvram_buffer_available;
-static int chromeos_read_nvram(u8 *nvram_buffer, int buf_size);
-static int chromeos_write_nvram(unsigned offset, u8 value);
-
-#define MAX_NVRAM_BUFFER_SIZE 64 /* Should be enough for anything. */
-
-/* the following defines are copied from
- * vboot_reference:firmware/lib/vboot_nvstorage.c.
- */
-#define RECOVERY_OFFSET 2
-#define VBNV_RECOVERY_RW_INVALID_OS 0x43
-
-bool chromeos_is_devmode(void)
-{
- struct chromeos_acpi_datum *chsw = &chromeos_acpi_if_data.switch_state;
- /*
- * If switch_state is unset, report system as in devmode since we're
- * probably running on a non-chromeos system.
- */
- return (!chsw->cad_is_set) || (chsw->cad_value & CHSW_DEVELOPER_MODE);
-}
-EXPORT_SYMBOL(chromeos_is_devmode);
-
-/*
- * This function is used with BIOSes which do not export VBNV element through
- * ACPI. These BIOSes use a fixed location in NVRAM to communicate the need to
- * restart in recovery mode.
- */
-static void chromeos_set_nvram_flag(int index, unsigned char flag)
-{
- unsigned char cur;
-
- cur = nvram_read_byte(index);
- /* already set. */
- if (cur & flag)
- return;
- nvram_write_byte(cur | flag, index);
-}
-
-static bool chromeos_on_legacy_firmware(void)
-{
- /*
- * Presense of the CHNV ACPI element implies running on a legacy
- * firmware
- */
- return chromeos_acpi_if_data.chnv.cad_is_set;
-}
-
-int chromeos_set_need_recovery(void)
-{
- if (chromeos_on_legacy_firmware()) {
- /* Use fixed location to request recovery reboot. */
- struct chromeos_acpi_datum *chnv = &chromeos_acpi_if_data.chnv;
- chromeos_set_nvram_flag(chnv->cad_value,
- CHNV_RECOVERY_FLAG);
- return 0;
- }
-
- if (chromeos_nvram_buffer_available) {
- return chromeos_write_nvram(RECOVERY_OFFSET,
- VBNV_RECOVERY_RW_INVALID_OS);
- }
- return -EINVAL;
-}
-EXPORT_SYMBOL(chromeos_set_need_recovery);
-
-bool chromeos_initialized(void)
-{
- return chromeos_inited;
-}
-EXPORT_SYMBOL(chromeos_initialized);
-
-/*
- * Lifted from vboot_reference:firmware/lib/vboot_nvstorage.c and formatted.
- *
- * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A table-based
- * algorithm would be faster, but for only 15 bytes isn't worth the code size.
- */
-static u8 crc8(const u8 *data, int len)
-{
- unsigned crc = 0;
- int i, j;
-
- for (j = len; j; j--, data++) {
- crc ^= (*data << 8);
- for (i = 8; i; i--) {
- if (crc & 0x8000)
- crc ^= (0x1070 << 3);
- crc <<= 1;
- }
- }
- return (u8)(crc >> 8);
-}
-
-static int chromeos_write_nvram(unsigned offset, u8 value)
-{
- u8 nvram_buffer[MAX_NVRAM_BUFFER_SIZE];
- u8 new_crc;
- unsigned size;
- unsigned base;
-
- if (chromeos_read_nvram(nvram_buffer, sizeof(nvram_buffer)))
- return -ENODEV;
-
- size = chromeos_acpi_if_data.nv_size.cad_value;
- base = chromeos_acpi_if_data.nv_base.cad_value;;
-
- if (offset >= (size - 1))
- return -EINVAL;
-
- nvram_buffer[offset] = value;
- new_crc = crc8(nvram_buffer, size - 1);
-
- nvram_write_byte(base + offset, value);
- nvram_write_byte(base + size - 1, new_crc);
- return 0;
-}
-
-/*
- * read nvram buffer contents and verify it.
- * Return 0 on success and -1 on failure (uninitialized, or corrupted crc8
- * value). The passed in memory space is guaranteed to be large enough for the
- * nvram buffer contents.
- */
-static int chromeos_read_nvram(u8 *nvram_buffer, int buf_size)
-{
- int start, size, i;
-
- if (!chromeos_inited)
- return -1;
-
- start = chromeos_acpi_if_data.nv_base.cad_value;
- size = chromeos_acpi_if_data.nv_size.cad_value;
-
- if (size > buf_size) {
- pr_err("%s: buffer range exceeded\n", __func__);
- return -1;
- }
-
- for (i = 0; i < size; i++)
- nvram_buffer[i] = nvram_read_byte(start++);
-
- if (nvram_buffer[size - 1] != crc8(nvram_buffer, size - 1)) {
- pr_err("%s: NVRAM contents corrupted\n", __func__);
- return -1;
- }
- return 0;
-}
-
-static int __init chromeos_init(void)
-{
- u8 nvram_buffer[MAX_NVRAM_BUFFER_SIZE];
-
- if (!chromeos_acpi_if_data.switch_state.cad_is_set) {
- pr_err("Chrome OS platform not found\n");
- return -ENODEV;
- }
-
- chromeos_inited = true;
-
- if (chromeos_on_legacy_firmware()) {
- pr_info("Legacy ChromeOS firmware detected\n");
- return 0;
- }
-
- pr_info("ChromeOS firmware detected\n");
-
- /* check NVRAM buffer sanity */
- if (!chromeos_acpi_if_data.nv_base.cad_is_set ||
- !chromeos_acpi_if_data.nv_size.cad_is_set ||
- (chromeos_acpi_if_data.nv_size.cad_value > MAX_NVRAM_BUFFER_SIZE) ||
- chromeos_read_nvram(nvram_buffer, sizeof(nvram_buffer))) {
- pr_warning("Chrome NVram buffer not used\n");
- chromeos_nvram_buffer_available = false;
- } else {
- chromeos_nvram_buffer_available = true;
- }
-
- return 0;
-}
-subsys_initcall_sync(chromeos_init);
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/nvram.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
-#include "chromeos_acpi.h"
+#define CHNV_DEBUG_RESET_FLAG 0x40 /* flag for S3 reboot */
+#define CHNV_RECOVERY_FLAG 0x80 /* flag for recovery reboot */
-struct chromeos_acpi_if chromeos_acpi_if_data;
-EXPORT_SYMBOL_GPL(chromeos_acpi_if_data);
+#define CHSW_RECOVERY_FW 0x00000002 /* recovery button depressed */
+#define CHSW_RECOVERY_EC 0x00000004 /* recovery button depressed */
+#define CHSW_DEVELOPER_MODE 0x00000020 /* developer switch set */
+#define CHSW_WP 0x00000200 /* write-protect (optional) */
+
+/*
+ * Structure containing one ACPI exported integer along with the validity
+ * flag.
+ */
+struct chromeos_acpi_datum {
+ unsigned cad_value;
+ bool cad_is_set;
+};
+
+/*
+ * Structure containing the set of ACPI exported integers required by chromeos
+ * wrapper.
+ */
+struct chromeos_acpi_if {
+ struct chromeos_acpi_datum switch_state;
+
+ /* chnv is a single byte offset in nvram. exported by older firmware */
+ struct chromeos_acpi_datum chnv;
+
+ /* vbnv is an address range in nvram, exported by newer firmware */
+ struct chromeos_acpi_datum nv_base;
+ struct chromeos_acpi_datum nv_size;
+};
#define MY_LOGPREFIX "chromeos_acpi: "
#define MY_ERR KERN_ERR MY_LOGPREFIX
};
MODULE_DEVICE_TABLE(acpi, chromeos_device_ids);
+
static int chromeos_device_add(struct acpi_device *device);
static int chromeos_device_remove(struct acpi_device *device, int type);
+static struct chromeos_acpi_if chromeos_acpi_if_data;
static struct acpi_driver chromeos_acpi_driver = {
.name = "ChromeOS Device",
.class = "ChromeOS",
static struct chromeos_acpi_dev chromeos_acpi = { };
+static bool chromeos_on_legacy_firmware(void)
+{
+ /*
+ * Presense of the CHNV ACPI element implies running on a legacy
+ * firmware
+ */
+ return chromeos_acpi_if_data.chnv.cad_is_set;
+}
+
+/*
+ * This function operates on legacy BIOSes which do not export VBNV element
+ * through ACPI. These BIOSes use a fixed location in NVRAM to contain a
+ * bitmask of known flags.
+ *
+ * @flag - the bitmask to set, it is the responsibility of the caller to set
+ * the proper bits.
+ *
+ * returns 0 on success (is running in legacy mode and chnv is initialized) or
+ * -1 otherwise.
+ */
+static int chromeos_set_nvram_flag(u8 flag)
+{
+ u8 cur;
+ unsigned index = chromeos_acpi_if_data.chnv.cad_value;
+
+ if (!chromeos_on_legacy_firmware())
+ return -ENODEV;
+
+ cur = nvram_read_byte(index);
+
+ if ((cur & flag) != flag)
+ nvram_write_byte(cur | flag, index);
+ return 0;
+}
+
+int chromeos_legacy_set_need_recovery(void)
+{
+ return chromeos_set_nvram_flag(CHNV_RECOVERY_FLAG);
+}
+
+/*
+ * Read the nvram buffer contents into the user provided space.
+ *
+ * retrun number of bytes copied, or -1 on any error.
+ */
+int chromeos_platform_read_nvram(u8 *nvram_buffer, int buf_size)
+{
+
+ int base, size, i;
+
+ if (!chromeos_acpi_if_data.nv_base.cad_is_set ||
+ !chromeos_acpi_if_data.nv_size.cad_is_set) {
+ printk(MY_ERR "%s: NVRAM not configured!\n", __func__);
+ return -ENODEV;
+ }
+
+ base = chromeos_acpi_if_data.nv_base.cad_value;
+ size = chromeos_acpi_if_data.nv_size.cad_value;
+
+ if (buf_size < size) {
+ pr_err("%s: not enough room to read nvram (%d < %d)\n",
+ __func__, buf_size, size);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < size; i++)
+ nvram_buffer[i] = nvram_read_byte(base++);
+
+ return size;
+}
+
+int chromeos_platform_write_nvram(u8 *nvram_buffer, int buf_size)
+{
+ unsigned base, size, i;
+
+ if (!chromeos_acpi_if_data.nv_base.cad_is_set ||
+ !chromeos_acpi_if_data.nv_size.cad_is_set) {
+ printk(MY_ERR "%s: NVRAM not configured!\n", __func__);
+ return -ENODEV;
+ }
+
+ size = chromeos_acpi_if_data.nv_size.cad_value;
+ base = chromeos_acpi_if_data.nv_base.cad_value;
+
+ if (buf_size != size) {
+ printk(MY_ERR "%s: wrong buffer size (%d != %d)!\n", __func__,
+ buf_size, size);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < size; i++) {
+ u8 c;
+
+ c = nvram_read_byte(base + i);
+ if (c == nvram_buffer[i])
+ continue;
+ nvram_write_byte(nvram_buffer[i], base + i);
+ }
+ return 0;
+}
/*
* To show attribute value just access the container structure's `value'
chromeos_acpi.p_dev = NULL;
return ret;
}
- printk(MY_INFO "installed\n");
+ printk(MY_INFO "installed%s\n",
+ chromeos_on_legacy_firmware() ? " (legacy mode)" : "");
return 0;
}
+++ /dev/null
-#ifndef _DRIVERS_PLATFORM_X86_CHROMEOS_ACPI_H
-#define _DRIVERS_PLATFORM_X86_CHROMEOS_ACPI_H
-
-#include <linux/types.h>
-
-#define NVRAM_BYTES (128 - NVRAM_FIRST_BYTE) /* from drivers/char/nvram.c */
-
-#define CHNV_DEBUG_RESET_FLAG 0x40 /* flag for S3 reboot */
-#define CHNV_RECOVERY_FLAG 0x80 /* flag for recovery reboot */
-
-#define CHSW_RECOVERY_FW 0x00000002 /* recovery button depressed */
-#define CHSW_RECOVERY_EC 0x00000004 /* recovery button depressed */
-#define CHSW_DEVELOPER_MODE 0x00000020 /* developer switch set */
-#define CHSW_WP 0x00000200 /* write-protect (optional) */
-
-/*
- * Structure containing one ACPI exported integer along with the validity
- * flag.
- */
-struct chromeos_acpi_datum {
- unsigned cad_value;
- bool cad_is_set;
-};
-
-/*
- * Structure containing the set of ACPI exported integers required by chromeos
- * wrapper.
- */
-struct chromeos_acpi_if {
- struct chromeos_acpi_datum switch_state;
-
- /* chnv is a single byte offset in nvram. exported by older firmware */
- struct chromeos_acpi_datum chnv;
-
- /* vbnv is an address range in nvram, exported by newer firmware */
- struct chromeos_acpi_datum nv_base;
- struct chromeos_acpi_datum nv_size;
-};
-
-
-extern struct chromeos_acpi_if chromeos_acpi_if_data;
-
-#endif /* _DRIVERS_PLATFORM_X86_CHROMEOS_ACPI_H */
#include <linux/errno.h>
#include <linux/types.h>
+extern int chromeos_platform_read_nvram(u8 *nvram_buffer, int buf_size);
+extern int chromeos_platform_write_nvram(u8 *nvram_buffer, int buf_size);
+
#ifdef CONFIG_CHROMEOS
/*
* ChromeOS platform support code. Glue layer between higher level functions
* and per-platform firmware interfaces.
*/
-/* Checks to see if the current device is in devmode */
-extern bool chromeos_is_devmode(void);
-
/*
* Set the taint bit telling firmware that the currently running side needs
* recovery (or reinstall).
*/
extern int chromeos_set_need_recovery(void);
-extern u64 phys_window_base;
-
#else
-/* Stubbed-out versions so we can keep code common */
-static inline bool chromeos_is_devmode(void)
-{
- return true;
-}
-
static inline int chromeos_set_need_recovery(void)
{
return -ENODEV;