summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/elog/elog.c85
1 files changed, 31 insertions, 54 deletions
diff --git a/src/drivers/elog/elog.c b/src/drivers/elog/elog.c
index c33544fb93..606f5e7954 100644
--- a/src/drivers/elog/elog.c
+++ b/src/drivers/elog/elog.c
@@ -45,16 +45,15 @@
* Static variables for ELOG state
*/
static u16 total_size;
-static u16 log_size; /* excluding header */
static u32 flash_base;
-static u16 full_threshold; /* from end of header */
-static u16 shrink_size; /* from end of header */
+static u16 full_threshold;
+static u16 shrink_size;
static elog_area_state area_state;
static elog_header_state header_state;
static elog_event_buffer_state event_buffer_state;
-static u16 next_event_offset; /* from end of header */
+static u16 next_event_offset;
static u16 event_count;
static struct spi_flash *elog_spi;
@@ -72,16 +71,22 @@ static inline struct region_device *mirror_dev_get(void)
return &mirror_dev.rdev;
}
+static size_t elog_events_start(void)
+{
+ /* Events are added directly after the header. */
+ return sizeof(struct elog_header);
+}
+
+static size_t elog_events_total_space(void)
+{
+ return total_size - elog_events_start();
+}
+
/*
* Pointer to an event log header in the event data area
*/
static struct event_header *elog_get_event_buffer(size_t offset, size_t size)
{
- /*
- * Events are appended relative to the end of the header. Update
- * offset to include the header size.
- */
- offset += sizeof(struct elog_header);
return rdev_mmap(mirror_dev_get(), offset, size);
}
@@ -139,17 +144,6 @@ static int elog_is_buffer_clear(size_t offset)
return ret;
}
-static int elog_event_buffer_is_clear(size_t offset)
-{
- /*
- * Events are appended relative to the end of the header. Update
- * offset to include the header size.
- */
- offset += sizeof(struct elog_header);
-
- return elog_is_buffer_clear(offset);
-}
-
/*
* Check that the ELOG area has been initialized and is valid.
*/
@@ -268,16 +262,6 @@ static void elog_flash_write(size_t offset, size_t size)
rdev_munmap(rdev, address);
}
-static void elog_append_event(size_t offset, size_t event_size)
-{
- /*
- * Events are appended relative to the end of the header. Update
- * offset to include the header size.
- */
- offset += sizeof(struct elog_header);
- elog_flash_write(offset, event_size);
-}
-
/*
* Erase the first block specified in the address.
* Only handles flash area within a single flash block.
@@ -300,7 +284,7 @@ static void elog_flash_erase(void)
static void elog_update_event_buffer_state(void)
{
u32 count = 0;
- u32 offset = 0;
+ size_t offset = elog_events_start();
elog_debug("elog_update_event_buffer_state()\n");
@@ -310,10 +294,9 @@ static void elog_update_event_buffer_state(void)
const size_t type_offset = offsetof(struct event_header, type);
size_t len;
const size_t size = sizeof(type);
- size_t abs_offset = offset + sizeof(struct elog_header);
if (rdev_readat(mirror_dev_get(), &type,
- abs_offset + type_offset, size) < 0) {
+ offset + type_offset, size) < 0) {
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
break;
}
@@ -323,7 +306,7 @@ static void elog_update_event_buffer_state(void)
break;
/* Validate the event */
- len = elog_is_event_valid(abs_offset);
+ len = elog_is_event_valid(offset);
if (!len) {
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
@@ -336,7 +319,7 @@ static void elog_update_event_buffer_state(void)
}
/* Ensure the remaining buffer is empty */
- if (!elog_event_buffer_is_clear(offset))
+ if (!elog_is_buffer_clear(offset))
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
/* Update ELOG state */
@@ -359,7 +342,7 @@ static void elog_scan_flash(void)
elog_spi->read(elog_spi, flash_base, total_size, mirror_buffer);
rdev_munmap(rdev, mirror_buffer);
- next_event_offset = 0;
+ next_event_offset = elog_events_start();
event_count = 0;
/* Check if the area is empty or not */
@@ -412,14 +395,9 @@ static void elog_move_events_to_front(size_t offset, size_t size)
{
void *src;
void *dest;
- size_t start_offset = sizeof(struct elog_header);
+ size_t start_offset = elog_events_start();
const struct region_device *rdev = mirror_dev_get();
- /*
- * Events are appended relative to the end of the header. Update
- * offset to include the header size.
- */
- offset += start_offset;
src = rdev_mmap(rdev, offset, size);
dest = rdev_mmap(rdev, start_offset, size);
@@ -454,7 +432,7 @@ static void elog_move_events_to_front(size_t offset, size_t size)
static int elog_shrink(void)
{
const struct region_device *rdev = mirror_dev_get();
- u16 offset = 0;
+ size_t offset = elog_events_start();
elog_debug("elog_shrink()\n");
@@ -464,21 +442,19 @@ static int elog_shrink(void)
const size_t size = sizeof(uint8_t);
uint8_t type;
uint8_t len;
- size_t abs_offset = offset + sizeof(struct elog_header);
/* Next event has exceeded constraints */
if (offset > shrink_size)
break;
- if (rdev_readat(rdev, &type, abs_offset + type_offset,
- size) < 0)
+ if (rdev_readat(rdev, &type, offset + type_offset, size) < 0)
break;
/* Reached the end of the area */
if (type == ELOG_TYPE_EOL)
break;
- if (rdev_readat(rdev, &len, abs_offset + len_offset, size) < 0)
+ if (rdev_readat(rdev, &len, offset + len_offset, size) < 0)
break;
offset += len;
@@ -497,7 +473,7 @@ static int elog_shrink(void)
}
/* Add clear event */
- elog_add_event_word(ELOG_TYPE_LOG_CLEAR, offset);
+ elog_add_event_word(ELOG_TYPE_LOG_CLEAR, offset - elog_events_start());
return 0;
}
@@ -581,7 +557,7 @@ int elog_clear(void)
return -1;
/* Log the clear event */
- elog_add_event_word(ELOG_TYPE_LOG_CLEAR, log_size);
+ elog_add_event_word(ELOG_TYPE_LOG_CLEAR, elog_events_total_space());
return 0;
}
@@ -589,6 +565,7 @@ int elog_clear(void)
static void elog_find_flash(void)
{
struct region r;
+ size_t reserved_space = ELOG_MIN_AVAILABLE_ENTRIES * MAX_EVENT_SIZE;
elog_debug("elog_find_flash()\n");
@@ -602,8 +579,7 @@ static void elog_find_flash(void)
total_size = MIN(4*KiB, region_sz(&r));
}
- log_size = total_size - sizeof(struct elog_header);
- full_threshold = log_size - ELOG_MIN_AVAILABLE_ENTRIES * MAX_EVENT_SIZE;
+ full_threshold = total_size - reserved_space;
shrink_size = MIN(total_size * ELOG_SHRINK_PERCENTAGE / 100,
full_threshold);
}
@@ -642,7 +618,7 @@ int elog_init(void)
} else if (total_size < sizeof(struct elog_header) + MAX_EVENT_SIZE) {
printk(BIOS_ERR, "ELOG: Region too small to hold any events\n");
return -1;
- } else if (log_size - shrink_size >= full_threshold) {
+ } else if (total_size - shrink_size >= full_threshold) {
printk(BIOS_ERR,
"ELOG: SHRINK_PERCENTAGE set too small for MIN_AVAILABLE_ENTRIES\n");
return -1;
@@ -691,7 +667,8 @@ int elog_init(void)
/* Log a clear event if necessary */
if (event_count == 0)
- elog_add_event_word(ELOG_TYPE_LOG_CLEAR, log_size);
+ elog_add_event_word(ELOG_TYPE_LOG_CLEAR,
+ elog_events_total_space());
#if !defined(__SMM__)
/* Log boot count event except in S3 resume */
@@ -793,7 +770,7 @@ void elog_add_event_raw(u8 event_type, void *data, u8 data_size)
/* Update the ELOG state */
event_count++;
- elog_append_event(next_event_offset, event_size);
+ elog_flash_write(next_event_offset, event_size);
next_event_offset += event_size;