blob: 37399702f8c1fd12f6cf74d63918e5c5900ea501 [file] [log] [blame]
/* Copyright 2019 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.
*/
#ifndef __TPM2_NVMEM_TEST_NEW_NVMEM_H
#define __TPM2_NVMEM_TEST_NEW_NVMEM_H
#include "common.h"
#include "nvmem.h"
#include "nvmem_vars.h"
#include "util.h"
#define NVMEM_NOT_INITIALIZED ((unsigned int)-1)
/*
* A totally arbitrary byte limit for space occupied by (key, value) pairs in
* the flash. This is an improvement compared to the legacy case where there
* were just 272 bytes dedicated to the (key, value) pairs storage.
*/
#define MAX_VAR_TOTAL_SPACE 1000
/*
* Let's be reasonable: we're unlikely to have keys longer than 40 or so
* bytes, and leave full 255 bytes for the value. Total data space occupied by
* a (key, value) pair is not to exceed the value below.
*/
#define MAX_VAR_BODY_SPACE 300
enum nn_object_type {
NN_OBJ_OLD_COPY = 0,
NN_OBJ_TUPLE = 1,
NN_OBJ_TPM_RESERVED = 2,
NN_OBJ_TPM_EVICTABLE = 3,
NN_OBJ_TRANSACTION_DEL = 4,
NN_OBJ_ESCAPE = 5,
NN_OBJ_ERASED = 7,
};
/*
* Structure placed at the base of each flash page used for NVMEM storage.
*
* page_number: allows to arrange pages in order they were added
*
* data_offset: the offset of the first element in the page (space above
* page header and below data_offset could be taken by the
* 'tail' of the object stored on the previous page).
*
* page_hash: is used to verify page header integrity
*/
struct nn_page_header {
unsigned int page_number : 21;
unsigned int data_offset : 11;
uint32_t page_hash;
} __packed;
/*
* Index of the 'virtual' last reserved object. RAM index space and max
* counter objects stored at fixed location in the NVMEM cache are considered
* reserved objects by this NVMEM flash layer.
*/
#define NV_VIRTUAL_RESERVE_LAST (NV_RESERVE_LAST + 2)
/*
* Container header for all blobs stored in flash.
*
* container_type: type of object stored in the container. MAKE SURE THIS
* FIELD TYPE IS THE FIRST FIELD IN THIS STRUCTURE, it is
* supposed to be in the first word of the container so that
* the type can be erased when object is deleted.
*
* container_type_copy: immutable copy of the container_type field, used to
* verify contents of deleted objects.
*
* encrypted: set to 1 if contents are encrypted.
*
* size: size of the payload, 12 bits allocated, 11 bits would be enough for
* this use case.
*
* generation: a free running counter, used to compare ages of two containers
*
* container_hash: hash of the ENTIRE container, both header and body
* included. This field is set to zero before hash is calculated
*/
struct nn_container {
unsigned int container_type : 3;
unsigned int container_type_copy : 3;
unsigned int encrypted : 1;
unsigned int size : 11;
unsigned int generation : 2;
unsigned int container_hash : 12;
} __packed;
/*
* A structure to keep context of accessing to a page, page header and offset
* define where the next access would happen.
*/
struct page_tracker {
const struct nn_page_header *ph;
uint16_t data_offset;
};
/*
* Helper structure to keep track of accesses to the flash storage.
*
* mt: main tracker for read or write accesses.
*
* ct: keeps track of container fetches, as the location of containers has
* special significance: it is both part of the seed used when
* encrypting/decryping container contents, and also is necessary to
* unwind reading of the container header when the end of storage is
* reached and a header of all 0xff is read.
*
* dt: keeps track of delimiters which is important when assessing flash
* contents integrity. If during startup the last item in flash is not a
* delimiter, this is an indication of a failed transaction, all data
* after the previous delimiter needs to be discarded.
*
* list_index; index of the current page in the list of pages, useful when
* sequential reading and need to get to the next page in the
* list.
*/
struct access_tracker {
struct page_tracker mt; /* Main tracker. */
struct page_tracker ct; /* Container tracker. */
struct page_tracker dt; /* Delimiter tracker.*/
uint8_t list_index;
};
/*
* New nvmem interface functions, each of them could be blocking because each
* of them acquires nvmem flash protectioin mutex before proceeding.
*/
enum ec_error_list new_nvmem_init(void);
enum ec_error_list new_nvmem_migrate(unsigned int nvmem_act_partition);
enum ec_error_list new_nvmem_save(void);
int nvmem_erase_tpm_data(void);
#if defined(TEST_BUILD) && !defined(TEST_FUZZ)
#define NVMEM_TEST_BUILD
enum ec_error_list browse_flash_contents(int);
enum ec_error_list compact_nvmem(void);
extern struct access_tracker master_at;
extern uint16_t total_var_space;
int is_uninitialized(const void *p, size_t size);
size_t init_object_offsets(uint16_t *offsets, size_t count);
struct nn_page_header *list_element_to_ph(size_t el);
void *evictable_offs_to_addr(uint16_t offset);
enum ec_error_list get_next_object(struct access_tracker *at,
struct nn_container *ch,
int include_deleted);
#endif
#endif /* ! __TPM2_NVMEM_TEST_NEW_NVMEM_H */