Skip to content

Commit 206bb54

Browse files
committed
ec/system76: Support lockdown based on EC security state
Change-Id: I202c0607c2cdac1df59f42fb41735704dd5bd95c Signed-off-by: Jeremy Soller <[email protected]> Signed-off-by: Tim Crawford <[email protected]>
1 parent 0779f3c commit 206bb54

File tree

5 files changed

+85
-0
lines changed

5 files changed

+85
-0
lines changed

src/ec/system76/ec/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ config EC_SYSTEM76_EC_DGPU
1313
bool
1414
default n
1515

16+
config EC_SYSTEM76_EC_LOCKDOWN
17+
depends on EC_SYSTEM76_EC
18+
bool
19+
default n
20+
1621
config EC_SYSTEM76_EC_OLED
1722
depends on EC_SYSTEM76_EC
1823
bool

src/ec/system76/ec/Makefile.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ifeq ($(CONFIG_EC_SYSTEM76_EC),y)
44
all-y += system76_ec.c
55

66
ramstage-y += smbios.c
7+
ramstage-$(CONFIG_EC_SYSTEM76_EC_LOCKDOWN) += lockdown.c
78

89
smm-$(CONFIG_DEBUG_SMI) += system76_ec.c
910

src/ec/system76/ec/lockdown.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
3+
#include "system76_ec.h"
4+
#include <bootstate.h>
5+
#include <commonlib/region.h>
6+
#include <fmap.h>
7+
#include <spi_flash.h>
8+
9+
static int protect_region_by_name(const char *name)
10+
{
11+
int res;
12+
struct region region;
13+
14+
res = fmap_locate_area(name, &region);
15+
if (res < 0) {
16+
printk(BIOS_ERR, "fmap_locate_area '%s' failed: %d\n", name, res);
17+
return res;
18+
}
19+
20+
res = spi_flash_ctrlr_protect_region(
21+
boot_device_spi_flash(),
22+
&region,
23+
WRITE_PROTECT
24+
);
25+
if (res < 0) {
26+
printk(BIOS_ERR, "spi_flash_ctrlr_protect_region '%s' failed: %d\n", name, res);
27+
return res;
28+
}
29+
30+
printk(BIOS_INFO, "protected '%s'\n", name);
31+
return 0;
32+
}
33+
34+
static void lock(void *unused)
35+
{
36+
uint8_t state = SYSTEM76_EC_SECURITY_STATE_UNLOCK;
37+
if (!system76_ec_security_get(&state)) {
38+
printk(BIOS_INFO, "failed to get security state, assuming unlocked\n");
39+
state = SYSTEM76_EC_SECURITY_STATE_UNLOCK;
40+
}
41+
42+
printk(BIOS_INFO, "security state: %d\n", state);
43+
if (state != SYSTEM76_EC_SECURITY_STATE_UNLOCK) {
44+
// Protect WP_RO region, which should contain FMAP and COREBOOT
45+
protect_region_by_name("WP_RO");
46+
// Protect RW_MRC_CACHE region, this must be done after it is written
47+
protect_region_by_name("RW_MRC_CACHE");
48+
//TODO: protect entire flash except when in SMM?
49+
}
50+
}
51+
52+
/*
53+
* Keep in sync with mrc_cache.c
54+
*/
55+
#if CONFIG(MRC_WRITE_NV_LATE)
56+
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME_CHECK, BS_ON_EXIT, lock, NULL);
57+
#else
58+
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, lock, NULL);
59+
#endif

src/ec/system76/ec/system76_ec.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
#define CMD_PRINT_REG_LEN 3
2727
#define CMD_PRINT_REG_DATA 4
2828

29+
// Get security state command
30+
#define CMD_SECURITY_GET 20
31+
2932
static inline uint8_t system76_ec_read(uint8_t addr)
3033
{
3134
return inb(SYSTEM76_EC_BASE + (uint16_t)addr);
@@ -110,3 +113,9 @@ bool system76_ec_cmd(uint8_t cmd, const uint8_t *request_data,
110113

111114
return ret;
112115
}
116+
117+
bool system76_ec_security_get(uint8_t *state)
118+
{
119+
*state = SYSTEM76_EC_SECURITY_STATE_LOCK;
120+
return system76_ec_cmd(CMD_SECURITY_GET, NULL, 0, state, sizeof(*state));
121+
}

src/ec/system76/ec/system76_ec.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
#include <stdbool.h>
77
#include <stdint.h>
88

9+
// Default value, flashing is prevented, cannot be set with CMD_SECURITY_SET
10+
#define SYSTEM76_EC_SECURITY_STATE_LOCK 0
11+
// Flashing is allowed, cannot be set with CMD_SECURITY_SET
12+
#define SYSTEM76_EC_SECURITY_STATE_UNLOCK 1
13+
// Flashing will be prevented on the next reboot
14+
#define SYSTEM76_EC_SECURITY_STATE_PREPARE_LOCK 2
15+
// Flashing will be allowed on the next reboot
16+
#define SYSTEM76_EC_SECURITY_STATE_PREPARE_UNLOCK 3
17+
918
/*
1019
* Send a command to the EC. request_data/request_size are the request payload,
1120
* request_data can be NULL if request_size is 0. reply_data/reply_size are
@@ -14,4 +23,6 @@
1423
bool system76_ec_cmd(uint8_t cmd, const uint8_t *request_data,
1524
uint8_t request_size, uint8_t *reply_data, uint8_t reply_size);
1625

26+
bool system76_ec_security_get(uint8_t *state);
27+
1728
#endif

0 commit comments

Comments
 (0)