Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/*
2 * memconsole-coreboot.c
3 *
4 * Memory based BIOS console accessed through coreboot table.
5 *
6 * Copyright 2017 Google Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License v2.0 as published by
10 * the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/platform_device.h>
21
22#include "memconsole.h"
23#include "coreboot_table.h"
24
25#define CB_TAG_CBMEM_CONSOLE 0x17
26
27/* CBMEM firmware console log descriptor. */
28struct cbmem_cons {
29 u32 buffer_size;
30 u32 buffer_cursor;
31 u8 buffer_body[0];
32} __packed;
33
34static struct cbmem_cons __iomem *cbmem_console;
35
36static int memconsole_coreboot_init(phys_addr_t physaddr)
37{
38 struct cbmem_cons __iomem *tmp_cbmc;
39
40 tmp_cbmc = memremap(physaddr, sizeof(*tmp_cbmc), MEMREMAP_WB);
41
42 if (!tmp_cbmc)
43 return -ENOMEM;
44
45 cbmem_console = memremap(physaddr,
46 tmp_cbmc->buffer_size + sizeof(*cbmem_console),
47 MEMREMAP_WB);
48 memunmap(tmp_cbmc);
49
50 if (!cbmem_console)
51 return -ENOMEM;
52
53 memconsole_setup(cbmem_console->buffer_body,
54 min(cbmem_console->buffer_cursor, cbmem_console->buffer_size));
55
56 return 0;
57}
58
59static int memconsole_probe(struct platform_device *pdev)
60{
61 int ret;
62 struct lb_cbmem_ref entry;
63
64 ret = coreboot_table_find(CB_TAG_CBMEM_CONSOLE, &entry, sizeof(entry));
65 if (ret)
66 return ret;
67
68 ret = memconsole_coreboot_init(entry.cbmem_addr);
69 if (ret)
70 return ret;
71
72 return memconsole_sysfs_init();
73}
74
75static int memconsole_remove(struct platform_device *pdev)
76{
77 memconsole_exit();
78
79 if (cbmem_console)
80 memunmap(cbmem_console);
81
82 return 0;
83}
84
85static struct platform_driver memconsole_driver = {
86 .probe = memconsole_probe,
87 .remove = memconsole_remove,
88 .driver = {
89 .name = "memconsole",
90 },
91};
92
93static int __init platform_memconsole_init(void)
94{
95 struct platform_device *pdev;
96
97 pdev = platform_device_register_simple("memconsole", -1, NULL, 0);
98 if (IS_ERR(pdev))
99 return PTR_ERR(pdev);
100
101 platform_driver_register(&memconsole_driver);
102
103 return 0;
104}
105
106module_init(platform_memconsole_init);
107
108MODULE_AUTHOR("Google, Inc.");
109MODULE_LICENSE("GPL");