{drivers,southbridge}: Replace min() with MIN()
[coreboot.git] / src / drivers / spi / flashconsole.c
blob80c63e07eadea02c4d06cf1a3bb8026361ba8cf4
1 /*
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>
17 #include <fmap.h>
18 #include <console/console.h>
19 #include <console/flash.h>
20 #include <types.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];
28 static size_t offset;
29 static size_t line_offset;
31 void flashconsole_init(void)
33 uint8_t buffer[READ_BUFFER_SIZE];
34 size_t size;
35 size_t offset = 0;
36 size_t len = READ_BUFFER_SIZE;
37 size_t i;
39 if (fmap_locate_area_as_rdev_rw("CONSOLE", &rdev)) {
40 printk(BIOS_INFO, "Can't find 'CONSOLE' area in FMAP\n");
41 return;
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
57 if (i == 0) {
58 len = MIN(READ_BUFFER_SIZE, size - offset);
59 if (rdev_readat(&rdev, buffer, offset, len) != len)
60 return;
62 if (buffer[i] == 0xff) {
63 offset += i;
64 break;
66 // If we're done, repeat the process for the next sector
67 if (++i == READ_BUFFER_SIZE) {
68 offset += len;
69 i = 0;
72 // Make sure there is still space left on the console
73 if (offset >= size) {
74 printk(BIOS_INFO, "No space left on 'console' region in SPI flash\n");
75 return;
78 offset = offset;
79 rdev_ptr = &rdev;
82 void flashconsole_tx_byte(unsigned char c)
84 if (!rdev_ptr)
85 return;
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;
101 size_t region_size;
102 static int busy;
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) */
107 if (busy)
108 return;
110 if (!rdev_ptr)
111 return;
113 busy = 1;
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)
119 return;
121 // If the region is full, stop future write attempts
122 if (offset + len >= region_size)
123 return;
125 offset = offset + len;
126 line_offset = 0;
128 busy = 0;