soc/intel/xeon_sp/util: Enhance lock_pam0123
[coreboot2.git] / payloads / libpayload / drivers / cbmem_console.c
blobc243d5e88daa08825d9a0b6329e15a52958155fd
1 /*
3 * Copyright (c) 2012 Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include <libpayload.h>
30 #include <stdint.h>
32 struct cbmem_console {
33 uint32_t size;
34 uint32_t cursor;
35 uint8_t body[];
36 } __packed;
38 #define CURSOR_MASK ((1 << 28) - 1)
39 #define OVERFLOW (1 << 31)
41 static uintptr_t cbmem_console_p;
43 static struct console_output_driver cbmem_console_driver =
45 .write = &cbmem_console_write,
48 static void do_write(const void *buffer, size_t count)
50 struct cbmem_console *const cbmem_cons = phys_to_virt(cbmem_console_p);
52 memcpy(cbmem_cons->body + (cbmem_cons->cursor & CURSOR_MASK), buffer, count);
53 cbmem_cons->cursor += count;
56 void cbmem_console_init(void)
58 const struct cbmem_console *const cbmem_cons = phys_to_virt(lib_sysinfo.cbmem_cons);
60 cbmem_console_p = lib_sysinfo.cbmem_cons;
62 if (cbmem_console_p && cbmem_cons->size)
63 console_add_output_driver(&cbmem_console_driver);
66 void cbmem_console_write(const void *buffer, size_t count)
68 struct cbmem_console *const cbmem_cons = phys_to_virt(cbmem_console_p);
70 while ((cbmem_cons->cursor & CURSOR_MASK) + count >=
71 cbmem_cons->size) {
72 size_t still_fits = cbmem_cons->size - (cbmem_cons->cursor & CURSOR_MASK);
73 do_write(buffer, still_fits);
74 cbmem_cons->cursor &= ~CURSOR_MASK;
75 cbmem_cons->cursor |= OVERFLOW;
76 buffer += still_fits;
77 count -= still_fits;
80 do_write(buffer, count);
83 static void snapshot_putc(char *console, uint32_t *cursor, char c)
85 /* This is BIOS_LOG_IS_MARKER() from coreboot. Due to stupid
86 licensing restrictions, we can't use it directly. */
87 if (c >= 0x10 && c <= 0x18)
88 return;
90 /* Slight memory corruption may occur between reboots and give us a few
91 unprintable characters like '\0'. Replace them with '?' on output. */
92 if (!isprint(c) && !isspace(c))
93 console[*cursor] = '?';
94 else
95 console[*cursor] = c;
97 *cursor += 1;
100 char *cbmem_console_snapshot(void)
102 const struct cbmem_console *const console_p = phys_to_virt(cbmem_console_p);
103 char *console_c;
104 uint32_t size, cursor, overflow, newc, oldc;
106 if (!console_p) {
107 printf("ERROR: No cbmem console found in coreboot table\n");
108 return NULL;
111 cursor = console_p->cursor & CURSOR_MASK;
112 overflow = console_p->cursor & OVERFLOW;
113 if (!overflow && cursor < console_p->size)
114 size = cursor;
115 else
116 size = console_p->size;
118 console_c = malloc(size + 1);
119 if (!console_c) {
120 printf("ERROR: Not enough memory for console (size = %u)\n",
121 size);
122 return NULL;
125 newc = 0;
126 if (overflow) {
127 if (cursor >= size) {
128 printf("ERROR: CBMEM console struct is corrupted\n");
129 return NULL;
131 for (oldc = cursor; oldc < size; oldc++)
132 snapshot_putc(console_c, &newc, console_p->body[oldc]);
134 for (oldc = 0; oldc < size && oldc < cursor; oldc++)
135 snapshot_putc(console_c, &newc, console_p->body[oldc]);
136 console_c[newc] = '\0';
138 return console_c;