timestamp: Keep the timestamp table in the FWDB.

Change-Id: Ie1cb4e79a2f0f47947c6619a243f835d6fd32a22
diff --git a/src/arch/x86/amd64/handoff/uefi.c b/src/arch/x86/amd64/handoff/uefi.c
index 051e793..b667720 100644
--- a/src/arch/x86/amd64/handoff/uefi.c
+++ b/src/arch/x86/amd64/handoff/uefi.c
@@ -25,6 +25,7 @@
 #include "arch/x86/amd64/handoff/handoff.h"
 #include "base/fwdb.h"
 #include "base/memory.h"
+#include "base/timestamp.h"
 #include "uefi/uefi.h"
 
 extern EFI_SYSTEM_TABLE *_uefi_handoff_system_table;
diff --git a/src/base/Kconfig b/src/base/Kconfig
index d91d372..778d71c 100644
--- a/src/base/Kconfig
+++ b/src/base/Kconfig
@@ -27,3 +27,7 @@
 config MAX_MEM_RANGES
 	int "Max number of memory ranges"
 	default 32
+
+config MAX_TIMESTAMPS
+	int "Max number of timestamps in the timestamp table"
+	default 60
diff --git a/src/base/timestamp.c b/src/base/timestamp.c
index 71aef04..da0979d 100644
--- a/src/base/timestamp.c
+++ b/src/base/timestamp.c
@@ -16,49 +16,83 @@
  */
 
 #include <stdint.h>
+#include <stdio.h>
 #include <sysinfo.h>
 
+#include "base/fwdb.h"
 #include "base/init_funcs.h"
 #include "base/time.h"
 #include "base/timestamp.h"
 #include "drivers/timer/timer.h"
 
-struct timestamp_entry {
-	uint32_t	entry_id;
-	uint64_t	entry_stamp;
-} __attribute__((packed));
+static TimestampTable *timestamp_table;
 
-struct timestamp_table {
-	uint64_t	base_time;
-	uint32_t	max_entries;
-	uint32_t	num_entries;
-	struct timestamp_entry entries[0]; /* Variable number of entries */
-} __attribute__((packed));
-
-static struct timestamp_table *ts_table;
-
-static int timestamp_init(void)
+static int timestamp_table_max_entries(TimestampTable *table, size_t size)
 {
-	ts_table = get_sysinfo()->tstamp_table;
+	size_t entries_size = size - offsetof(TimestampTable, entries);
+	return entries_size / sizeof(TimestampEntry);
+}
+
+static void timestamp_table_init(TimestampTable *table, size_t size)
+{
+	table->base_time = 0;
+	table->max_entries = timestamp_table_max_entries(table, size);
+	table->num_entries = 0;
+}
+
+static int timestamp_table_install(void)
+{
+	if (timestamp_table) {
+		printf("Timestamp table is already initialized.\n");
+		return 1;
+	}
+
+	FwdbEntry default_entry = {
+		.size = offsetof(TimestampTable, entries) +
+			CONFIG_MAX_TIMESTAMPS * sizeof(TimestampEntry),
+	};
+	FwdbEntry entry;
+	if (fwdb_access("timestamp table", &entry, &default_entry))
+		return 1;
+	TimestampTable *table = (TimestampTable *)entry.ptr;
+	if (!table->max_entries)
+		timestamp_table_init(table, entry.size);
+
+	int max_entries = timestamp_table_max_entries(table, entry.size);
+	if (table->max_entries > max_entries) {
+		printf("Timestamp table max entries too high.\n");
+		return 1;
+	}
+
+	if (table->num_entries > table->max_entries) {
+		printf("Timestamp table over filled.\n");
+		return 1;
+	}
+
+	timestamp_table = table;
+
 	timestamp_add_now(TS_START);
 	return 0;
 }
 
-INIT_FUNC_TIMESTAMP(timestamp_init)
+INIT_FUNC_TIMESTAMP(timestamp_table_install)
 
-void timestamp_add(enum timestamp_id id, uint64_t ts_time)
+void timestamp_add(TimestampId id, uint64_t time)
 {
-	struct timestamp_entry *tse;
+	TimestampEntry *tse;
 
-	if (!ts_table || (ts_table->num_entries == ts_table->max_entries))
+	if (!timestamp_table ||
+	    (timestamp_table->num_entries ==
+	     timestamp_table->max_entries)) {
 		return;
+	}
 
-	tse = &ts_table->entries[ts_table->num_entries++];
-	tse->entry_id = id;
-	tse->entry_stamp = ts_time - ts_table->base_time;
+	tse = &timestamp_table->entries[timestamp_table->num_entries++];
+	tse->id = id;
+	tse->stamp = time - timestamp_table->base_time;
 }
 
-void timestamp_add_now(enum timestamp_id id)
+void timestamp_add_now(TimestampId id)
 {
 	if (CONFIG_TIMESTAMP_RAW)
 		timestamp_add(id, timer_raw_value());
diff --git a/src/base/timestamp.h b/src/base/timestamp.h
index 045dedf..aee7b73 100644
--- a/src/base/timestamp.h
+++ b/src/base/timestamp.h
@@ -20,7 +20,19 @@
 
 #include <stdint.h>
 
-enum timestamp_id {
+typedef struct __attribute__((packed)) {
+	uint32_t id;
+	uint64_t stamp;
+} TimestampEntry;
+
+typedef struct __attribute__((packed)) {
+	uint64_t base_time;
+	uint32_t max_entries;
+	uint32_t num_entries;
+	TimestampEntry entries[0]; // Variable number of entries.
+} TimestampTable;
+
+typedef enum {
 	// Depthcharge entry IDs start at 1000.
 	TS_START = 1000,
 
@@ -37,9 +49,9 @@
 
 	TS_CROSSYSTEM_DATA = 1100,
 	TS_START_KERNEL = 1101
-};
+} TimestampId;
 
-void timestamp_add(enum timestamp_id id, uint64_t ts_time);
-void timestamp_add_now(enum timestamp_id id);
+void timestamp_add(TimestampId id, uint64_t time);
+void timestamp_add_now(TimestampId id);
 
 #endif /* __BASE_TIMESTAMP_H__ */
diff --git a/src/module/handoff/coreboot.c b/src/module/handoff/coreboot.c
index bf8731e..28fa042 100644
--- a/src/module/handoff/coreboot.c
+++ b/src/module/handoff/coreboot.c
@@ -34,6 +34,7 @@
 
 #include "base/fwdb.h"
 #include "base/memory.h"
+#include "base/timestamp.h"
 #include "drivers/framebuffer/framebuffer.h"
 #include "vboot/util/vboot_handoff.h"
 
@@ -150,6 +151,14 @@
 {
 	struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
 	info->tstamp_table = (void *)(uintptr_t)cbmem->cbmem_tab;
+
+	TimestampTable *table = (void *)(uintptr_t)cbmem->cbmem_tab;
+	FwdbEntry timestamp_table_entry = {
+		.ptr = table,
+		.size = offsetof(TimestampTable, entries) +
+			table->max_entries * sizeof(TimestampEntry),
+	};
+	fwdb_access("timestamp table", NULL, &timestamp_table_entry);
 }
 
 static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info)