diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-06-12 13:12:04 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-06-12 15:56:35 -0700 |
commit | 801a90c3fcee004db153940810371b3d06e37b35 (patch) | |
tree | 1ae64279f7633ca156431fcb2a4cc0d004108883 | |
parent | 8c44e8b74d79a31a810391511fbe7c73f0bc59d4 (diff) | |
download | chrome-ec-801a90c3fcee004db153940810371b3d06e37b35.tar.gz |
Use EC LPC arbitration to prevent host writes to memmap space
Previously, the host could write to this space and corrupt the memmap data.
BUG=chrome-os-partner:10210
TEST=manual
From a root shell:
localhost ~ # io_read32 0x960
0x574e5553
localhost ~ # io_write32 0x960 0x1234
localhost ~ # io_read32 0x960
0x574e5553
That verifies that the EC is rejecting host writes on the memmap range
localhost ~ # ectool hello
EC says hello!
That verifies the host is still able to write to the user param range
Change-Id: I8c29571f439a14f308ed73f4c641264e17f944e9
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/25115
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r-- | board/link/board.h | 5 | ||||
-rw-r--r-- | chip/lm4/lpc.c | 33 |
2 files changed, 32 insertions, 6 deletions
diff --git a/board/link/board.h b/board/link/board.h index 2e985f95d9..6124bf921e 100644 --- a/board/link/board.h +++ b/board/link/board.h @@ -41,6 +41,7 @@ #define LPC_CH_CMD_DATA 2 /* Data for kernel/user-mode commands */ #define LPC_CH_KEYBOARD 3 /* 8042 keyboard emulation */ #define LPC_CH_USER 4 /* User-mode commands */ +#define LPC_CH_MEMMAP 5 /* Data for kernel/user-mode commands */ #define LPC_CH_COMX 7 /* UART emulation */ /* LPC pool offsets */ #define LPC_POOL_OFFS_KERNEL 0 /* Kernel commands - 0=in, 1=out */ @@ -48,7 +49,8 @@ #define LPC_POOL_OFFS_COMX 8 /* UART emulation range - 8-15 */ #define LPC_POOL_OFFS_KEYBOARD 16 /* Keyboard - 16=in, 17=out */ #define LPC_POOL_OFFS_USER 20 /* User commands - 20=in, 21=out */ -#define LPC_POOL_OFFS_CMD_DATA 512 /* Data range for commands - 512-1023 */ +#define LPC_POOL_OFFS_CMD_DATA 512 /* Data range for commands - 512-767 */ +#define LPC_POOL_OFFS_MEMMAP 768 /* Data range for commands - 768-1023 */ /* LPC pool data pointers */ #define LPC_POOL_KERNEL (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_KERNEL) #define LPC_POOL_PORT80 (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_PORT80) @@ -56,6 +58,7 @@ #define LPC_POOL_KEYBOARD (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_KEYBOARD) #define LPC_POOL_CMD_DATA (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_CMD_DATA) #define LPC_POOL_USER (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_USER) +#define LPC_POOL_MEMMAP (LM4_LPC_LPCPOOL + LPC_POOL_OFFS_MEMMAP) /* LPC COMx I/O address (in x86 I/O address space) */ #define LPC_COMX_ADDR 0x3f8 /* COM1 */ diff --git a/chip/lm4/lpc.c b/chip/lm4/lpc.c index c4f14214f9..fda63c7761 100644 --- a/chip/lm4/lpc.c +++ b/chip/lm4/lpc.c @@ -122,7 +122,7 @@ uint8_t *host_get_buffer(int slot) uint8_t *lpc_get_memmap_range(void) { - return (uint8_t *)LPC_POOL_CMD_DATA + EC_PARAM_SIZE * 2; + return (uint8_t *)LPC_POOL_MEMMAP; } @@ -445,14 +445,13 @@ static int lpc_init(void) /* Set LPC channel 2 to I/O address 0x800, range endpoint, - * arbitration disabled, pool bytes 512-1023. To access this from - * x86, use the following commands to set GEN_LPC2 and GEN_LPC3: + * arbitration disabled, pool bytes 512-767. To access this from + * x86, use the following command to set GEN_LPC2: * * pci_write32 0 0x1f 0 0x88 0x007c0801 - * pci_write32 0 0x1f 0 0x8c 0x007c0901 */ LM4_LPC_ADR(LPC_CH_CMD_DATA) = EC_LPC_ADDR_KERNEL_PARAM; - LM4_LPC_CTL(LPC_CH_CMD_DATA) = 0x801D | + LM4_LPC_CTL(LPC_CH_CMD_DATA) = 0x8019 | (LPC_POOL_OFFS_CMD_DATA << (5 - 1)); /* Set LPC channel 3 to I/O address 0x60 (data) / 0x64 (command), @@ -473,6 +472,15 @@ static int lpc_init(void) /* Unmask interrupt for host command writes */ LM4_LPC_LPCIM |= LM4_LPC_INT_MASK(LPC_CH_USER, 4); + /* Set LPC channel 5 to I/O address 0x900, range endpoint, + * arbitration enabled, pool bytes 768-1023. To access this from + * x86, use the following command to set GEN_LPC3: + * + * pci_write32 0 0x1f 0 0x8c 0x007c0901 + */ + LM4_LPC_ADR(LPC_CH_MEMMAP) = EC_LPC_ADDR_MEMMAP; + LM4_LPC_CTL(LPC_CH_MEMMAP) = 0x0019 | (LPC_POOL_OFFS_MEMMAP << (5 - 1)); + /* Set LPC channel 7 to COM port I/O address. Note that channel 7 * ignores the TYPE bit and is always an 8-byte range. */ LM4_LPC_ADR(LPC_CH_COMX) = LPC_COMX_ADDR; @@ -498,8 +506,23 @@ static int lpc_init(void) (1 << LPC_CH_CMD_DATA) | (1 << LPC_CH_KEYBOARD) | (1 << LPC_CH_USER) | + (1 << LPC_CH_MEMMAP) | (1 << LPC_CH_COMX); + /* + * Ensure the EC (slave) has control of the memory-mapped I/O space. + * Once the EC has won arbtration for the memory-mapped space, it will + * keep control of it until it writes the last byte in the space. + * (That never happens; we can't use the last byte in the space because + * ACPI can't see it anyway.) + */ + while (!(LM4_LPC_ST(LPC_CH_MEMMAP) & 0x10)) { + /* Clear HW1ST */ + LM4_LPC_ST(LPC_CH_MEMMAP) &= ~0x40; + /* Do a dummy slave write; this should cause SW1ST to be set */ + *LPC_POOL_MEMMAP = *LPC_POOL_MEMMAP; + } + /* Enable LPC interrupt */ task_enable_irq(LM4_IRQ_LPC); |