Add OTP support

One Time Programmable memory can be used to store permanent data like
serial numbers.
Reorganize the code to support writing serial number to OTP, in
addition to pstate (if using its own memory bank) or autogenerate from
unique id (hammer).

+ Add CONFIG_OTP to enable OTP code
+ Add CONFIG_SERIALNO_LEN to indicate the size of the serial number
string.  Currently set to 28, when USB serial number is needed.
+ Expose flash_read|write_pstate_serial and add otp_read|write_serail,
remove more generic flash_read|write_serial.
+ Make board_read|write_serial generic, declared outside of USB subsystem.

Priority order to read|write serial string:
- board definition (like hammer)
- pstate location, if stored in its private memory bank
- otp area
If none of these methods are available, a compilation error is raised.

BUG=chromium:746471
BRANCH=none
TEST=compile

Change-Id: I3d16125a6c0f424fb30e38123e63cf074b3cb2d3
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/580289
Reviewed-by: Nick Sanders <nsanders@chromium.org>
This commit is contained in:
Gwendal Grignou
2017-07-20 09:48:50 -07:00
committed by chrome-bot
parent 734ebcbbb4
commit 1b25735b73
11 changed files with 120 additions and 61 deletions

View File

@@ -172,7 +172,7 @@ int board_get_entropy(void *buffer, int len)
*/
const char *board_read_serial(void)
{
static char str[USB_STRING_LEN];
static char str[CONFIG_SERIALNO_LEN];
if (str[0] == '\0') {
uint8_t *id;
@@ -188,3 +188,9 @@ const char *board_read_serial(void)
return str;
}
int board_write_serial(const char *serialno)
{
return 0;
}

View File

@@ -1434,7 +1434,7 @@ static int usb_set_serial(const char *serialno)
return EC_ERROR_INVAL;
/* Convert into unicode usb string desc. */
for (i = 0; i < USB_STRING_LEN; i++) {
for (i = 0; i < CONFIG_SERIALNO_LEN; i++) {
sd->_data[i] = serialno[i];
if (serialno[i] == 0)
break;
@@ -1460,7 +1460,7 @@ DECLARE_HOOK(HOOK_INIT, usb_load_serialno, HOOK_PRIO_DEFAULT - 1);
static int command_serialno(int argc, char **argv)
{
struct usb_string_desc *sd = usb_serialno_desc;
char buf[USB_STRING_LEN];
char buf[CONFIG_SERIALNO_LEN];
int rv = EC_SUCCESS;
int i;
@@ -1469,7 +1469,7 @@ static int command_serialno(int argc, char **argv)
rv = usb_set_serial(argv[1]);
}
for (i = 0; i < USB_STRING_LEN; i++)
for (i = 0; i < CONFIG_SERIALNO_LEN; i++)
buf[i] = sd->_data[i];
ccprintf("Serial number: %s\n", buf);
return rv;

View File

@@ -645,7 +645,7 @@ static int usb_set_serial(const char *serialno)
return EC_ERROR_INVAL;
/* Convert into unicode usb string desc. */
for (i = 0; i < USB_STRING_LEN; i++) {
for (i = 0; i < CONFIG_SERIALNO_LEN; i++) {
sd->_data[i] = serialno[i];
if (serialno[i] == 0)
break;
@@ -657,13 +657,6 @@ static int usb_set_serial(const char *serialno)
return EC_SUCCESS;
}
/* By default, read serial number from flash, can be overridden. */
__attribute__((weak))
const char *board_read_serial(void)
{
return flash_read_serial();
}
/* Retrieve serial number from pstate flash. */
static int usb_load_serial(void)
{
@@ -687,7 +680,7 @@ static int usb_save_serial(const char *serialno)
return EC_ERROR_INVAL;
/* Save this new serial number to flash. */
rv = flash_write_serial(serialno);
rv = board_write_serial(serialno);
if (rv)
return rv;
@@ -699,7 +692,7 @@ static int usb_save_serial(const char *serialno)
static int command_serialno(int argc, char **argv)
{
struct usb_string_desc *sd = usb_serialno_desc;
char buf[USB_STRING_LEN];
char buf[CONFIG_SERIALNO_LEN];
int rv = EC_SUCCESS;
int i;
@@ -716,7 +709,7 @@ static int command_serialno(int argc, char **argv)
return EC_ERROR_INVAL;
}
for (i = 0; i < USB_STRING_LEN; i++)
for (i = 0; i < CONFIG_SERIALNO_LEN; i++)
buf[i] = sd->_data[i];
ccprintf("Serial number: %s\n", buf);
return rv;
@@ -725,4 +718,4 @@ static int command_serialno(int argc, char **argv)
DECLARE_CONSOLE_COMMAND(serialno, command_serialno,
"load/set [value]",
"Read and write USB serial number");
#endif
#endif /* CONFIG_USB_SERIALNO */

View File

@@ -1359,7 +1359,7 @@ static int usb_set_serial(const char *serialno)
return EC_ERROR_INVAL;
/* Convert into unicode usb string desc. */
for (i = 0; i < USB_STRING_LEN; i++) {
for (i = 0; i < CONFIG_SERIALNO_LEN; i++) {
sd->_data[i] = serialno[i];
if (serialno[i] == 0)
break;
@@ -1371,13 +1371,6 @@ static int usb_set_serial(const char *serialno)
return EC_SUCCESS;
}
/* By default, read serial number from flash, can be overridden. */
__attribute__((weak))
const char *board_read_serial(void)
{
return flash_read_serial();
}
/* Retrieve serial number from pstate flash. */
static int usb_load_serial(void)
{
@@ -1392,7 +1385,6 @@ static int usb_load_serial(void)
return rv;
}
/* Save serial number into pstate region. */
static int usb_save_serial(const char *serialno)
{
@@ -1402,7 +1394,7 @@ static int usb_save_serial(const char *serialno)
return EC_ERROR_INVAL;
/* Save this new serial number to flash. */
rv = flash_write_serial(serialno);
rv = board_write_serial(serialno);
if (rv)
return rv;
@@ -1414,7 +1406,7 @@ static int usb_save_serial(const char *serialno)
static int command_serialno(int argc, char **argv)
{
struct usb_string_desc *sd = usb_serialno_desc;
char buf[USB_STRING_LEN];
char buf[CONFIG_SERIALNO_LEN];
int rv = EC_SUCCESS;
int i;
@@ -1431,7 +1423,7 @@ static int command_serialno(int argc, char **argv)
return EC_ERROR_INVAL;
}
for (i = 0; i < USB_STRING_LEN; i++)
for (i = 0; i < CONFIG_SERIALNO_LEN; i++)
buf[i] = sd->_data[i];
ccprintf("Serial number: %s\n", buf);
return rv;
@@ -1440,5 +1432,4 @@ static int command_serialno(int argc, char **argv)
DECLARE_CONSOLE_COMMAND(serialno, command_serialno,
"load/set [value]",
"Read and write USB serial number");
#endif
#endif /* CONFIG_USB_SERIALNO */

View File

@@ -11,6 +11,7 @@
#include "gpio.h"
#include "hooks.h"
#include "host_command.h"
#include "otp.h"
#include "shared_mem.h"
#include "system.h"
#include "util.h"
@@ -39,7 +40,6 @@
/* NOTE: It's not expected that RO and RW will support
* differing PSTATE versions. */
#define PERSIST_STATE_VERSION 3 /* Expected persist_state.version */
#define SERIALNO_MAX 28
/* Flags for persist_state.flags */
/* Protect persist state and RO firmware at boot */
@@ -52,7 +52,11 @@ struct persist_state {
uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
uint8_t valid_fields; /* Flags for valid data. */
uint8_t reserved; /* Reserved; set 0 */
uint8_t serialno[SERIALNO_MAX]; /* Serial number. */
#ifdef CONFIG_SERIALNO_LEN
uint8_t serialno[CONFIG_SERIALNO_LEN]; /* Serial number. */
#else
uint8_t padding[4 % CONFIG_FLASH_WRITE_SIZE];
#endif
};
/* written with flash_physical_write, need to respect alignment constraints */
#ifndef CHIP_FAMILY_STM32L /* STM32L1xx is somewhat lying to us */
@@ -216,10 +220,11 @@ static uint32_t flash_read_pstate(void)
}
}
#ifdef CONFIG_SERIALNO_LEN
/**
* Read and return persistent serial number.
*/
static const char *flash_read_pstate_serial(void)
const char *flash_read_pstate_serial(void)
{
const struct persist_state *pstate =
(const struct persist_state *)
@@ -230,8 +235,9 @@ static const char *flash_read_pstate_serial(void)
return (const char *)(pstate->serialno);
}
return 0;
return NULL;
}
#endif
/**
* Write persistent state after erasing.
@@ -312,13 +318,14 @@ static int flash_write_pstate(uint32_t flags)
return flash_write_pstate_data(&newpstate);
}
#ifdef CONFIG_SERIALNO_LEN
/**
* Write persistent serial number to pstate, erasing if necessary.
*
* @param serialno New iascii serial number to set in pstate.
* @return EC_SUCCESS, or nonzero if error.
*/
static int flash_write_pstate_serial(const char *serialno)
int flash_write_pstate_serial(const char *serialno)
{
int i;
struct persist_state newpstate;
@@ -335,17 +342,18 @@ static int flash_write_pstate_serial(const char *serialno)
validate_pstate_struct(&newpstate);
/* Copy in serialno. */
for (i = 0; i < SERIALNO_MAX - 1; i++) {
for (i = 0; i < CONFIG_SERIALNO_LEN - 1; i++) {
newpstate.serialno[i] = serialno[i];
if (serialno[i] == 0)
break;
}
for (; i < SERIALNO_MAX; i++)
for (; i < CONFIG_SERIALNO_LEN; i++)
newpstate.serialno[i] = 0;
newpstate.valid_fields |= PSTATE_VALID_SERIALNO;
return flash_write_pstate_data(&newpstate);
}
#endif
@@ -515,24 +523,6 @@ int flash_erase(int offset, int size)
return flash_physical_erase(offset, size);
}
const char *flash_read_serial(void)
{
#if defined(CONFIG_FLASH_PSTATE) && defined(CONFIG_FLASH_PSTATE_BANK)
return flash_read_pstate_serial();
#else
return 0;
#endif
}
int flash_write_serial(const char *serialno)
{
#if defined(CONFIG_FLASH_PSTATE) && defined(CONFIG_FLASH_PSTATE_BANK)
return flash_write_pstate_serial(serialno);
#else
return EC_ERROR_UNIMPLEMENTED;
#endif
}
int flash_protect_at_boot(uint32_t new_flags)
{
#ifdef CONFIG_FLASH_PSTATE

View File

@@ -17,6 +17,7 @@
#include "host_command.h"
#include "i2c.h"
#include "lpc.h"
#include "otp.h"
#include "rwsig.h"
#include "spi_flash.h"
#ifdef CONFIG_MPU
@@ -1321,3 +1322,34 @@ int system_can_boot_ap(void)
return power_good;
}
#ifdef CONFIG_SERIALNO_LEN
/* By default, read serial number from flash, can be overridden. */
#if defined(CONFIG_FLASH_PSTATE) && defined(CONFIG_FLASH_PSTATE_BANK)
__attribute__((weak))
const char *board_read_serial(void)
{
return flash_read_pstate_serial();
}
#elif defined(CONFIG_OTP)
__attribute__((weak))
const char *board_read_serial(void)
{
return otp_read_serial();
}
#endif
#if defined(CONFIG_FLASH_PSTATE) && defined(CONFIG_FLASH_PSTATE_BANK)
__attribute__((weak))
int board_write_serial(const char *serialno)
{
return flash_write_pstate_serial(serialno);
}
#elif defined(CONFIG_OTP)
__attribute__((weak))
int board_write_serial(const char *serialno)
{
return otp_write_serial(serialno);
}
#endif
#endif /* CONFIG_SERIALNO_LEN */

View File

@@ -1815,6 +1815,9 @@
/* Support one-wire interface */
#undef CONFIG_ONEWIRE
/* Support One Time Protection structure */
#undef CONFIG_OTP
/* Support PECI interface to x86 processor */
#undef CONFIG_PECI
@@ -2001,6 +2004,9 @@
#undef CONFIG_RW_SIG_ADDR
#undef CONFIG_RW_SIG_SIZE
/* Size of the serial number if needed */
#undef CONFIG_SERIALNO_LEN
/****************************************************************************/
/* Shared objects library. */
@@ -2940,4 +2946,8 @@
#error "CONFIG_AUX_TIMER_PERIOD_MS must be at least 2x HOOK_TICK_INTERVAL_MS"
#endif
#ifdef CONFIG_USB_SERIALNO
#define CONFIG_SERIALNO_LEN 28
#endif
#endif /* __CROS_EC_CONFIG_H */

View File

@@ -320,17 +320,18 @@ int flash_set_protect(uint32_t mask, uint32_t flags);
* Get the serial number from flash.
*
* @return char * ascii serial number string.
* NULL if error.
*/
const char *flash_read_serial(void);
const char *flash_read_pstate_serial(void);
/**
* Set the serial number in flash.
*
* @param serialno ascii serial number string < 30 char.
* @param serialno ascii serial number string.
*
* @return success status.
*/
int flash_write_serial(const char *serialno);
int flash_write_pstate_serial(const char *serialno);
/**
* Lock or unlock HW necessary for mapped storage read.

32
include/otp.h Normal file
View File

@@ -0,0 +1,32 @@
/* Copyright 2017 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* OTP memory module for Chrome EC */
#ifndef __CROS_EC_OTP_H
#define __CROS_EC_OTP_H
/*
* OTP: One Time Programable memory is used for storing persistent data.
*/
/**
* Set the serial number in OTP memory.
*
* @param serialno ascii serial number string.
*
* @return success status.
*/
int otp_write_serial(const char *serialno);
/**
* Get the serial number from flash.
*
* @return char * ascii serial number string.
* NULL if error.
*/
const char *otp_read_serial(void);
#endif /* __CROS_EC_OTP_H */

View File

@@ -287,10 +287,15 @@ int system_get_chip_unique_id(uint8_t **id);
/**
* Optional board-level callback functions to read a unique serial number per
* chip. Default implementation reads from flash (flash_read_serial).
* chip. Default implementation reads from flash/otp (flash/otp_read_serial).
*/
const char *board_read_serial(void) __attribute__((weak));
/**
* Optional board-level callback functions to write a unique serial number per
* chip. Default implementation reads from flash/otp (flash/otp_write_serial).
*/
int board_write_serial(const char *serial) __attribute__((weak));
/*
* Common bbram entries. Chips don't necessarily need to implement
* all of these, error will be returned from system_get/set_bbram if

View File

@@ -258,11 +258,10 @@ struct usb_setup_packet {
#ifdef CONFIG_USB_SERIALNO
/* String Descriptor for USB, for editable strings. */
#define USB_STRING_LEN 28
struct usb_string_desc {
uint8_t _len;
uint8_t _type;
wchar_t _data[USB_STRING_LEN];
wchar_t _data[CONFIG_SERIALNO_LEN];
};
#define USB_WR_STRING_DESC(str) \
(&(struct usb_string_desc) { \