2 * This file is part of the coreboot project.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <commonlib/helpers.h>
15 #include <commonlib/region.h>
16 #include <boot_device.h>
18 #include <console/console.h>
19 #include <console/flash.h>
22 #define LINE_BUFFER_SIZE 128
23 #define READ_BUFFER_SIZE 0x100
25 static const struct region_device
*rdev_ptr
;
26 static struct region_device rdev
;
27 static uint8_t line_buffer
[LINE_BUFFER_SIZE
];
29 static size_t line_offset
;
31 void flashconsole_init(void)
33 uint8_t buffer
[READ_BUFFER_SIZE
];
36 size_t len
= READ_BUFFER_SIZE
;
39 if (fmap_locate_area_as_rdev_rw("CONSOLE", &rdev
)) {
40 printk(BIOS_INFO
, "Can't find 'CONSOLE' area in FMAP\n");
43 size
= region_device_sz(&rdev
);
46 * We need to check the region until we find a 0xff indicating
47 * the end of a previous log write.
48 * We can't erase the region because one stage would erase the
49 * data from the previous stage. Also, it looks like doing an
50 * erase could completely freeze the SPI controller and then
51 * we can't write anything anymore (apparently might happen if
52 * the sector is already erased, so we would need to read
53 * anyways to check if it's all 0xff).
55 for (i
= 0; i
< len
&& offset
< size
;) {
56 // Fill the buffer on first iteration
58 len
= MIN(READ_BUFFER_SIZE
, size
- offset
);
59 if (rdev_readat(&rdev
, buffer
, offset
, len
) != len
)
62 if (buffer
[i
] == 0xff) {
66 // If we're done, repeat the process for the next sector
67 if (++i
== READ_BUFFER_SIZE
) {
72 // Make sure there is still space left on the console
74 printk(BIOS_INFO
, "No space left on 'console' region in SPI flash\n");
82 void flashconsole_tx_byte(unsigned char c
)
87 size_t region_size
= region_device_sz(rdev_ptr
);
89 line_buffer
[line_offset
++] = c
;
91 if (line_offset
>= LINE_BUFFER_SIZE
||
92 offset
+ line_offset
>= region_size
|| c
== '\n') {
93 flashconsole_tx_flush();
97 void flashconsole_tx_flush(void)
99 size_t offset
= offset
;
100 size_t len
= line_offset
;
104 /* Prevent any recursive loops in case the spi flash driver
105 * calls printk (in case of transaction timeout or
106 * any other error while writing) */
114 region_size
= region_device_sz(rdev_ptr
);
115 if (offset
+ len
>= region_size
)
116 len
= region_size
- offset
;
118 if (rdev_writeat(&rdev
, line_buffer
, offset
, len
) != len
)
121 // If the region is full, stop future write attempts
122 if (offset
+ len
>= region_size
)
125 offset
= offset
+ len
;