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
|
bool
|
||||||
default n
|
default n
|
||||||
|
|
||||||
|
config EC_SYSTEM76_EC_LOCKDOWN
|
||||||
|
depends on EC_SYSTEM76_EC
|
||||||
|
bool
|
||||||
|
default n
|
||||||
|
|
||||||
config EC_SYSTEM76_EC_OLED
|
config EC_SYSTEM76_EC_OLED
|
||||||
depends on EC_SYSTEM76_EC
|
depends on EC_SYSTEM76_EC
|
||||||
bool
|
bool
|
||||||
|
@ -4,6 +4,7 @@ ifeq ($(CONFIG_EC_SYSTEM76_EC),y)
|
|||||||
all-y += system76_ec.c
|
all-y += system76_ec.c
|
||||||
|
|
||||||
ramstage-y += smbios.c
|
ramstage-y += smbios.c
|
||||||
|
ramstage-$(CONFIG_EC_SYSTEM76_EC_LOCKDOWN) += lockdown.c
|
||||||
|
|
||||||
smm-$(CONFIG_DEBUG_SMI) += system76_ec.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_LEN 3
|
||||||
#define CMD_PRINT_REG_DATA 4
|
#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)
|
static inline uint8_t system76_ec_read(uint8_t addr)
|
||||||
{
|
{
|
||||||
return inb(SYSTEM76_EC_BASE + (uint16_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;
|
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 <stdbool.h>
|
||||||
#include <stdint.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,
|
* 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
|
* 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,
|
bool system76_ec_cmd(uint8_t cmd, const uint8_t *request_data,
|
||||||
uint8_t request_size, uint8_t *reply_data, uint8_t reply_size);
|
uint8_t request_size, uint8_t *reply_data, uint8_t reply_size);
|
||||||
|
|
||||||
|
bool system76_ec_security_get(uint8_t *state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user