1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <commonlib/helpers.h>
4 #include <commonlib/region.h>
6 #include <console/console.h>
7 #include <console/flash.h>
10 #define LINE_BUFFER_SIZE 128
11 #define READ_BUFFER_SIZE 0x100
13 static const struct region_device
*rdev_ptr
;
14 static struct region_device rdev
;
15 static uint8_t line_buffer
[LINE_BUFFER_SIZE
];
17 static size_t line_offset
;
19 void flashconsole_init(void)
21 uint8_t buffer
[READ_BUFFER_SIZE
];
23 size_t initial_offset
= 0;
24 size_t len
= READ_BUFFER_SIZE
;
27 if (fmap_locate_area_as_rdev_rw("CONSOLE", &rdev
)) {
28 printk(BIOS_INFO
, "Can't find 'CONSOLE' area in FMAP\n");
31 size
= region_device_sz(&rdev
);
34 * We need to check the region until we find a 0xff indicating
35 * the end of a previous log write.
36 * We can't erase the region because one stage would erase the
37 * data from the previous stage. Also, it looks like doing an
38 * erase could completely freeze the SPI controller and then
39 * we can't write anything anymore (apparently might happen if
40 * the sector is already erased, so we would need to read
41 * anyways to check if it's all 0xff).
43 for (i
= 0; i
< len
&& initial_offset
< size
;) {
44 // Fill the buffer on first iteration
46 len
= MIN(READ_BUFFER_SIZE
, size
- offset
);
47 if (rdev_readat(&rdev
, buffer
, initial_offset
, len
) != len
)
50 if (buffer
[i
] == 0xff) {
54 // If we're done, repeat the process for the next sector
55 if (++i
== READ_BUFFER_SIZE
) {
56 initial_offset
+= len
;
60 // Make sure there is still space left on the console
61 if (initial_offset
>= size
) {
62 printk(BIOS_INFO
, "No space left on 'console' region in SPI flash\n");
66 offset
= initial_offset
;
70 void flashconsole_tx_byte(unsigned char c
)
75 size_t region_size
= region_device_sz(rdev_ptr
);
77 if (line_offset
< LINE_BUFFER_SIZE
)
78 line_buffer
[line_offset
++] = c
;
80 if (line_offset
>= LINE_BUFFER_SIZE
||
81 offset
+ line_offset
>= region_size
|| c
== '\n') {
82 flashconsole_tx_flush();
86 void flashconsole_tx_flush(void)
88 size_t len
= line_offset
;
92 /* Prevent any recursive loops in case the spi flash driver
93 * calls printk (in case of transaction timeout or
94 * any other error while writing) */
102 region_size
= region_device_sz(rdev_ptr
);
103 if (offset
+ len
>= region_size
)
104 len
= region_size
- offset
;
106 if (rdev_writeat(&rdev
, line_buffer
, offset
, len
) != len
)
109 // If the region is full, stop future write attempts
110 if (offset
+ len
>= region_size
)