Linux Audio

Check our new training course

Loading...
v5.9
 1// SPDX-License-Identifier: GPL-2.0-only
 2/*
 3 * memconsole.c
 4 *
 5 * Architecture-independent parts of the memory based BIOS console.
 
 6 *
 7 * Copyright 2017 Google Inc.
 8 */
 9
 
 
 
 
10#include <linux/sysfs.h>
11#include <linux/kobject.h>
12#include <linux/module.h>
 
 
13
14#include "memconsole.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
16static ssize_t memconsole_read(struct file *filp, struct kobject *kobp,
17			       struct bin_attribute *bin_attr, char *buf,
18			       loff_t pos, size_t count)
19{
20	ssize_t (*memconsole_read_func)(char *, loff_t, size_t);
21
22	memconsole_read_func = bin_attr->private;
23	if (WARN_ON_ONCE(!memconsole_read_func))
24		return -EIO;
25
26	return memconsole_read_func(buf, pos, count);
27}
28
29static struct bin_attribute memconsole_bin_attr = {
30	.attr = {.name = "log", .mode = 0444},
31	.read = memconsole_read,
32};
33
34void memconsole_setup(ssize_t (*read_func)(char *, loff_t, size_t))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35{
36	memconsole_bin_attr.private = read_func;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37}
38EXPORT_SYMBOL(memconsole_setup);
39
40int memconsole_sysfs_init(void)
 
 
 
 
 
 
 
 
 
 
 
41{
42	return sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
 
 
 
 
 
 
 
 
 
 
 
 
43}
44EXPORT_SYMBOL(memconsole_sysfs_init);
45
46void memconsole_exit(void)
47{
48	sysfs_remove_bin_file(firmware_kobj, &memconsole_bin_attr);
49}
50EXPORT_SYMBOL(memconsole_exit);
 
 
51
52MODULE_AUTHOR("Google, Inc.");
53MODULE_LICENSE("GPL");
v3.1
 
  1/*
  2 * memconsole.c
  3 *
  4 * Infrastructure for importing the BIOS memory based console
  5 * into the kernel log ringbuffer.
  6 *
  7 * Copyright 2010 Google Inc. All rights reserved.
  8 */
  9
 10#include <linux/ctype.h>
 11#include <linux/init.h>
 12#include <linux/kernel.h>
 13#include <linux/string.h>
 14#include <linux/sysfs.h>
 15#include <linux/kobject.h>
 16#include <linux/module.h>
 17#include <linux/dmi.h>
 18#include <asm/bios_ebda.h>
 19
 20#define BIOS_MEMCONSOLE_V1_MAGIC	0xDEADBABE
 21#define BIOS_MEMCONSOLE_V2_MAGIC	(('M')|('C'<<8)|('O'<<16)|('N'<<24))
 22
 23struct biosmemcon_ebda {
 24	u32 signature;
 25	union {
 26		struct {
 27			u8  enabled;
 28			u32 buffer_addr;
 29			u16 start;
 30			u16 end;
 31			u16 num_chars;
 32			u8  wrapped;
 33		} __packed v1;
 34		struct {
 35			u32 buffer_addr;
 36			/* Misdocumented as number of pages! */
 37			u16 num_bytes;
 38			u16 start;
 39			u16 end;
 40		} __packed v2;
 41	};
 42} __packed;
 43
 44static char *memconsole_baseaddr;
 45static size_t memconsole_length;
 46
 47static ssize_t memconsole_read(struct file *filp, struct kobject *kobp,
 48			       struct bin_attribute *bin_attr, char *buf,
 49			       loff_t pos, size_t count)
 50{
 51	return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr,
 52				       memconsole_length);
 
 
 
 
 
 53}
 54
 55static struct bin_attribute memconsole_bin_attr = {
 56	.attr = {.name = "log", .mode = 0444},
 57	.read = memconsole_read,
 58};
 59
 60
 61static void found_v1_header(struct biosmemcon_ebda *hdr)
 62{
 63	printk(KERN_INFO "BIOS console v1 EBDA structure found at %p\n", hdr);
 64	printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
 65	       "start = %d, end = %d, num = %d\n",
 66	       hdr->v1.buffer_addr, hdr->v1.start,
 67	       hdr->v1.end, hdr->v1.num_chars);
 68
 69	memconsole_length = hdr->v1.num_chars;
 70	memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr);
 71}
 72
 73static void found_v2_header(struct biosmemcon_ebda *hdr)
 74{
 75	printk(KERN_INFO "BIOS console v2 EBDA structure found at %p\n", hdr);
 76	printk(KERN_INFO "BIOS console buffer at 0x%.8x, "
 77	       "start = %d, end = %d, num_bytes = %d\n",
 78	       hdr->v2.buffer_addr, hdr->v2.start,
 79	       hdr->v2.end, hdr->v2.num_bytes);
 80
 81	memconsole_length = hdr->v2.end - hdr->v2.start;
 82	memconsole_baseaddr = phys_to_virt(hdr->v2.buffer_addr
 83					   + hdr->v2.start);
 84}
 85
 86/*
 87 * Search through the EBDA for the BIOS Memory Console, and
 88 * set the global variables to point to it.  Return true if found.
 89 */
 90static bool found_memconsole(void)
 91{
 92	unsigned int address;
 93	size_t length, cur;
 94
 95	address = get_bios_ebda();
 96	if (!address) {
 97		printk(KERN_INFO "BIOS EBDA non-existent.\n");
 98		return false;
 99	}
100
101	/* EBDA length is byte 0 of EBDA (in KB) */
102	length = *(u8 *)phys_to_virt(address);
103	length <<= 10; /* convert to bytes */
104
105	/*
106	 * Search through EBDA for BIOS memory console structure
107	 * note: signature is not necessarily dword-aligned
108	 */
109	for (cur = 0; cur < length; cur++) {
110		struct biosmemcon_ebda *hdr = phys_to_virt(address + cur);
111
112		/* memconsole v1 */
113		if (hdr->signature == BIOS_MEMCONSOLE_V1_MAGIC) {
114			found_v1_header(hdr);
115			return true;
116		}
117
118		/* memconsole v2 */
119		if (hdr->signature == BIOS_MEMCONSOLE_V2_MAGIC) {
120			found_v2_header(hdr);
121			return true;
122		}
123	}
124
125	printk(KERN_INFO "BIOS console EBDA structure not found!\n");
126	return false;
127}
 
128
129static struct dmi_system_id memconsole_dmi_table[] __initdata = {
130	{
131		.ident = "Google Board",
132		.matches = {
133			DMI_MATCH(DMI_BOARD_VENDOR, "Google, Inc."),
134		},
135	},
136	{}
137};
138MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table);
139
140static int __init memconsole_init(void)
141{
142	int ret;
143
144	if (!dmi_check_system(memconsole_dmi_table))
145		return -ENODEV;
146
147	if (!found_memconsole())
148		return -ENODEV;
149
150	memconsole_bin_attr.size = memconsole_length;
151
152	ret = sysfs_create_bin_file(firmware_kobj, &memconsole_bin_attr);
153
154	return ret;
155}
 
156
157static void __exit memconsole_exit(void)
158{
159	sysfs_remove_bin_file(firmware_kobj, &memconsole_bin_attr);
160}
161
162module_init(memconsole_init);
163module_exit(memconsole_exit);
164
165MODULE_AUTHOR("Google, Inc.");
166MODULE_LICENSE("GPL");