1*44e33a5aSSean Rhodes // SPDX-License-Identifier: GPL-2.0-only
2*44e33a5aSSean Rhodes /*
3*44e33a5aSSean Rhodes * memconsole-coreboot.c
4*44e33a5aSSean Rhodes *
5*44e33a5aSSean Rhodes * Memory based BIOS console accessed through coreboot table.
6*44e33a5aSSean Rhodes *
7*44e33a5aSSean Rhodes * Copyright 2017 Google Inc.
8*44e33a5aSSean Rhodes */
9*44e33a5aSSean Rhodes
10*44e33a5aSSean Rhodes #include <linux/device.h>
11*44e33a5aSSean Rhodes #include <linux/io.h>
12*44e33a5aSSean Rhodes #include <linux/kernel.h>
13*44e33a5aSSean Rhodes #include <linux/device-id/coreboot.h>
14*44e33a5aSSean Rhodes #include <linux/module.h>
15*44e33a5aSSean Rhodes
16*44e33a5aSSean Rhodes #include "memconsole.h"
17*44e33a5aSSean Rhodes #include "coreboot_table.h"
18*44e33a5aSSean Rhodes
19*44e33a5aSSean Rhodes #define CB_TAG_CBMEM_CONSOLE 0x17
20*44e33a5aSSean Rhodes
21*44e33a5aSSean Rhodes /* CBMEM firmware console log descriptor. */
22*44e33a5aSSean Rhodes struct cbmem_cons {
23*44e33a5aSSean Rhodes u32 size_dont_access_after_boot;
24*44e33a5aSSean Rhodes u32 cursor;
25*44e33a5aSSean Rhodes u8 body[];
26*44e33a5aSSean Rhodes } __packed;
27*44e33a5aSSean Rhodes
28*44e33a5aSSean Rhodes #define CURSOR_MASK ((1 << 28) - 1)
29*44e33a5aSSean Rhodes #define OVERFLOW (1 << 31)
30*44e33a5aSSean Rhodes
31*44e33a5aSSean Rhodes static struct cbmem_cons *cbmem_console;
32*44e33a5aSSean Rhodes static u32 cbmem_console_size;
33*44e33a5aSSean Rhodes
34*44e33a5aSSean Rhodes /*
35*44e33a5aSSean Rhodes * The cbmem_console structure is read again on every access because it may
36*44e33a5aSSean Rhodes * change at any time if runtime firmware logs new messages. This may rarely
37*44e33a5aSSean Rhodes * lead to race conditions where the firmware overwrites the beginning of the
38*44e33a5aSSean Rhodes * ring buffer with more lines after we have already read |cursor|. It should be
39*44e33a5aSSean Rhodes * rare and harmless enough that we don't spend extra effort working around it.
40*44e33a5aSSean Rhodes */
memconsole_coreboot_read(char * buf,loff_t pos,size_t count)41*44e33a5aSSean Rhodes static ssize_t memconsole_coreboot_read(char *buf, loff_t pos, size_t count)
42*44e33a5aSSean Rhodes {
43*44e33a5aSSean Rhodes u32 cursor = cbmem_console->cursor & CURSOR_MASK;
44*44e33a5aSSean Rhodes u32 flags = cbmem_console->cursor & ~CURSOR_MASK;
45*44e33a5aSSean Rhodes u32 size = cbmem_console_size;
46*44e33a5aSSean Rhodes struct seg { /* describes ring buffer segments in logical order */
47*44e33a5aSSean Rhodes u32 phys; /* physical offset from start of mem buffer */
48*44e33a5aSSean Rhodes u32 len; /* length of segment */
49*44e33a5aSSean Rhodes } seg[2] = { {0}, {0} };
50*44e33a5aSSean Rhodes size_t done = 0;
51*44e33a5aSSean Rhodes int i;
52*44e33a5aSSean Rhodes
53*44e33a5aSSean Rhodes if (flags & OVERFLOW) {
54*44e33a5aSSean Rhodes if (cursor > size) /* Shouldn't really happen, but... */
55*44e33a5aSSean Rhodes cursor = 0;
56*44e33a5aSSean Rhodes seg[0] = (struct seg){.phys = cursor, .len = size - cursor};
57*44e33a5aSSean Rhodes seg[1] = (struct seg){.phys = 0, .len = cursor};
58*44e33a5aSSean Rhodes } else {
59*44e33a5aSSean Rhodes seg[0] = (struct seg){.phys = 0, .len = min(cursor, size)};
60*44e33a5aSSean Rhodes }
61*44e33a5aSSean Rhodes
62*44e33a5aSSean Rhodes for (i = 0; i < ARRAY_SIZE(seg) && count > done; i++) {
63*44e33a5aSSean Rhodes done += memory_read_from_buffer(buf + done, count - done, &pos,
64*44e33a5aSSean Rhodes cbmem_console->body + seg[i].phys, seg[i].len);
65*44e33a5aSSean Rhodes pos -= seg[i].len;
66*44e33a5aSSean Rhodes }
67*44e33a5aSSean Rhodes return done;
68*44e33a5aSSean Rhodes }
69*44e33a5aSSean Rhodes
memconsole_probe(struct coreboot_device * dev)70*44e33a5aSSean Rhodes static int memconsole_probe(struct coreboot_device *dev)
71*44e33a5aSSean Rhodes {
72*44e33a5aSSean Rhodes struct cbmem_cons *tmp_cbmc;
73*44e33a5aSSean Rhodes
74*44e33a5aSSean Rhodes tmp_cbmc = memremap(dev->cbmem_ref.cbmem_addr,
75*44e33a5aSSean Rhodes sizeof(*tmp_cbmc), MEMREMAP_WB);
76*44e33a5aSSean Rhodes
77*44e33a5aSSean Rhodes if (!tmp_cbmc)
78*44e33a5aSSean Rhodes return -ENOMEM;
79*44e33a5aSSean Rhodes
80*44e33a5aSSean Rhodes /* Read size only once to prevent overrun attack through /dev/mem. */
81*44e33a5aSSean Rhodes cbmem_console_size = tmp_cbmc->size_dont_access_after_boot;
82*44e33a5aSSean Rhodes cbmem_console = devm_memremap(&dev->dev, dev->cbmem_ref.cbmem_addr,
83*44e33a5aSSean Rhodes cbmem_console_size + sizeof(*cbmem_console),
84*44e33a5aSSean Rhodes MEMREMAP_WB);
85*44e33a5aSSean Rhodes memunmap(tmp_cbmc);
86*44e33a5aSSean Rhodes
87*44e33a5aSSean Rhodes if (IS_ERR(cbmem_console))
88*44e33a5aSSean Rhodes return PTR_ERR(cbmem_console);
89*44e33a5aSSean Rhodes
90*44e33a5aSSean Rhodes memconsole_setup(memconsole_coreboot_read);
91*44e33a5aSSean Rhodes
92*44e33a5aSSean Rhodes return memconsole_sysfs_init();
93*44e33a5aSSean Rhodes }
94*44e33a5aSSean Rhodes
memconsole_remove(struct coreboot_device * dev)95*44e33a5aSSean Rhodes static void memconsole_remove(struct coreboot_device *dev)
96*44e33a5aSSean Rhodes {
97*44e33a5aSSean Rhodes memconsole_exit();
98*44e33a5aSSean Rhodes }
99*44e33a5aSSean Rhodes
100*44e33a5aSSean Rhodes static const struct coreboot_device_id memconsole_ids[] = {
101*44e33a5aSSean Rhodes { .tag = CB_TAG_CBMEM_CONSOLE },
102*44e33a5aSSean Rhodes { /* sentinel */ }
103*44e33a5aSSean Rhodes };
104*44e33a5aSSean Rhodes MODULE_DEVICE_TABLE(coreboot, memconsole_ids);
105*44e33a5aSSean Rhodes
106*44e33a5aSSean Rhodes static struct coreboot_driver memconsole_driver = {
107*44e33a5aSSean Rhodes .probe = memconsole_probe,
108*44e33a5aSSean Rhodes .remove = memconsole_remove,
109*44e33a5aSSean Rhodes .drv = {
110*44e33a5aSSean Rhodes .name = "memconsole",
111*44e33a5aSSean Rhodes },
112*44e33a5aSSean Rhodes .id_table = memconsole_ids,
113*44e33a5aSSean Rhodes };
114*44e33a5aSSean Rhodes module_coreboot_driver(memconsole_driver);
115*44e33a5aSSean Rhodes
116*44e33a5aSSean Rhodes MODULE_AUTHOR("Google, Inc.");
117*44e33a5aSSean Rhodes MODULE_DESCRIPTION("Memory based BIOS console accessed through coreboot table");
118*44e33a5aSSean Rhodes MODULE_LICENSE("GPL");
119