diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-04-10 13:50:29 -0700 |
---|---|---|
committer | Randall Spangler <rspangler@chromium.org> | 2012-04-10 14:09:40 -0700 |
commit | 322eebbae40c6e4450ab4867de31d56e37471436 (patch) | |
tree | 22957b3bdd4eef72730bb36a6b1aebd4b3a39002 /common | |
parent | eac723c3e5567a8c968e25773da9875bd1e66e1e (diff) | |
download | chrome-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.mk | 1 | ||||
-rw-r--r-- | common/eoption.c | 191 | ||||
-rw-r--r-- | common/main.c | 18 | ||||
-rw-r--r-- | common/pstore_commands.c | 19 |
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)) |