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
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
29 #include <libpayload.h>
32 struct cbmem_console
{
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
>=
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
;
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)
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
] = '?';
100 char *cbmem_console_snapshot(void)
102 const struct cbmem_console
*const console_p
= phys_to_virt(cbmem_console_p
);
104 uint32_t size
, cursor
, overflow
, newc
, oldc
;
107 printf("ERROR: No cbmem console found in coreboot table\n");
111 cursor
= console_p
->cursor
& CURSOR_MASK
;
112 overflow
= console_p
->cursor
& OVERFLOW
;
113 if (!overflow
&& cursor
< console_p
->size
)
116 size
= console_p
->size
;
118 console_c
= malloc(size
+ 1);
120 printf("ERROR: Not enough memory for console (size = %u)\n",
127 if (cursor
>= size
) {
128 printf("ERROR: CBMEM console struct is corrupted\n");
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';