2 * memconsole-x86-legacy.c
4 * EBDA specific parts of the memory based BIOS console.
6 * Copyright 2017 Google Inc.
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.
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.
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/dmi.h>
22 #include <asm/bios_ebda.h>
23 #include <linux/acpi.h>
25 #include "memconsole.h"
27 #define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE
28 #define BIOS_MEMCONSOLE_V2_MAGIC (('M')|('C'<<8)|('O'<<16)|('N'<<24))
30 struct biosmemcon_ebda
{
43 /* Misdocumented as number of pages! */
51 static char *memconsole_baseaddr
;
52 static size_t memconsole_length
;
54 static ssize_t
memconsole_read(char *buf
, loff_t pos
, size_t count
)
56 return memory_read_from_buffer(buf
, count
, &pos
, memconsole_baseaddr
,
60 static void found_v1_header(struct biosmemcon_ebda
*hdr
)
62 pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n",
64 pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = %d, num = %d\n",
65 hdr
->v1
.buffer_addr
, hdr
->v1
.start
,
66 hdr
->v1
.end
, hdr
->v1
.num_chars
);
68 memconsole_baseaddr
= phys_to_virt(hdr
->v1
.buffer_addr
);
69 memconsole_length
= hdr
->v1
.num_chars
;
70 memconsole_setup(memconsole_read
);
73 static void found_v2_header(struct biosmemcon_ebda
*hdr
)
75 pr_info("memconsole: BIOS console v2 EBDA structure found at %p\n",
77 pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = %d, num_bytes = %d\n",
78 hdr
->v2
.buffer_addr
, hdr
->v2
.start
,
79 hdr
->v2
.end
, hdr
->v2
.num_bytes
);
81 memconsole_baseaddr
= phys_to_virt(hdr
->v2
.buffer_addr
+ hdr
->v2
.start
);
82 memconsole_length
= hdr
->v2
.end
- hdr
->v2
.start
;
83 memconsole_setup(memconsole_read
);
87 * Search through the EBDA for the BIOS Memory Console, and
88 * set the global variables to point to it. Return true if found.
90 static bool memconsole_ebda_init(void)
95 address
= get_bios_ebda();
97 pr_info("memconsole: BIOS EBDA non-existent.\n");
101 /* EBDA length is byte 0 of EBDA (in KB) */
102 length
= *(u8
*)phys_to_virt(address
);
103 length
<<= 10; /* convert to bytes */
106 * Search through EBDA for BIOS memory console structure
107 * note: signature is not necessarily dword-aligned
109 for (cur
= 0; cur
< length
; cur
++) {
110 struct biosmemcon_ebda
*hdr
= phys_to_virt(address
+ cur
);
113 if (hdr
->signature
== BIOS_MEMCONSOLE_V1_MAGIC
) {
114 found_v1_header(hdr
);
119 if (hdr
->signature
== BIOS_MEMCONSOLE_V2_MAGIC
) {
120 found_v2_header(hdr
);
125 pr_info("memconsole: BIOS console EBDA structure not found!\n");
129 static const struct dmi_system_id memconsole_dmi_table
[] __initconst
= {
131 .ident
= "Google Board",
133 DMI_MATCH(DMI_BOARD_VENDOR
, "Google, Inc."),
138 MODULE_DEVICE_TABLE(dmi
, memconsole_dmi_table
);
140 static bool __init
memconsole_find(void)
142 if (!dmi_check_system(memconsole_dmi_table
))
145 return memconsole_ebda_init();
148 static int __init
memconsole_x86_init(void)
150 if (!memconsole_find())
153 return memconsole_sysfs_init();
156 static void __exit
memconsole_x86_exit(void)
161 module_init(memconsole_x86_init
);
162 module_exit(memconsole_x86_exit
);
164 MODULE_AUTHOR("Google, Inc.");
165 MODULE_LICENSE("GPL");