elog: Get rid of the descriptor type and some unnecessary wrappers
There was always exactly one elog descriptor declared and initialized, but its contents were being accessed through a pointer that was passed back and forth between functions instead of being accessed directly. This made the code more verbose than it needed to be and harder to follow. To address this the descriptor type was eliminated, its contents were turned into individual global variables, and various functions were adjusted to no longer take the descriptor as an argument. Similarly, the code was more verbose and complicated than it needed to be because of several wrapper functions which wrapped a single line of code which called an underlying function with particular arguments and were only used once. This makes it harder to tell what the code is doing because the call to the real function you may already be familiar with is obscured behind a new function you've never seen before. It also adds one more text to the file as a whole while providing at best a marginal benefit. Those functions were removed and their callers now call their contents directly. Built and booted on Link. Ran mosys eventlog list. Cleared the event log and ran mosys eventlog list again. Added 2000 events and ran mosys eventlog list. Cleared the log again and ran mosys eventlog list. Change-Id: I4f5f6b9f4f508548077b7f5a92f4322db99e01ca Signed-off-by: Gabe Black <gabeblack@google.com> Reviewed-on: https://gerrit.chromium.org/gerrit/49310 Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Commit-Queue: Gabe Black <gabeblack@chromium.org> Tested-by: Gabe Black <gabeblack@chromium.org> Reviewed-on: http://review.coreboot.org/4245 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
parent
84a93d1bc3
commit
0bf1febed8
|
@ -57,14 +57,20 @@
|
||||||
/*
|
/*
|
||||||
* Static variables for ELOG state
|
* Static variables for ELOG state
|
||||||
*/
|
*/
|
||||||
|
static struct elog_area *elog_area;
|
||||||
|
static u16 total_size;
|
||||||
|
static u16 log_size;
|
||||||
|
static u32 flash_base;
|
||||||
|
|
||||||
|
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;
|
||||||
|
static u16 event_count;
|
||||||
|
|
||||||
static int elog_initialized;
|
static int elog_initialized;
|
||||||
static struct spi_flash *elog_spi;
|
static struct spi_flash *elog_spi;
|
||||||
static struct elog_descriptor elog_flash_area;
|
|
||||||
|
|
||||||
static inline struct elog_descriptor* elog_get_flash(void)
|
|
||||||
{
|
|
||||||
return &elog_flash_area;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a memory mapped flash address into a flash offset
|
* Convert a memory mapped flash address into a flash offset
|
||||||
|
@ -86,31 +92,13 @@ static inline u8* elog_flash_offset_to_address(u32 offset)
|
||||||
return (u8*)((u32)~0UL - elog_spi->size + 1 + offset);
|
return (u8*)((u32)~0UL - elog_spi->size + 1 + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* The ELOG header is at the very beginning of the area
|
|
||||||
*/
|
|
||||||
static inline struct elog_header*
|
|
||||||
elog_get_header(struct elog_descriptor *elog)
|
|
||||||
{
|
|
||||||
return elog->backing_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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 inline struct event_header*
|
||||||
elog_get_event_base(struct elog_descriptor *elog, u32 offset)
|
elog_get_event_base(u32 offset)
|
||||||
{
|
{
|
||||||
return (struct event_header *)&elog->data[offset];
|
return (struct event_header *)&elog_area->data[offset];
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Pointer to where the next event should be stored
|
|
||||||
*/
|
|
||||||
static inline struct event_header*
|
|
||||||
elog_get_next_event_base(struct elog_descriptor *elog)
|
|
||||||
{
|
|
||||||
return elog_get_event_base(elog, elog->next_event_offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -138,7 +126,7 @@ static u8 elog_checksum_event(struct event_header *event)
|
||||||
/*
|
/*
|
||||||
* Check if a raw buffer is filled with ELOG_TYPE_EOL byte
|
* Check if a raw buffer is filled with ELOG_TYPE_EOL byte
|
||||||
*/
|
*/
|
||||||
static int elog_is_buffer_clear(u8 *base, u32 size)
|
static int elog_is_buffer_clear(void *base, u32 size)
|
||||||
{
|
{
|
||||||
u8 *current = base;
|
u8 *current = base;
|
||||||
u8 *end = current + size;
|
u8 *end = current + size;
|
||||||
|
@ -152,26 +140,18 @@ static int elog_is_buffer_clear(u8 *base, u32 size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Verify whether ELOG area is filled with ELOG_TYPE_EOL byte
|
|
||||||
*/
|
|
||||||
static int elog_is_area_clear(struct elog_descriptor *elog)
|
|
||||||
{
|
|
||||||
return elog_is_buffer_clear(elog->backing_store, elog->total_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the ELOG area has been initialized and is valid.
|
* Check that the ELOG area has been initialized and is valid.
|
||||||
*/
|
*/
|
||||||
static int elog_is_area_valid(struct elog_descriptor *elog)
|
static int elog_is_area_valid(void)
|
||||||
{
|
{
|
||||||
elog_debug("elog_is_area_valid()\n");
|
elog_debug("elog_is_area_valid()\n");
|
||||||
|
|
||||||
if (elog->area_state != ELOG_AREA_HAS_CONTENT)
|
if (area_state != ELOG_AREA_HAS_CONTENT)
|
||||||
return 0;
|
return 0;
|
||||||
if (elog->header_state != ELOG_HEADER_VALID)
|
if (header_state != ELOG_HEADER_VALID)
|
||||||
return 0;
|
return 0;
|
||||||
if (elog->event_buffer_state != ELOG_EVENT_BUFFER_OK)
|
if (event_buffer_state != ELOG_EVENT_BUFFER_OK)
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -205,17 +185,17 @@ 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(struct elog_descriptor *elog, u32 offset)
|
static int elog_is_event_valid(u32 offset)
|
||||||
{
|
{
|
||||||
struct event_header *event;
|
struct event_header *event;
|
||||||
|
|
||||||
event = elog_get_event_base(elog, offset);
|
event = elog_get_event_base(offset);
|
||||||
if (!event)
|
if (!event)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Validate event length */
|
/* Validate event length */
|
||||||
if ((offsetof(struct event_header, type) +
|
if ((offsetof(struct event_header, type) +
|
||||||
sizeof(event->type) - 1 + offset) >= elog->data_size)
|
sizeof(event->type) - 1 + offset) >= log_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* End of event marker has been found */
|
/* End of event marker has been found */
|
||||||
|
@ -224,14 +204,14 @@ static int elog_is_event_valid(struct elog_descriptor *elog, u32 offset)
|
||||||
|
|
||||||
/* Check if event fits in area */
|
/* Check if event fits in area */
|
||||||
if ((offsetof(struct event_header, length) +
|
if ((offsetof(struct event_header, length) +
|
||||||
sizeof(event->length) - 1 + offset) >= elog->data_size)
|
sizeof(event->length) - 1 + offset) >= log_size)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the current event length + the current offset exceeds
|
* If the current event length + the current offset exceeds
|
||||||
* the area size then the event area is corrupt.
|
* the area size then the event area is corrupt.
|
||||||
*/
|
*/
|
||||||
if ((event->length + offset) >= elog->data_size)
|
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 */
|
||||||
|
@ -251,16 +231,15 @@ static int elog_is_event_valid(struct elog_descriptor *elog, u32 offset)
|
||||||
* store into flash. This will not erase the flash and it assumes the flash
|
* store into flash. This will not erase the flash and it assumes the flash
|
||||||
* area has been erased appropriately.
|
* area has been erased appropriately.
|
||||||
*/
|
*/
|
||||||
static void elog_flash_write(u8 *address, u32 size)
|
static void elog_flash_write(void *address, u32 size)
|
||||||
{
|
{
|
||||||
struct elog_descriptor *flash = elog_get_flash();
|
|
||||||
u32 offset;
|
u32 offset;
|
||||||
|
|
||||||
if (!address || !size || !elog_spi)
|
if (!address || !size || !elog_spi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
offset = flash->flash_base;
|
offset = flash_base;
|
||||||
offset += address - (u8*)flash->backing_store;
|
offset += (u8 *)address - (u8 *)elog_area;
|
||||||
|
|
||||||
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);
|
||||||
|
@ -273,16 +252,15 @@ static void elog_flash_write(u8 *address, u32 size)
|
||||||
* Erase the first block specified in the address.
|
* Erase the first block specified in the address.
|
||||||
* Only handles flash area within a single flash block.
|
* Only handles flash area within a single flash block.
|
||||||
*/
|
*/
|
||||||
static void elog_flash_erase(u8 *address, u32 size)
|
static void elog_flash_erase(void *address, u32 size)
|
||||||
{
|
{
|
||||||
struct elog_descriptor *flash = elog_get_flash();
|
|
||||||
u32 offset;
|
u32 offset;
|
||||||
|
|
||||||
if (!address || !size || !elog_spi)
|
if (!address || !size || !elog_spi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
offset = flash->flash_base;
|
offset = flash_base;
|
||||||
offset += address - (u8*)flash->backing_store;
|
offset += (u8 *)address - (u8*)elog_area;
|
||||||
|
|
||||||
elog_debug("elog_flash_erase(address=0x%p offset=0x%08x size=%u)\n",
|
elog_debug("elog_flash_erase(address=0x%p offset=0x%08x size=%u)\n",
|
||||||
address, offset, size);
|
address, offset, size);
|
||||||
|
@ -292,10 +270,9 @@ static void elog_flash_erase(u8 *address, u32 size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the event area and validate each entry and
|
* Scan the event area and validate each entry and update the ELOG state.
|
||||||
* update the ELOG descriptor state.
|
|
||||||
*/
|
*/
|
||||||
static void elog_update_event_buffer_state(struct elog_descriptor *elog)
|
static void elog_update_event_buffer_state(void)
|
||||||
{
|
{
|
||||||
u32 count = 0;
|
u32 count = 0;
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
@ -305,12 +282,12 @@ static void elog_update_event_buffer_state(struct elog_descriptor *elog)
|
||||||
|
|
||||||
/* Go through each event and validate it */
|
/* Go through each event and validate it */
|
||||||
while (1) {
|
while (1) {
|
||||||
event = elog_get_event_base(elog, offset);
|
event = elog_get_event_base(offset);
|
||||||
|
|
||||||
/* Do not de-reference anything past the area length */
|
/* Do not de-reference anything past the area length */
|
||||||
if ((offsetof(struct event_header, type) +
|
if ((offsetof(struct event_header, type) +
|
||||||
sizeof(event->type) - 1 + offset) >= elog->data_size) {
|
sizeof(event->type) - 1 + offset) >= log_size) {
|
||||||
elog->event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,8 +296,8 @@ static void elog_update_event_buffer_state(struct elog_descriptor *elog)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Validate the event */
|
/* Validate the event */
|
||||||
if (!elog_is_event_valid(elog, offset)) {
|
if (!elog_is_event_valid(offset)) {
|
||||||
elog->event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,67 +307,62 @@ static void elog_update_event_buffer_state(struct elog_descriptor *elog)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the remaining buffer is empty */
|
/* Ensure the remaining buffer is empty */
|
||||||
if (!elog_is_buffer_clear(&elog->data[offset],
|
if (!elog_is_buffer_clear(&elog_area->data[offset], log_size - offset))
|
||||||
elog->data_size - offset))
|
event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
||||||
elog->event_buffer_state = ELOG_EVENT_BUFFER_CORRUPTED;
|
|
||||||
|
|
||||||
/* Update data into elog descriptor */
|
/* Update ELOG state */
|
||||||
elog->event_count = count;
|
event_count = count;
|
||||||
elog->next_event_offset = offset;
|
next_event_offset = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void elog_scan_flash(void)
|
||||||
* (Re)initialize a new ELOG descriptor
|
|
||||||
*/
|
|
||||||
static void elog_scan_flash(struct elog_descriptor *elog)
|
|
||||||
{
|
{
|
||||||
elog_debug("elog_scan_flash()\n");
|
elog_debug("elog_scan_flash()\n");
|
||||||
|
|
||||||
elog->area_state = ELOG_AREA_UNDEFINED;
|
area_state = ELOG_AREA_UNDEFINED;
|
||||||
elog->header_state = ELOG_HEADER_INVALID;
|
header_state = ELOG_HEADER_INVALID;
|
||||||
elog->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, elog->flash_base, elog->total_size,
|
elog_spi->read(elog_spi, flash_base, total_size, elog_area);
|
||||||
elog->backing_store);
|
|
||||||
|
|
||||||
elog->next_event_offset = 0;
|
next_event_offset = 0;
|
||||||
elog->event_count = 0;
|
event_count = 0;
|
||||||
|
|
||||||
/* Check if the area is empty or not */
|
/* Check if the area is empty or not */
|
||||||
if (elog_is_area_clear(elog)) {
|
if (elog_is_buffer_clear(elog_area, total_size)) {
|
||||||
elog->area_state = ELOG_AREA_EMPTY;
|
area_state = ELOG_AREA_EMPTY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
elog->area_state = ELOG_AREA_HAS_CONTENT;
|
area_state = ELOG_AREA_HAS_CONTENT;
|
||||||
|
|
||||||
/* Validate the header */
|
/* Validate the header */
|
||||||
if (!elog_is_header_valid(elog_get_header(elog))) {
|
if (!elog_is_header_valid(&elog_area->header)) {
|
||||||
elog->header_state = ELOG_HEADER_INVALID;
|
header_state = ELOG_HEADER_INVALID;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
elog->header_state = ELOG_HEADER_VALID;
|
header_state = ELOG_HEADER_VALID;
|
||||||
elog_update_event_buffer_state(elog);
|
elog_update_event_buffer_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elog_prepare_empty(struct elog_descriptor *elog)
|
static void elog_prepare_empty(void)
|
||||||
{
|
{
|
||||||
struct elog_header *header;
|
struct elog_header *header;
|
||||||
|
|
||||||
elog_debug("elog_prepare_empty(%u bytes)\n", data_size);
|
elog_debug("elog_prepare_empty()\n");
|
||||||
|
|
||||||
/* Write out the header */
|
/* Write out the header */
|
||||||
header = elog_get_header(elog);
|
header = &elog_area->header;
|
||||||
header->magic = ELOG_SIGNATURE;
|
header->magic = ELOG_SIGNATURE;
|
||||||
header->version = ELOG_VERSION;
|
header->version = ELOG_VERSION;
|
||||||
header->header_size = sizeof(struct elog_header);
|
header->header_size = sizeof(struct elog_header);
|
||||||
header->reserved[0] = ELOG_TYPE_EOL;
|
header->reserved[0] = ELOG_TYPE_EOL;
|
||||||
header->reserved[1] = ELOG_TYPE_EOL;
|
header->reserved[1] = ELOG_TYPE_EOL;
|
||||||
elog_flash_write(elog->backing_store, header->header_size);
|
elog_flash_write(elog_area, header->header_size);
|
||||||
|
|
||||||
elog_scan_flash(elog);
|
elog_scan_flash();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -399,7 +371,6 @@ static void elog_prepare_empty(struct elog_descriptor *elog)
|
||||||
*/
|
*/
|
||||||
static int elog_shrink(void)
|
static int elog_shrink(void)
|
||||||
{
|
{
|
||||||
struct elog_descriptor *flash = elog_get_flash();
|
|
||||||
struct event_header *event;
|
struct event_header *event;
|
||||||
u16 discard_count = 0;
|
u16 discard_count = 0;
|
||||||
u16 offset = 0;
|
u16 offset = 0;
|
||||||
|
@ -407,7 +378,7 @@ static int elog_shrink(void)
|
||||||
|
|
||||||
elog_debug("elog_shrink()\n");
|
elog_debug("elog_shrink()\n");
|
||||||
|
|
||||||
if (flash->next_event_offset < CONFIG_ELOG_SHRINK_SIZE)
|
if (next_event_offset < CONFIG_ELOG_SHRINK_SIZE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -415,7 +386,7 @@ static int elog_shrink(void)
|
||||||
if (offset > CONFIG_ELOG_SHRINK_SIZE)
|
if (offset > CONFIG_ELOG_SHRINK_SIZE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
event = elog_get_event_base(flash, offset);
|
event = elog_get_event_base(offset);
|
||||||
|
|
||||||
/* Reached the end of the area */
|
/* Reached the end of the area */
|
||||||
if (!event || event->type == ELOG_TYPE_EOL)
|
if (!event || event->type == ELOG_TYPE_EOL)
|
||||||
|
@ -425,17 +396,16 @@ static int elog_shrink(void)
|
||||||
discard_count++;
|
discard_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_size = flash->next_event_offset - offset;
|
new_size = next_event_offset - offset;
|
||||||
memmove(&flash->data[0], &flash->data[offset], new_size);
|
memmove(&elog_area->data[0], &elog_area->data[offset], new_size);
|
||||||
memset(&flash->data[new_size], ELOG_TYPE_EOL,
|
memset(&elog_area->data[new_size], ELOG_TYPE_EOL, log_size - new_size);
|
||||||
flash->data_size - new_size);
|
|
||||||
|
|
||||||
elog_flash_erase(flash->backing_store, flash->total_size);
|
elog_flash_erase(elog_area, total_size);
|
||||||
elog_flash_write(flash->backing_store, flash->total_size);
|
elog_flash_write(elog_area, total_size);
|
||||||
elog_scan_flash(flash);
|
elog_scan_flash();
|
||||||
|
|
||||||
/* Ensure the area was successfully erased */
|
/* Ensure the area was successfully erased */
|
||||||
if (flash->next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD) {
|
if (next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD) {
|
||||||
printk(BIOS_ERR, "ELOG: Flash area was not erased!\n");
|
printk(BIOS_ERR, "ELOG: Flash area was not erased!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -453,23 +423,22 @@ static int elog_shrink(void)
|
||||||
*/
|
*/
|
||||||
int elog_smbios_write_type15(unsigned long *current, int handle)
|
int elog_smbios_write_type15(unsigned long *current, int handle)
|
||||||
{
|
{
|
||||||
struct elog_descriptor *flash = elog_get_flash();
|
|
||||||
struct smbios_type15 *t = (struct smbios_type15 *)*current;
|
struct smbios_type15 *t = (struct smbios_type15 *)*current;
|
||||||
int len = sizeof(struct smbios_type15);
|
int len = sizeof(struct smbios_type15);
|
||||||
|
|
||||||
#if CONFIG_ELOG_CBMEM
|
#if CONFIG_ELOG_CBMEM
|
||||||
/* Save event log buffer into CBMEM for the OS to read */
|
/* Save event log buffer into CBMEM for the OS to read */
|
||||||
void *cbmem = cbmem_add(CBMEM_ID_ELOG, flash->total_size);
|
void *cbmem = cbmem_add(CBMEM_ID_ELOG, total_size);
|
||||||
if (!cbmem)
|
if (!cbmem)
|
||||||
return 0;
|
return 0;
|
||||||
memcpy(cbmem, flash->backing_store, flash->total_size);
|
memcpy(cbmem, elog_area, total_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(t, 0, len);
|
memset(t, 0, len);
|
||||||
t->type = SMBIOS_EVENT_LOG;
|
t->type = SMBIOS_EVENT_LOG;
|
||||||
t->length = len - 2;
|
t->length = len - 2;
|
||||||
t->handle = handle;
|
t->handle = handle;
|
||||||
t->area_length = flash->total_size - 1;
|
t->area_length = total_size - 1;
|
||||||
t->header_offset = 0;
|
t->header_offset = 0;
|
||||||
t->data_offset = sizeof(struct elog_header);
|
t->data_offset = sizeof(struct elog_header);
|
||||||
t->access_method = SMBIOS_EVENTLOG_ACCESS_METHOD_MMIO32;
|
t->access_method = SMBIOS_EVENTLOG_ACCESS_METHOD_MMIO32;
|
||||||
|
@ -478,7 +447,7 @@ int elog_smbios_write_type15(unsigned long *current, int handle)
|
||||||
#if CONFIG_ELOG_CBMEM
|
#if CONFIG_ELOG_CBMEM
|
||||||
t->address = (u32)cbmem;
|
t->address = (u32)cbmem;
|
||||||
#else
|
#else
|
||||||
t->address = (u32)elog_flash_offset_to_address(flash->flash_base);
|
t->address = (u32)elog_flash_offset_to_address(flash_base);
|
||||||
#endif
|
#endif
|
||||||
t->header_format = ELOG_HEADER_TYPE_OEM;
|
t->header_format = ELOG_HEADER_TYPE_OEM;
|
||||||
t->log_type_descriptors = 0;
|
t->log_type_descriptors = 0;
|
||||||
|
@ -494,8 +463,6 @@ int elog_smbios_write_type15(unsigned long *current, int handle)
|
||||||
*/
|
*/
|
||||||
int elog_clear(void)
|
int elog_clear(void)
|
||||||
{
|
{
|
||||||
struct elog_descriptor *flash = elog_get_flash();
|
|
||||||
|
|
||||||
elog_debug("elog_clear()\n");
|
elog_debug("elog_clear()\n");
|
||||||
|
|
||||||
/* Make sure ELOG structures are initialized */
|
/* Make sure ELOG structures are initialized */
|
||||||
|
@ -503,44 +470,45 @@ int elog_clear(void)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Erase flash area */
|
/* Erase flash area */
|
||||||
elog_flash_erase(flash->backing_store, flash->total_size);
|
elog_flash_erase(elog_area, total_size);
|
||||||
elog_prepare_empty(flash);
|
elog_prepare_empty();
|
||||||
|
|
||||||
if (!elog_is_area_valid(flash))
|
if (!elog_is_area_valid())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Log the clear event */
|
/* Log the clear event */
|
||||||
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, flash->total_size);
|
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, total_size);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void elog_find_flash(u32 *base, int *size)
|
static void elog_find_flash(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_CHROMEOS
|
#if CONFIG_CHROMEOS
|
||||||
u8 *flash_base_ptr;
|
u8 *flash_base_ptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
elog_debug("elog_find_flash(base = %p, size = %p)\n", base, size);
|
elog_debug("elog_find_flash()\n");
|
||||||
|
|
||||||
#if CONFIG_CHROMEOS
|
#if CONFIG_CHROMEOS
|
||||||
/* Find the ELOG base and size in FMAP */
|
/* Find the ELOG base and size in FMAP */
|
||||||
*size = find_fmap_entry("RW_ELOG", (void **)&flash_base_ptr);
|
total_size = find_fmap_entry("RW_ELOG", (void **)&flash_base_ptr);
|
||||||
if (*size < 0) {
|
if (total_size < 0) {
|
||||||
printk(BIOS_WARNING, "ELOG: Unable to find RW_ELOG in FMAP, "
|
printk(BIOS_WARNING, "ELOG: Unable to find RW_ELOG in FMAP, "
|
||||||
"using CONFIG_ELOG_FLASH_BASE instead\n");
|
"using CONFIG_ELOG_FLASH_BASE instead\n");
|
||||||
*size = CONFIG_ELOG_AREA_SIZE;
|
total_size = CONFIG_ELOG_AREA_SIZE;
|
||||||
} else {
|
} else {
|
||||||
*base = elog_flash_address_to_offset(flash_base_ptr);
|
flash_base = elog_flash_address_to_offset(flash_base_ptr);
|
||||||
|
|
||||||
/* Use configured size if smaller than FMAP size */
|
/* Use configured size if smaller than FMAP size */
|
||||||
if (*size > CONFIG_ELOG_AREA_SIZE)
|
if (total_size > CONFIG_ELOG_AREA_SIZE)
|
||||||
*size = CONFIG_ELOG_AREA_SIZE;
|
total_size = CONFIG_ELOG_AREA_SIZE;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
*base = CONFIG_ELOG_FLASH_BASE;
|
flash_base = CONFIG_ELOG_FLASH_BASE;
|
||||||
*size = CONFIG_ELOG_AREA_SIZE;
|
total_size = CONFIG_ELOG_AREA_SIZE;
|
||||||
#endif
|
#endif
|
||||||
|
log_size = total_size - sizeof(struct elog_header);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -548,10 +516,6 @@ static void elog_find_flash(u32 *base, int *size)
|
||||||
*/
|
*/
|
||||||
int elog_init(void)
|
int elog_init(void)
|
||||||
{
|
{
|
||||||
struct elog_descriptor *flash = elog_get_flash();
|
|
||||||
u32 flash_base = CONFIG_ELOG_FLASH_BASE;
|
|
||||||
int flash_size = CONFIG_ELOG_AREA_SIZE;
|
|
||||||
|
|
||||||
if (elog_initialized)
|
if (elog_initialized)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -566,41 +530,35 @@ int elog_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up the backing store */
|
/* Set up the backing store */
|
||||||
elog_find_flash(&flash_base, &flash_size);
|
elog_find_flash();
|
||||||
if (flash_base == 0) {
|
if (flash_base == 0) {
|
||||||
printk(BIOS_ERR, "ELOG: Invalid flash base\n");
|
printk(BIOS_ERR, "ELOG: Invalid flash base\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
flash->backing_store = malloc(flash_size);
|
elog_area = malloc(total_size);
|
||||||
if (!flash->backing_store) {
|
if (!elog_area) {
|
||||||
printk(BIOS_ERR, "ELOG: Unable to allocate backing store\n");
|
printk(BIOS_ERR, "ELOG: Unable to allocate backing store\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
flash->flash_base = flash_base;
|
|
||||||
flash->total_size = flash_size;
|
|
||||||
|
|
||||||
/* Data starts immediately after header */
|
|
||||||
flash->data = flash->backing_store + sizeof(struct elog_header);
|
|
||||||
flash->data_size = flash_size - sizeof(struct elog_header);
|
|
||||||
|
|
||||||
/* Load the log from flash */
|
/* Load the log from flash */
|
||||||
elog_scan_flash(flash);
|
elog_scan_flash();
|
||||||
|
|
||||||
/* Prepare the flash if necessary */
|
/* Prepare the flash if necessary */
|
||||||
if (flash->header_state == ELOG_HEADER_INVALID ||
|
if (header_state == ELOG_HEADER_INVALID ||
|
||||||
flash->event_buffer_state == ELOG_EVENT_BUFFER_CORRUPTED) {
|
event_buffer_state == ELOG_EVENT_BUFFER_CORRUPTED) {
|
||||||
/* If the header is invalid or the events are corrupted,
|
/* If the header is invalid or the events are corrupted,
|
||||||
* no events can be salvaged so erase the entire area. */
|
* no events can be salvaged so erase the entire area. */
|
||||||
printk(BIOS_ERR, "ELOG: flash area invalid\n");
|
printk(BIOS_ERR, "ELOG: flash area invalid\n");
|
||||||
elog_flash_erase(flash->backing_store, flash->total_size);
|
elog_flash_erase(elog_area, total_size);
|
||||||
elog_prepare_empty(flash);
|
elog_prepare_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flash->area_state == ELOG_AREA_EMPTY)
|
if (area_state == ELOG_AREA_EMPTY)
|
||||||
elog_prepare_empty(flash);
|
elog_prepare_empty();
|
||||||
|
|
||||||
if (!elog_is_area_valid(flash)) {
|
if (!elog_is_area_valid()) {
|
||||||
printk(BIOS_ERR, "ELOG: Unable to prepare flash\n");
|
printk(BIOS_ERR, "ELOG: Unable to prepare flash\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -608,18 +566,18 @@ int elog_init(void)
|
||||||
elog_initialized = 1;
|
elog_initialized = 1;
|
||||||
|
|
||||||
printk(BIOS_INFO, "ELOG: FLASH @0x%p [SPI 0x%08x]\n",
|
printk(BIOS_INFO, "ELOG: FLASH @0x%p [SPI 0x%08x]\n",
|
||||||
flash->backing_store, flash->flash_base);
|
elog_area, 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", flash_size,
|
" shrink size %d\n", total_size,
|
||||||
CONFIG_ELOG_FULL_THRESHOLD, CONFIG_ELOG_SHRINK_SIZE);
|
CONFIG_ELOG_FULL_THRESHOLD, CONFIG_ELOG_SHRINK_SIZE);
|
||||||
|
|
||||||
/* Log a clear event if necessary */
|
/* Log a clear event if necessary */
|
||||||
if (flash->event_count == 0)
|
if (event_count == 0)
|
||||||
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, flash->total_size);
|
elog_add_event_word(ELOG_TYPE_LOG_CLEAR, total_size);
|
||||||
|
|
||||||
/* Shrink the log if we are getting too full */
|
/* Shrink the log if we are getting too full */
|
||||||
if (flash->next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD)
|
if (next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD)
|
||||||
if (elog_shrink() < 0)
|
if (elog_shrink() < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -666,7 +624,6 @@ static void elog_fill_timestamp(struct event_header *event)
|
||||||
void elog_add_event_raw(u8 event_type, void *data, u8 data_size)
|
void elog_add_event_raw(u8 event_type, void *data, u8 data_size)
|
||||||
{
|
{
|
||||||
struct event_header *event;
|
struct event_header *event;
|
||||||
struct elog_descriptor *flash = elog_get_flash();
|
|
||||||
u8 event_size;
|
u8 event_size;
|
||||||
|
|
||||||
elog_debug("elog_add_event_raw(type=%X)\n", event_type);
|
elog_debug("elog_add_event_raw(type=%X)\n", event_type);
|
||||||
|
@ -684,14 +641,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 ((flash->next_event_offset + event_size) >= flash->data_size) {
|
if ((next_event_offset + event_size) >= log_size) {
|
||||||
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_next_event_base(flash);
|
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);
|
||||||
|
@ -703,18 +660,18 @@ void elog_add_event_raw(u8 event_type, void *data, u8 data_size)
|
||||||
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)));
|
||||||
|
|
||||||
/* Update memory descriptor parameters */
|
/* Update the ELOG state */
|
||||||
flash->event_count++;
|
event_count++;
|
||||||
|
|
||||||
elog_flash_write((void *)event, event_size);
|
elog_flash_write((void *)event, event_size);
|
||||||
|
|
||||||
flash->next_event_offset += event_size;
|
next_event_offset += event_size;
|
||||||
|
|
||||||
printk(BIOS_INFO, "ELOG: Event(%X) added with size %d\n",
|
printk(BIOS_INFO, "ELOG: Event(%X) added with size %d\n",
|
||||||
event_type, event_size);
|
event_type, event_size);
|
||||||
|
|
||||||
/* Shrink the log if we are getting too full */
|
/* Shrink the log if we are getting too full */
|
||||||
if (flash->next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD)
|
if (next_event_offset >= CONFIG_ELOG_FULL_THRESHOLD)
|
||||||
elog_shrink();
|
elog_shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,20 +63,9 @@ 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 {
|
||||||
* Internal handler for event log buffers
|
struct elog_header header;
|
||||||
*/
|
u8 data[0];
|
||||||
struct elog_descriptor {
|
} __attribute__((packed));
|
||||||
elog_area_state area_state;
|
|
||||||
elog_header_state header_state;
|
|
||||||
elog_event_buffer_state event_buffer_state;
|
|
||||||
void *backing_store;
|
|
||||||
u8 *data;
|
|
||||||
u32 flash_base;
|
|
||||||
u16 total_size;
|
|
||||||
u16 data_size;
|
|
||||||
u16 next_event_offset;
|
|
||||||
u16 event_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* ELOG_INTERNAL_H_ */
|
#endif /* ELOG_INTERNAL_H_ */
|
||||||
|
|
Loading…
Reference in New Issue