drivers/elog: use region_device for mirroring into ram
A region_device can be used to represent the in-memory mirror of the event log. The region_device infrastructure has builtin bounds checking so there's no need to duplicate that. In addition, it allows for removing much of the math juggling for the buffer size, etc. BUG=chrome-os-partner:55932 Change-Id: Ic7fe9466019640b449257c5905ed919ac522bb58 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/16097 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
parent
422c440fa6
commit
281c994ce2
|
@ -44,7 +44,6 @@
|
||||||
/*
|
/*
|
||||||
* Static variables for ELOG state
|
* Static variables for ELOG state
|
||||||
*/
|
*/
|
||||||
static struct elog_area *elog_area;
|
|
||||||
static u16 total_size;
|
static u16 total_size;
|
||||||
static u16 log_size; /* excluding header */
|
static u16 log_size; /* excluding header */
|
||||||
static u32 flash_base;
|
static u32 flash_base;
|
||||||
|
@ -59,6 +58,8 @@ static u16 next_event_offset; /* from end of header */
|
||||||
static u16 event_count;
|
static u16 event_count;
|
||||||
|
|
||||||
static struct spi_flash *elog_spi;
|
static struct spi_flash *elog_spi;
|
||||||
|
/* Device that mirrors the eventlog in memory. */
|
||||||
|
static struct mem_region_device mirror_dev;
|
||||||
|
|
||||||
static enum {
|
static enum {
|
||||||
ELOG_UNINITIALIZED = 0,
|
ELOG_UNINITIALIZED = 0,
|
||||||
|
@ -66,13 +67,27 @@ static enum {
|
||||||
ELOG_BROKEN,
|
ELOG_BROKEN,
|
||||||
} elog_initialized = ELOG_UNINITIALIZED;
|
} elog_initialized = ELOG_UNINITIALIZED;
|
||||||
|
|
||||||
|
static inline struct region_device *mirror_dev_get(void)
|
||||||
|
{
|
||||||
|
return &mirror_dev.rdev;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pointer to an event log header in the event data area
|
* Pointer to an event log header in the event data area
|
||||||
*/
|
*/
|
||||||
static inline struct event_header*
|
static struct event_header *elog_get_event_buffer(size_t offset, size_t size)
|
||||||
elog_get_event_base(u32 offset)
|
|
||||||
{
|
{
|
||||||
return (struct event_header *)&elog_area->data[offset];
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void elog_put_event_buffer(struct event_header *event)
|
||||||
|
{
|
||||||
|
rdev_munmap(mirror_dev_get(), event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -103,17 +118,25 @@ static u8 elog_checksum_event(struct event_header *event)
|
||||||
*/
|
*/
|
||||||
static int elog_is_buffer_clear(size_t offset)
|
static int elog_is_buffer_clear(size_t offset)
|
||||||
{
|
{
|
||||||
size_t size = total_size - offset;
|
size_t i;
|
||||||
u8 *current = offset + (u8 *)elog_area;
|
const struct region_device *rdev = mirror_dev_get();
|
||||||
u8 *end = current + size;
|
size_t size = region_device_sz(rdev) - offset;
|
||||||
|
uint8_t *buffer = rdev_mmap(rdev, offset, size);
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
elog_debug("elog_is_buffer_clear(offset=%zu size=%zu)\n", offset, size);
|
elog_debug("elog_is_buffer_clear(offset=%zu size=%zu)\n", offset, size);
|
||||||
|
|
||||||
for (; current != end; current++) {
|
if (buffer == NULL)
|
||||||
if (*current != ELOG_TYPE_EOL)
|
return 0;
|
||||||
return 0;
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if (buffer[i] != ELOG_TYPE_EOL) {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
rdev_munmap(rdev, buffer);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elog_event_buffer_is_clear(size_t offset)
|
static int elog_event_buffer_is_clear(size_t offset)
|
||||||
|
@ -144,13 +167,22 @@ static int elog_is_area_valid(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify the contents of an ELOG Header structure
|
* Verify if the mirrored elog structure is valid.
|
||||||
* Returns 1 if the header is valid, 0 otherwise
|
* Returns 1 if the header is valid, 0 otherwise
|
||||||
*/
|
*/
|
||||||
static int elog_is_header_valid(struct elog_header *header)
|
static int elog_is_header_valid(void)
|
||||||
{
|
{
|
||||||
|
struct elog_header *header;
|
||||||
|
|
||||||
elog_debug("elog_is_header_valid()\n");
|
elog_debug("elog_is_header_valid()\n");
|
||||||
|
|
||||||
|
header = rdev_mmap(mirror_dev_get(), 0, sizeof(*header));
|
||||||
|
|
||||||
|
if (header == NULL) {
|
||||||
|
printk(BIOS_ERR, "ELOG: could not map header.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (header->magic != ELOG_SIGNATURE) {
|
if (header->magic != ELOG_SIGNATURE) {
|
||||||
printk(BIOS_ERR, "ELOG: header magic 0x%X != 0x%X\n",
|
printk(BIOS_ERR, "ELOG: header magic 0x%X != 0x%X\n",
|
||||||
header->magic, ELOG_SIGNATURE);
|
header->magic, ELOG_SIGNATURE);
|
||||||
|
@ -172,45 +204,38 @@ static int elog_is_header_valid(struct elog_header *header)
|
||||||
/*
|
/*
|
||||||
* Validate the event header and data.
|
* Validate the event header and data.
|
||||||
*/
|
*/
|
||||||
static int elog_is_event_valid(u32 offset)
|
static size_t elog_is_event_valid(size_t offset)
|
||||||
{
|
{
|
||||||
|
uint8_t checksum;
|
||||||
struct event_header *event;
|
struct event_header *event;
|
||||||
|
uint8_t len;
|
||||||
|
const size_t len_offset = offsetof(struct event_header, length);
|
||||||
|
const size_t size = sizeof(len);
|
||||||
|
|
||||||
event = elog_get_event_base(offset);
|
/* Read and validate length. */
|
||||||
if (!event)
|
if (rdev_readat(mirror_dev_get(), &len, offset + len_offset, size) < 0)
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Validate event length */
|
|
||||||
if ((offsetof(struct event_header, type) +
|
|
||||||
sizeof(event->type) - 1 + offset) >= log_size)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* End of event marker has been found */
|
|
||||||
if (event->type == ELOG_TYPE_EOL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Check if event fits in area */
|
|
||||||
if ((offsetof(struct event_header, length) +
|
|
||||||
sizeof(event->length) - 1 + offset) >= log_size)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the current event length + the current offset exceeds
|
|
||||||
* the area size then the event area is corrupt.
|
|
||||||
*/
|
|
||||||
if ((event->length + offset) >= log_size)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Event length must be at least header size + checksum */
|
/* Event length must be at least header size + checksum */
|
||||||
if (event->length < (sizeof(*event) + 1))
|
if (len < (sizeof(*event) + sizeof(checksum)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (len > MAX_EVENT_SIZE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
event = elog_get_event_buffer(offset, len);
|
||||||
|
if (!event)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If event checksum is invalid the area is corrupt */
|
/* If event checksum is invalid the area is corrupt */
|
||||||
if (elog_checksum_event(event) != 0)
|
checksum = elog_checksum_event(event);
|
||||||
|
elog_put_event_buffer(event);
|
||||||
|
|
||||||
|
if (checksum != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Event is valid */
|
/* Event is valid */
|
||||||
return 1;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -221,11 +246,12 @@ static int elog_is_event_valid(u32 offset)
|
||||||
static void elog_flash_write(size_t offset, size_t size)
|
static void elog_flash_write(size_t offset, size_t size)
|
||||||
{
|
{
|
||||||
void *address;
|
void *address;
|
||||||
|
const struct region_device *rdev = mirror_dev_get();
|
||||||
|
|
||||||
if (!size || !elog_spi)
|
if (!size || !elog_spi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
address = offset + (u8 *)elog_area;
|
address = rdev_mmap(rdev, offset, size);
|
||||||
|
|
||||||
/* Ensure offset is absolute. */
|
/* Ensure offset is absolute. */
|
||||||
offset += flash_base;
|
offset += flash_base;
|
||||||
|
@ -233,8 +259,13 @@ static void elog_flash_write(size_t offset, size_t size)
|
||||||
elog_debug("elog_flash_write(address=0x%p offset=0x%08x size=%u)\n",
|
elog_debug("elog_flash_write(address=0x%p offset=0x%08x size=%u)\n",
|
||||||
address, offset, size);
|
address, offset, size);
|
||||||
|
|
||||||
|
if (address == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Write the data to flash */
|
/* Write the data to flash */
|
||||||
elog_spi->write(elog_spi, offset, size, address);
|
elog_spi->write(elog_spi, offset, size, address);
|
||||||
|
|
||||||
|
rdev_munmap(rdev, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elog_append_event(size_t offset, size_t event_size)
|
static void elog_append_event(size_t offset, size_t event_size)
|
||||||
|
@ -270,34 +301,38 @@ static void elog_update_event_buffer_state(void)
|
||||||
{
|
{
|
||||||
u32 count = 0;
|
u32 count = 0;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
struct event_header *event;
|
|
||||||
|
|
||||||
elog_debug("elog_update_event_buffer_state()\n");
|
elog_debug("elog_update_event_buffer_state()\n");
|
||||||
|
|
||||||
/* Go through each event and validate it */
|
/* Go through each event and validate it */
|
||||||
while (1) {
|
while (1) {
|
||||||
event = elog_get_event_base(offset);
|
uint8_t type;
|
||||||
|
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);
|
||||||
|
|
||||||
/* Do not de-reference anything past the area length */
|
if (rdev_readat(mirror_dev_get(), &type,
|
||||||
if ((offsetof(struct event_header, type) +
|
abs_offset + type_offset, size) < 0) {
|
||||||
sizeof(event->type) - 1 + offset) >= log_size) {
|
|
||||||
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The end of the event marker has been found */
|
/* The end of the event marker has been found */
|
||||||
if (event->type == ELOG_TYPE_EOL)
|
if (type == ELOG_TYPE_EOL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Validate the event */
|
/* Validate the event */
|
||||||
if (!elog_is_event_valid(offset)) {
|
len = elog_is_event_valid(abs_offset);
|
||||||
|
|
||||||
|
if (!len) {
|
||||||
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move to the next event */
|
/* Move to the next event */
|
||||||
count++;
|
count++;
|
||||||
offset += event->length;
|
offset += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the remaining buffer is empty */
|
/* Ensure the remaining buffer is empty */
|
||||||
|
@ -312,13 +347,17 @@ static void elog_update_event_buffer_state(void)
|
||||||
static void elog_scan_flash(void)
|
static void elog_scan_flash(void)
|
||||||
{
|
{
|
||||||
elog_debug("elog_scan_flash()\n");
|
elog_debug("elog_scan_flash()\n");
|
||||||
|
void *mirror_buffer;
|
||||||
|
const struct region_device *rdev = mirror_dev_get();
|
||||||
|
|
||||||
area_state = ELOG_AREA_UNDEFINED;
|
area_state = ELOG_AREA_UNDEFINED;
|
||||||
header_state = ELOG_HEADER_INVALID;
|
header_state = ELOG_HEADER_INVALID;
|
||||||
event_buffer_state = ELOG_EVENT_BUFFER_OK;
|
event_buffer_state = ELOG_EVENT_BUFFER_OK;
|
||||||
|
|
||||||
/* Fill memory buffer by reading from SPI */
|
/* Fill memory buffer by reading from SPI */
|
||||||
elog_spi->read(elog_spi, flash_base, total_size, elog_area);
|
mirror_buffer = rdev_mmap_full(rdev);
|
||||||
|
elog_spi->read(elog_spi, flash_base, total_size, mirror_buffer);
|
||||||
|
rdev_munmap(rdev, mirror_buffer);
|
||||||
|
|
||||||
next_event_offset = 0;
|
next_event_offset = 0;
|
||||||
event_count = 0;
|
event_count = 0;
|
||||||
|
@ -332,7 +371,7 @@ static void elog_scan_flash(void)
|
||||||
area_state = ELOG_AREA_HAS_CONTENT;
|
area_state = ELOG_AREA_HAS_CONTENT;
|
||||||
|
|
||||||
/* Validate the header */
|
/* Validate the header */
|
||||||
if (!elog_is_header_valid(&elog_area->header)) {
|
if (!elog_is_header_valid()) {
|
||||||
header_state = ELOG_HEADER_INVALID;
|
header_state = ELOG_HEADER_INVALID;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -341,55 +380,111 @@ static void elog_scan_flash(void)
|
||||||
elog_update_event_buffer_state();
|
elog_update_event_buffer_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t elog_write_header_in_mirror(void)
|
||||||
|
{
|
||||||
|
static const struct elog_header header = {
|
||||||
|
.magic = ELOG_SIGNATURE,
|
||||||
|
.version = ELOG_VERSION,
|
||||||
|
.header_size = sizeof(struct elog_header),
|
||||||
|
.reserved = {
|
||||||
|
[0] = ELOG_TYPE_EOL,
|
||||||
|
[1] = ELOG_TYPE_EOL,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
rdev_writeat(mirror_dev_get(), &header, 0, sizeof(header));
|
||||||
|
return sizeof(header);
|
||||||
|
}
|
||||||
|
|
||||||
static void elog_prepare_empty(void)
|
static void elog_prepare_empty(void)
|
||||||
{
|
{
|
||||||
struct elog_header *header;
|
|
||||||
|
|
||||||
elog_debug("elog_prepare_empty()\n");
|
elog_debug("elog_prepare_empty()\n");
|
||||||
|
|
||||||
/* Write out the header */
|
/* Write out the header */
|
||||||
header = &elog_area->header;
|
size_t size = elog_write_header_in_mirror();
|
||||||
header->magic = ELOG_SIGNATURE;
|
elog_flash_write(0, size);
|
||||||
header->version = ELOG_VERSION;
|
|
||||||
header->header_size = sizeof(struct elog_header);
|
|
||||||
header->reserved[0] = ELOG_TYPE_EOL;
|
|
||||||
header->reserved[1] = ELOG_TYPE_EOL;
|
|
||||||
elog_flash_write(0, header->header_size);
|
|
||||||
|
|
||||||
elog_scan_flash();
|
elog_scan_flash();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (src == NULL || dest == NULL) {
|
||||||
|
printk(BIOS_ERR, "ELOG: failure moving events!\n");
|
||||||
|
rdev_munmap(rdev, dest);
|
||||||
|
rdev_munmap(rdev, src);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move the events to the front. */
|
||||||
|
memmove(dest, src, size);
|
||||||
|
rdev_munmap(rdev, dest);
|
||||||
|
rdev_munmap(rdev, src);
|
||||||
|
|
||||||
|
/* Mark EOL for previously used buffer until the end. */
|
||||||
|
offset = start_offset + size;
|
||||||
|
size = region_device_sz(rdev) - offset;
|
||||||
|
dest = rdev_mmap(rdev, offset, size);
|
||||||
|
if (dest == NULL) {
|
||||||
|
printk(BIOS_ERR, "ELOG: failure filling EOL!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset(dest, ELOG_TYPE_EOL, size);
|
||||||
|
rdev_munmap(rdev, dest);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shrink the log, deleting old entries and moving the
|
* Shrink the log, deleting old entries and moving the
|
||||||
* remaining ones to the front of the log.
|
* remaining ones to the front of the log.
|
||||||
*/
|
*/
|
||||||
static int elog_shrink(void)
|
static int elog_shrink(void)
|
||||||
{
|
{
|
||||||
struct event_header *event;
|
const struct region_device *rdev = mirror_dev_get();
|
||||||
u16 discard_count = 0;
|
|
||||||
u16 offset = 0;
|
u16 offset = 0;
|
||||||
u16 new_size = 0;
|
|
||||||
|
|
||||||
elog_debug("elog_shrink()\n");
|
elog_debug("elog_shrink()\n");
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
const size_t type_offset = offsetof(struct event_header, type);
|
||||||
|
const size_t len_offset = offsetof(struct event_header, length);
|
||||||
|
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 */
|
/* Next event has exceeded constraints */
|
||||||
if (offset > shrink_size)
|
if (offset > shrink_size)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
event = elog_get_event_base(offset);
|
if (rdev_readat(rdev, &type, abs_offset + type_offset,
|
||||||
|
size) < 0)
|
||||||
/* Reached the end of the area */
|
|
||||||
if (!event || event->type == ELOG_TYPE_EOL)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
offset += event->length;
|
/* Reached the end of the area */
|
||||||
discard_count++;
|
if (type == ELOG_TYPE_EOL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (rdev_readat(rdev, &len, abs_offset + len_offset, size) < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
offset += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_size = next_event_offset - offset;
|
elog_move_events_to_front(offset, next_event_offset - offset);
|
||||||
memmove(&elog_area->data[0], &elog_area->data[offset], new_size);
|
|
||||||
memset(&elog_area->data[new_size], ELOG_TYPE_EOL, log_size - new_size);
|
|
||||||
|
|
||||||
elog_flash_erase();
|
elog_flash_erase();
|
||||||
elog_flash_write(0, total_size);
|
elog_flash_write(0, total_size);
|
||||||
|
@ -439,7 +534,7 @@ int elog_smbios_write_type15(unsigned long *current, int handle)
|
||||||
void *cbmem = cbmem_add(CBMEM_ID_ELOG, total_size);
|
void *cbmem = cbmem_add(CBMEM_ID_ELOG, total_size);
|
||||||
if (!cbmem)
|
if (!cbmem)
|
||||||
return 0;
|
return 0;
|
||||||
memcpy(cbmem, elog_area, total_size);
|
rdev_readat(mirror_dev_get(), cbmem, 0, total_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(t, 0, len);
|
memset(t, 0, len);
|
||||||
|
@ -518,6 +613,8 @@ static void elog_find_flash(void)
|
||||||
*/
|
*/
|
||||||
int elog_init(void)
|
int elog_init(void)
|
||||||
{
|
{
|
||||||
|
void *mirror_buffer;
|
||||||
|
|
||||||
switch (elog_initialized) {
|
switch (elog_initialized) {
|
||||||
case ELOG_UNINITIALIZED:
|
case ELOG_UNINITIALIZED:
|
||||||
break;
|
break;
|
||||||
|
@ -551,11 +648,12 @@ int elog_init(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
elog_area = malloc(total_size);
|
mirror_buffer = malloc(total_size);
|
||||||
if (!elog_area) {
|
if (!mirror_buffer) {
|
||||||
printk(BIOS_ERR, "ELOG: Unable to allocate backing store\n");
|
printk(BIOS_ERR, "ELOG: Unable to allocate backing store\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
mem_region_device_rw_init(&mirror_dev, mirror_buffer, total_size);
|
||||||
|
|
||||||
/* Load the log from flash */
|
/* Load the log from flash */
|
||||||
elog_scan_flash();
|
elog_scan_flash();
|
||||||
|
@ -579,7 +677,7 @@ int elog_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(BIOS_INFO, "ELOG: FLASH @0x%p [SPI 0x%08x]\n",
|
printk(BIOS_INFO, "ELOG: FLASH @0x%p [SPI 0x%08x]\n",
|
||||||
elog_area, flash_base);
|
mirror_buffer, flash_base);
|
||||||
|
|
||||||
printk(BIOS_INFO, "ELOG: area is %d bytes, full threshold %d,"
|
printk(BIOS_INFO, "ELOG: area is %d bytes, full threshold %d,"
|
||||||
" shrink size %d\n", total_size, full_threshold, shrink_size);
|
" shrink size %d\n", total_size, full_threshold, shrink_size);
|
||||||
|
@ -672,14 +770,14 @@ void elog_add_event_raw(u8 event_type, void *data, u8 data_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure event data can fit */
|
/* Make sure event data can fit */
|
||||||
if ((next_event_offset + event_size) >= log_size) {
|
event = elog_get_event_buffer(next_event_offset, event_size);
|
||||||
|
if (event == NULL) {
|
||||||
printk(BIOS_ERR, "ELOG: Event(%X) does not fit\n",
|
printk(BIOS_ERR, "ELOG: Event(%X) does not fit\n",
|
||||||
event_type);
|
event_type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill out event data */
|
/* Fill out event data */
|
||||||
event = elog_get_event_base(next_event_offset);
|
|
||||||
event->type = event_type;
|
event->type = event_type;
|
||||||
event->length = event_size;
|
event->length = event_size;
|
||||||
elog_fill_timestamp(event);
|
elog_fill_timestamp(event);
|
||||||
|
@ -690,6 +788,7 @@ void elog_add_event_raw(u8 event_type, void *data, u8 data_size)
|
||||||
/* Zero the checksum byte and then compute checksum */
|
/* Zero the checksum byte and then compute checksum */
|
||||||
elog_update_checksum(event, 0);
|
elog_update_checksum(event, 0);
|
||||||
elog_update_checksum(event, -(elog_checksum_event(event)));
|
elog_update_checksum(event, -(elog_checksum_event(event)));
|
||||||
|
elog_put_event_buffer(event);
|
||||||
|
|
||||||
/* Update the ELOG state */
|
/* Update the ELOG state */
|
||||||
event_count++;
|
event_count++;
|
||||||
|
|
|
@ -61,9 +61,4 @@ typedef enum elog_event_buffer_state {
|
||||||
ELOG_EVENT_BUFFER_CORRUPTED,
|
ELOG_EVENT_BUFFER_CORRUPTED,
|
||||||
} elog_event_buffer_state;
|
} elog_event_buffer_state;
|
||||||
|
|
||||||
struct elog_area {
|
|
||||||
struct elog_header header;
|
|
||||||
u8 data[0];
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
#endif /* ELOG_INTERNAL_H_ */
|
#endif /* ELOG_INTERNAL_H_ */
|
||||||
|
|
Loading…
Reference in New Issue