From ce5c91534485c8181425449a6c2a286076c6d18c Mon Sep 17 00:00:00 2001 From: Nicholas Chin Date: Tue, 24 Feb 2026 23:29:17 -0700 Subject: [PATCH] drivers/spi/flashconsole.c: Fix flashconsole Commit 1f2408f57300 ("console: Fix flushing for slow consoles") fixed a typo related to some refactoring of the CBMEM fast code path. However, this also seems to have indirectly broken the SPI flash console, causing only the console header messages at the beginning of each stage to be stored. This is caused by multiple calls to flashconsole_tx_flush() without a call to flashconsole_tx_byte() in between them. Data is accumulated in a buffer during calls to flashconsole_tx_byte(), which is then written to the flash during a flush. If no tx calls occur between flushes, the second call will try to write data of length 0, which seems to cause rdev_writeat() to return -1. This causes an early return, since the return value of rdev_writeat() must match the data length in order for the rest of the flashconsole_tx_flush to run. The flush function contains a busy flag to prevent recursive calls to itself, and the early return prevents it from being reset. Thus, the busy flag remains set for the remainder of the stage, blocking all future flushes. The multiple flushes occur because vprintk flushes console drivers after the string has been sent, but flashconsole_tx_byte() also calls a flush whenever a newline is encountered. Because of this, flushes are disabled for the remainder of each stage after the first printk call containing a newline is stored to the flash console. Although this newline check could be omitted, flashconsole_tx_byte() also invokes a flush when its data buffer is full, which shouldn't be avoided. Prior to the mentioned commit, the incorrect logic happened to prevent the flush in vprintk, preventing the double flush issue from occurring. The mentioned commit inverted the logic, allowing the double flush to occur. Address this by returning early if len = 0. While we're here, consolidate the early returns into a single check and change the busy flag to a bool instead of an int. TEST=Console messages are not missing in the flashconsole. Tested on the Lenovo ThinkCentre M900 SFF. Change-Id: Ic6c2418f04a687610df020df117f7be90b1724b9 Signed-off-by: Nicholas Chin Reviewed-on: https://review.coreboot.org/c/coreboot/+/91428 Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) Reviewed-by: Patrick Rudolph Reviewed-by: Julius Werner --- src/drivers/spi/flashconsole.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/drivers/spi/flashconsole.c b/src/drivers/spi/flashconsole.c index 679c814dff..878cef0ce3 100644 --- a/src/drivers/spi/flashconsole.c +++ b/src/drivers/spi/flashconsole.c @@ -87,18 +87,20 @@ void flashconsole_tx_flush(void) { size_t len = line_offset; size_t region_size; - static int busy; /* Prevent any recursive loops in case the spi flash driver * calls printk (in case of transaction timeout or * any other error while writing) */ - if (busy) + static bool busy; + + /* In addition to being an obvious runtime optimization, checking for + * len = 0 also prevents false disabling of the driver, as rdev_writeat + * seems to return -1 if len is zero even though this should be a + * recoverable condition. */ + if (busy || !rdev_ptr || len == 0) return; - if (!rdev_ptr) - return; - - busy = 1; + busy = true; region_size = region_device_sz(rdev_ptr); if (offset + len >= region_size) len = region_size - offset; @@ -113,5 +115,5 @@ void flashconsole_tx_flush(void) offset += len; line_offset = 0; - busy = 0; + busy = false; }