drivers/elog: treat offsets relative to start of mirror
Instead of treating offsets relative to after the header make the offsets relative to the in-memory mirror buffer. This simplifies the logic in that all offsets are treated the same. It also allows one to remove a global variable. BUG=chrome-os-partner:55932 Change-Id: I42491e05755d414562b02b6f9ae47f5c357d2f8a Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/16098 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh <furquan@google.com> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
		
				
					committed by
					
						 Martin Roth
						Martin Roth
					
				
			
			
				
	
			
			
			
						parent
						
							281c994ce2
						
					
				
				
					commit
					f41a9a6459
				
			| @@ -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; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user