ec/system76: Support lockdown based on EC security state
Change-Id: I202c0607c2cdac1df59f42fb41735704dd5bd95c Signed-off-by: Jeremy Soller <jeremy@system76.com> Signed-off-by: Tim Crawford <tcrawford@system76.com>
This commit is contained in:
parent
beb8d7b318
commit
1967a764e0
@ -15,6 +15,11 @@ config EC_SYSTEM76_EC_DGPU
|
||||
bool
|
||||
default n
|
||||
|
||||
config EC_SYSTEM76_EC_LOCKDOWN
|
||||
depends on EC_SYSTEM76_EC
|
||||
bool
|
||||
default n
|
||||
|
||||
config EC_SYSTEM76_EC_OLED
|
||||
depends on EC_SYSTEM76_EC
|
||||
bool
|
||||
|
@ -4,6 +4,7 @@ ifeq ($(CONFIG_EC_SYSTEM76_EC),y)
|
||||
all-y += system76_ec.c
|
||||
|
||||
ramstage-y += smbios.c
|
||||
ramstage-$(CONFIG_EC_SYSTEM76_EC_LOCKDOWN) += lockdown.c
|
||||
|
||||
smm-$(CONFIG_DEBUG_SMI) += system76_ec.c
|
||||
|
||||
|
59
src/ec/system76/ec/lockdown.c
Normal file
59
src/ec/system76/ec/lockdown.c
Normal file
@ -0,0 +1,59 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include "system76_ec.h"
|
||||
#include <bootstate.h>
|
||||
#include <commonlib/region.h>
|
||||
#include <fmap.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
static int protect_region_by_name(const char *name)
|
||||
{
|
||||
int res;
|
||||
struct region region;
|
||||
|
||||
res = fmap_locate_area(name, ®ion);
|
||||
if (res < 0) {
|
||||
printk(BIOS_ERR, "fmap_locate_area '%s' failed: %d\n", name, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = spi_flash_ctrlr_protect_region(
|
||||
boot_device_spi_flash(),
|
||||
®ion,
|
||||
WRITE_PROTECT
|
||||
);
|
||||
if (res < 0) {
|
||||
printk(BIOS_ERR, "spi_flash_ctrlr_protect_region '%s' failed: %d\n", name, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
printk(BIOS_INFO, "protected '%s'\n", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lock(void *unused)
|
||||
{
|
||||
uint8_t state = SYSTEM76_EC_SECURITY_STATE_UNLOCK;
|
||||
if (!system76_ec_security_get(&state)) {
|
||||
printk(BIOS_INFO, "failed to get security state, assuming unlocked\n");
|
||||
state = SYSTEM76_EC_SECURITY_STATE_UNLOCK;
|
||||
}
|
||||
|
||||
printk(BIOS_INFO, "security state: %d\n", state);
|
||||
if (state != SYSTEM76_EC_SECURITY_STATE_UNLOCK) {
|
||||
// Protect WP_RO region, which should contain FMAP and COREBOOT
|
||||
protect_region_by_name("WP_RO");
|
||||
// Protect RW_MRC_CACHE region, this must be done after it is written
|
||||
protect_region_by_name("RW_MRC_CACHE");
|
||||
//TODO: protect entire flash except when in SMM?
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Keep in sync with mrc_cache.c
|
||||
*/
|
||||
#if CONFIG(MRC_WRITE_NV_LATE)
|
||||
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME_CHECK, BS_ON_EXIT, lock, NULL);
|
||||
#else
|
||||
BOOT_STATE_INIT_ENTRY(BS_DEV_RESOURCES, BS_ON_ENTRY, lock, NULL);
|
||||
#endif
|
@ -26,6 +26,9 @@
|
||||
#define CMD_PRINT_REG_LEN 3
|
||||
#define CMD_PRINT_REG_DATA 4
|
||||
|
||||
// Get security state command
|
||||
#define CMD_SECURITY_GET 20
|
||||
|
||||
static inline uint8_t system76_ec_read(uint8_t addr)
|
||||
{
|
||||
return inb(SYSTEM76_EC_BASE + (uint16_t)addr);
|
||||
@ -110,3 +113,9 @@ bool system76_ec_cmd(uint8_t cmd, const uint8_t *request_data,
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool system76_ec_security_get(uint8_t *state)
|
||||
{
|
||||
*state = SYSTEM76_EC_SECURITY_STATE_LOCK;
|
||||
return system76_ec_cmd(CMD_SECURITY_GET, NULL, 0, state, sizeof(*state));
|
||||
}
|
||||
|
@ -6,6 +6,15 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Default value, flashing is prevented, cannot be set with CMD_SECURITY_SET
|
||||
#define SYSTEM76_EC_SECURITY_STATE_LOCK 0
|
||||
// Flashing is allowed, cannot be set with CMD_SECURITY_SET
|
||||
#define SYSTEM76_EC_SECURITY_STATE_UNLOCK 1
|
||||
// Flashing will be prevented on the next reboot
|
||||
#define SYSTEM76_EC_SECURITY_STATE_PREPARE_LOCK 2
|
||||
// Flashing will be allowed on the next reboot
|
||||
#define SYSTEM76_EC_SECURITY_STATE_PREPARE_UNLOCK 3
|
||||
|
||||
/*
|
||||
* Send a command to the EC. request_data/request_size are the request payload,
|
||||
* request_data can be NULL if request_size is 0. reply_data/reply_size are
|
||||
@ -14,4 +23,6 @@
|
||||
bool system76_ec_cmd(uint8_t cmd, const uint8_t *request_data,
|
||||
uint8_t request_size, uint8_t *reply_data, uint8_t reply_size);
|
||||
|
||||
bool system76_ec_security_get(uint8_t *state);
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user