summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-04-10 13:50:29 -0700
committerRandall Spangler <rspangler@chromium.org>2012-04-10 14:09:40 -0700
commit322eebbae40c6e4450ab4867de31d56e37471436 (patch)
tree22957b3bdd4eef72730bb36a6b1aebd4b3a39002 /common
parenteac723c3e5567a8c968e25773da9875bd1e66e1e (diff)
downloadchrome-ec-322eebbae40c6e4450ab4867de31d56e37471436.tar.gz
Add fake developer switch
Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:8884 TEST=manual optget fake_dev_switch --> 0 optset fake_dev_switch 1 optget fake_dev_switch --> 1 optset fake_dev_switch 0 optget fake_dev_switch --> 0 Reboot by holding ESC+D and tapping power optget fake_dev_switch --> 1 Reboot by holding ESC+F and tapping power optget fake_dev_switch --> 0 Change-Id: Iccb3bc8b3d571e551e204892769efc4161858055
Diffstat (limited to 'common')
-rw-r--r--common/build.mk1
-rw-r--r--common/eoption.c191
-rw-r--r--common/main.c18
-rw-r--r--common/pstore_commands.c19
4 files changed, 211 insertions, 18 deletions
diff --git a/common/build.mk b/common/build.mk
index 0cb7c401e7..c79732ad42 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -10,6 +10,7 @@ common-y+=memory_commands.o shared_mem.o system_common.o
common-y+=gpio_commands.o version.o
common-$(CONFIG_BATTERY_ATL706486)+=battery_atl706486.o
common-$(CONFIG_CHARGER_BQ24725)+=charger_bq24725.o
+common-$(CONFIG_EOPTION)+=eoption.o
common-$(CONFIG_FLASH)+=flash_common.o flash_commands.o
common-$(CONFIG_LIGHTBAR)+=lightbar.o
common-$(CONFIG_LPC)+=port80.o host_event_commands.o
diff --git a/common/eoption.c b/common/eoption.c
new file mode 100644
index 0000000000..cf70fd537d
--- /dev/null
+++ b/common/eoption.c
@@ -0,0 +1,191 @@
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Persistent EC options stored in EEPROM */
+
+#include "board.h"
+#include "console.h"
+#include "eeprom.h"
+#include "eoption.h"
+#include "uart.h"
+#include "util.h"
+
+#define EOPTION_MAGIC 0x456f /* Magic number for header 'Eo' */
+#define EOPTION_VERSION_CURRENT 1 /* Current version of options data */
+
+struct eoption_bool_data {
+ int offset; /* Word offset of option */
+ int mask; /* Option mask within byte */
+ const char *name; /* Option name */
+};
+
+
+/* Word offsets inside the EOPTION EEPROM block */
+enum block_offsets {
+ OFFSET_HEADER = 0,
+ OFFSET_BOOL0,
+};
+
+
+/* Boolean options. Must be in the same order as enum eoption_bool, and must
+ * be terminated by an entry with a NULL name. */
+static const struct eoption_bool_data bool_opts[] = {
+ {OFFSET_BOOL0, (1 << 0), "fake_dev_switch"},
+ {0, 0, NULL},
+};
+
+
+/* Read a uint32_t from the specified EEPROM *word* offset. */
+static int read32(int offset, uint32_t *dest)
+{
+ return eeprom_read(EEPROM_BLOCK_EOPTION, offset * 4, sizeof(uint32_t),
+ (char *)dest);
+}
+
+
+/* Write a uint32_t to the specified EEPROM *word* offset. */
+static int write32(int offset, uint32_t v)
+{
+ return eeprom_write(EEPROM_BLOCK_EOPTION, offset * 4, sizeof(v),
+ (char *)&v);
+}
+
+
+int eoption_get_bool(enum eoption_bool opt)
+{
+ const struct eoption_bool_data *d = bool_opts + opt;
+ uint32_t v = 0;
+
+ read32(d->offset, &v);
+ return v & d->mask ? 1 : 0;
+}
+
+
+int eoption_set_bool(enum eoption_bool opt, int value)
+{
+ const struct eoption_bool_data *d = bool_opts + opt;
+ uint32_t v;
+ int rv;
+
+ rv = read32(d->offset, &v);
+ if (rv != EC_SUCCESS)
+ return rv;
+
+ if (value)
+ v |= d->mask;
+ else
+ v &= ~d->mask;
+
+ return write32(d->offset, v);
+}
+
+
+/* Find an option by name. Returns the option index, or -1 if no match. */
+static int find_option_by_name(const char *name,
+ const struct eoption_bool_data *d)
+{
+ int i;
+
+ if (!name || !*name)
+ return -1;
+
+ for (i = 0; d->name; i++, d++) {
+ if (!strcasecmp(name, d->name))
+ return i;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+/* Initialization */
+
+int eoption_init(void)
+{
+ uint32_t v;
+ int version;
+
+ /* Initialize EEPROM if necessary */
+ read32(OFFSET_HEADER, &v);
+
+ /* Check header */
+ if (v >> 16 != EOPTION_MAGIC)
+ v = EOPTION_MAGIC << 16; /* (implicitly sets version=0) */
+
+ version = (v >> 8) & 0xff;
+ if (version == EOPTION_VERSION_CURRENT)
+ return EC_SUCCESS;
+
+ /* TODO: should have a CRC if we start using this for real
+ * (non-debugging) options. */
+
+ /* Initialize fields which weren't set in previous versions */
+ if (version < 1)
+ write32(OFFSET_BOOL0, 0);
+
+ /* Update the header */
+ v = (v & ~0xff00) | (EOPTION_VERSION_CURRENT << 8);
+ return write32(OFFSET_HEADER, v);
+}
+
+/*****************************************************************************/
+/* Console commands */
+
+static int command_eoption_get(int argc, char **argv)
+{
+ const struct eoption_bool_data *d;
+ int i;
+
+ /* If a signal is specified, print only that one */
+ if (argc == 2) {
+ i = find_option_by_name(argv[1], bool_opts);
+ if (i == -1) {
+ uart_puts("Unknown option.\n");
+ return EC_ERROR_INVAL;
+ }
+ d = bool_opts + i;
+ uart_printf(" %d %s\n", eoption_get_bool(i), d->name);
+ return EC_SUCCESS;
+ }
+
+ /* Otherwise print them all */
+ uart_puts("Boolean options:\n");
+ for (i = 0, d = bool_opts; d->name; i++, d++) {
+ uart_printf(" %d %s\n", eoption_get_bool(i), d->name);
+
+ /* We have enough options that we'll overflow the output buffer
+ * without flushing */
+ uart_flush_output();
+ }
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(optget, command_eoption_get);
+
+
+static int command_eoption_set(int argc, char **argv)
+{
+ char *e;
+ int v, i;
+
+ if (argc < 3) {
+ uart_puts("Usage: optset <option> <value>\n");
+ return EC_ERROR_INVAL;
+ }
+
+ v = strtoi(argv[2], &e, 0);
+ if (*e) {
+ uart_puts("Invalid value.\n");
+ return EC_ERROR_INVAL;
+ }
+
+ i = find_option_by_name(argv[1], bool_opts);
+ if (i != -1) {
+ return eoption_set_bool(i, v);
+ } else {
+ uart_puts("Unknown option.\n");
+ return EC_ERROR_INVAL;
+ }
+}
+DECLARE_CONSOLE_COMMAND(optset, command_eoption_set);
diff --git a/common/main.c b/common/main.c
index 52c26c2cc9..95a0298a4b 100644
--- a/common/main.c
+++ b/common/main.c
@@ -12,6 +12,7 @@
#include "config.h"
#include "console.h"
#include "eeprom.h"
+#include "eoption.h"
#include "flash.h"
#include "gpio.h"
#include "i2c.h"
@@ -89,17 +90,24 @@ int main(void)
timer_init();
/* Verified boot needs to read the initial keyboard state and EEPROM
- * contents. */
-#ifdef CONFIG_TASK_KEYSCAN
- keyboard_scan_init();
-#endif
+ * contents. EEPROM must be up first, so keyboard_scan can toggle
+ * debugging settings via keys held at boot. */
#ifdef CONFIG_EEPROM
eeprom_init();
#endif
+#ifdef CONFIG_EOPTION
+ eoption_init();
+#endif
+#ifdef CONFIG_TASK_KEYSCAN
+ keyboard_scan_init();
+#endif
/* Verified boot initialization. This may jump to another image, which
* will need to reconfigure / reinitialize the system, so as little as
- * possible should be done above this step. */
+ * possible should be done above this step.
+ *
+ * Note that steps above here may be done TWICE per boot, once in the
+ * RO image and once in the RW image. */
vboot_init();
system_init();
diff --git a/common/pstore_commands.c b/common/pstore_commands.c
index 49ffa47a99..489e554941 100644
--- a/common/pstore_commands.c
+++ b/common/pstore_commands.c
@@ -11,13 +11,6 @@
#include "uart.h"
#include "util.h"
-/* TODO: move these to board.h */
-#ifdef CONFIG_PSTORE
-/* Start block and block count for host persistent storage in EC EEPROM */
-#define PSTORE_EEPROM_BLOCK_START 16
-#define PSTORE_EEPROM_BLOCK_COUNT 16
-#endif
-
enum lpc_status pstore_command_get_info(uint8_t *data)
{
struct lpc_response_pstore_info *r =
@@ -26,10 +19,10 @@ enum lpc_status pstore_command_get_info(uint8_t *data)
uart_printf("ee block size=%d, count=%d\n",
eeprom_get_block_size(), eeprom_get_block_count());
- ASSERT(PSTORE_EEPROM_BLOCK_START + PSTORE_EEPROM_BLOCK_COUNT <=
+ ASSERT(EEPROM_BLOCK_START_PSTORE + EEPROM_BLOCK_COUNT_PSTORE <=
eeprom_get_block_count());
- r->pstore_size = PSTORE_EEPROM_BLOCK_COUNT * eeprom_get_block_size();
+ r->pstore_size = EEPROM_BLOCK_COUNT_PSTORE * eeprom_get_block_size();
r->access_size = sizeof(uint32_t);
return EC_LPC_RESULT_SUCCESS;
}
@@ -44,7 +37,7 @@ enum lpc_status pstore_command_read(uint8_t *data)
(struct lpc_response_pstore_read *)data;
char *dest = r->data;
int block_size = eeprom_get_block_size();
- int block = p->offset / block_size + PSTORE_EEPROM_BLOCK_COUNT;
+ int block = p->offset / block_size + EEPROM_BLOCK_COUNT_PSTORE;
int offset = p->offset % block_size;
int bytes_left = p->size;
@@ -56,7 +49,7 @@ enum lpc_status pstore_command_read(uint8_t *data)
int bytes_this = MIN(bytes_left, block_size - offset);
if (block >=
- PSTORE_EEPROM_BLOCK_START + PSTORE_EEPROM_BLOCK_COUNT)
+ EEPROM_BLOCK_START_PSTORE + EEPROM_BLOCK_COUNT_PSTORE)
return EC_LPC_RESULT_ERROR;
if (eeprom_read(block, offset, bytes_this, dest))
@@ -81,7 +74,7 @@ enum lpc_status pstore_command_write(uint8_t *data)
const char *src = p->data;
int block_size = eeprom_get_block_size();
- int block = p->offset / block_size + PSTORE_EEPROM_BLOCK_COUNT;
+ int block = p->offset / block_size + EEPROM_BLOCK_COUNT_PSTORE;
int offset = p->offset % block_size;
int bytes_left = p->size;
@@ -93,7 +86,7 @@ enum lpc_status pstore_command_write(uint8_t *data)
int bytes_this = MIN(bytes_left, block_size - offset);
if (block >=
- PSTORE_EEPROM_BLOCK_START + PSTORE_EEPROM_BLOCK_COUNT)
+ EEPROM_BLOCK_START_PSTORE + EEPROM_BLOCK_COUNT_PSTORE)
return EC_LPC_RESULT_ERROR;
if (eeprom_write(block, offset, bytes_this, src))