b2e610011c
In order to support the physical recovery GPIO on sarien it needs to enable the option VBOOT_PHYSICAL_REC_SWITCH and set the GPIO number in the coreboot table appropriately so that depthcharge can correctly determine the GPIO number. The same is done for the write protect GPIO in this table. Additionally since we are reading a recovery request from H1 it needs to cache the result since H1 will only return true on the first request. All subsequent queries to H1 will not indicate recovery. Add a CAR global here to keep track of the state and only read it from H1 the first time. BUG=b:121380403 TEST=test_that DUT firmware_DevMode Change-Id: Ia816a2e285d3c2c3769b25fc5d20147abbc71421 Signed-off-by: Duncan Laurie <dlaurie@google.com> Reviewed-on: https://review.coreboot.org/c/31043 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
113 lines
2.9 KiB
C
113 lines
2.9 KiB
C
/*
|
|
* This file is part of the coreboot project.
|
|
*
|
|
* Copyright 2018 Google LLC
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#include <arch/acpi.h>
|
|
#include <arch/early_variables.h>
|
|
#include <boot/coreboot_tables.h>
|
|
#include <gpio.h>
|
|
#include <soc/gpio.h>
|
|
#include <variant/gpio.h>
|
|
#include <vendorcode/google/chromeos/chromeos.h>
|
|
#include <security/tpm/tss.h>
|
|
|
|
enum rec_mode_state {
|
|
REC_MODE_UNINITIALIZED,
|
|
REC_MODE_NOT_REQUESTED,
|
|
REC_MODE_REQUESTED,
|
|
};
|
|
static enum rec_mode_state saved_rec_mode CAR_GLOBAL;
|
|
|
|
void fill_lb_gpios(struct lb_gpios *gpios)
|
|
{
|
|
struct lb_gpio chromeos_gpios[] = {
|
|
{GPIO_PCH_WP, ACTIVE_HIGH, get_write_protect_state(),
|
|
"write protect"},
|
|
{GPIO_REC_MODE, ACTIVE_LOW, get_recovery_mode_switch(),
|
|
"recovery"},
|
|
{-1, ACTIVE_HIGH, get_lid_switch(), "lid"},
|
|
{-1, ACTIVE_HIGH, 0, "power"},
|
|
{-1, ACTIVE_HIGH, gfx_get_init_done(), "oprom"},
|
|
{-1, ACTIVE_HIGH, 0, "EC in RW"},
|
|
};
|
|
lb_add_gpios(gpios, chromeos_gpios, ARRAY_SIZE(chromeos_gpios));
|
|
}
|
|
|
|
static int cros_get_gpio_value(int type)
|
|
{
|
|
const struct cros_gpio *cros_gpios;
|
|
size_t i, num_gpios = 0;
|
|
|
|
cros_gpios = variant_cros_gpios(&num_gpios);
|
|
|
|
for (i = 0; i < num_gpios; i++) {
|
|
const struct cros_gpio *gpio = &cros_gpios[i];
|
|
if (gpio->type == type) {
|
|
int state = gpio_get(gpio->gpio_num);
|
|
if (gpio->polarity == CROS_GPIO_ACTIVE_LOW)
|
|
return !state;
|
|
else
|
|
return state;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void mainboard_chromeos_acpi_generate(void)
|
|
{
|
|
const struct cros_gpio *cros_gpios;
|
|
size_t num_gpios = 0;
|
|
|
|
cros_gpios = variant_cros_gpios(&num_gpios);
|
|
|
|
chromeos_acpi_gpio_generate(cros_gpios, num_gpios);
|
|
}
|
|
|
|
int get_write_protect_state(void)
|
|
{
|
|
return cros_get_gpio_value(CROS_GPIO_WP);
|
|
}
|
|
|
|
int get_recovery_mode_switch(void)
|
|
{
|
|
enum rec_mode_state state = car_get_var(saved_rec_mode);
|
|
uint8_t recovery_button_state = 0;
|
|
|
|
/* Check the global variable first. */
|
|
if (state == REC_MODE_NOT_REQUESTED)
|
|
return 0;
|
|
else if (state == REC_MODE_REQUESTED)
|
|
return 1;
|
|
|
|
state = REC_MODE_NOT_REQUESTED;
|
|
|
|
/* Read state from the GPIO controlled by servo. */
|
|
if (cros_get_gpio_value(CROS_GPIO_REC))
|
|
state = REC_MODE_REQUESTED;
|
|
/* Read one-time recovery request from cr50. */
|
|
else if (tlcl_cr50_get_recovery_button(&recovery_button_state)
|
|
== TPM_SUCCESS)
|
|
state = recovery_button_state ?
|
|
REC_MODE_REQUESTED : REC_MODE_NOT_REQUESTED;
|
|
|
|
/* Store the state in case this is called again in verstage. */
|
|
car_set_var(saved_rec_mode, state);
|
|
|
|
return state == REC_MODE_REQUESTED;
|
|
}
|
|
|
|
int get_lid_switch(void)
|
|
{
|
|
return 1;
|
|
}
|