1 // SPDX-License-Identifier: GPL-2.0-only
3 * memconsole-x86-legacy.c
5 * EBDA specific parts of the memory based BIOS console.
7 * Copyright 2017 Google Inc.
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/dmi.h>
14 #include <asm/bios_ebda.h>
15 #include <linux/acpi.h>
17 #include "memconsole.h"
19 #define BIOS_MEMCONSOLE_V1_MAGIC 0xDEADBABE
20 #define BIOS_MEMCONSOLE_V2_MAGIC (('M')|('C'<<8)|('O'<<16)|('N'<<24))
22 struct biosmemcon_ebda
{
35 /* Misdocumented as number of pages! */
43 static char *memconsole_baseaddr
;
44 static size_t memconsole_length
;
46 static ssize_t
memconsole_read(char *buf
, loff_t pos
, size_t count
)
48 return memory_read_from_buffer(buf
, count
, &pos
, memconsole_baseaddr
,
52 static void found_v1_header(struct biosmemcon_ebda
*hdr
)
54 pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n",
56 pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = %d, num = %d\n",
57 hdr
->v1
.buffer_addr
, hdr
->v1
.start
,
58 hdr
->v1
.end
, hdr
->v1
.num_chars
);
60 memconsole_baseaddr
= phys_to_virt(hdr
->v1
.buffer_addr
);
61 memconsole_length
= hdr
->v1
.num_chars
;
62 memconsole_setup(memconsole_read
);
65 static void found_v2_header(struct biosmemcon_ebda
*hdr
)
67 pr_info("memconsole: BIOS console v2 EBDA structure found at %p\n",
69 pr_info("memconsole: BIOS console buffer at 0x%.8x, start = %d, end = %d, num_bytes = %d\n",
70 hdr
->v2
.buffer_addr
, hdr
->v2
.start
,
71 hdr
->v2
.end
, hdr
->v2
.num_bytes
);
73 memconsole_baseaddr
= phys_to_virt(hdr
->v2
.buffer_addr
+ hdr
->v2
.start
);
74 memconsole_length
= hdr
->v2
.end
- hdr
->v2
.start
;
75 memconsole_setup(memconsole_read
);
79 * Search through the EBDA for the BIOS Memory Console, and
80 * set the global variables to point to it. Return true if found.
82 static bool memconsole_ebda_init(void)
87 address
= get_bios_ebda();
89 pr_info("memconsole: BIOS EBDA non-existent.\n");
93 /* EBDA length is byte 0 of EBDA (in KB) */
94 length
= *(u8
*)phys_to_virt(address
);
95 length
<<= 10; /* convert to bytes */
98 * Search through EBDA for BIOS memory console structure
99 * note: signature is not necessarily dword-aligned
101 for (cur
= 0; cur
< length
; cur
++) {
102 struct biosmemcon_ebda
*hdr
= phys_to_virt(address
+ cur
);
105 if (hdr
->signature
== BIOS_MEMCONSOLE_V1_MAGIC
) {
106 found_v1_header(hdr
);
111 if (hdr
->signature
== BIOS_MEMCONSOLE_V2_MAGIC
) {
112 found_v2_header(hdr
);
117 pr_info("memconsole: BIOS console EBDA structure not found!\n");
121 static const struct dmi_system_id memconsole_dmi_table
[] __initconst
= {
123 .ident
= "Google Board",
125 DMI_MATCH(DMI_BOARD_VENDOR
, "Google, Inc."),
130 MODULE_DEVICE_TABLE(dmi
, memconsole_dmi_table
);
132 static bool __init
memconsole_find(void)
134 if (!dmi_check_system(memconsole_dmi_table
))
137 return memconsole_ebda_init();
140 static int __init
memconsole_x86_init(void)
142 if (!memconsole_find())
145 return memconsole_sysfs_init();
148 static void __exit
memconsole_x86_exit(void)
153 module_init(memconsole_x86_init
);
154 module_exit(memconsole_x86_exit
);
156 MODULE_AUTHOR("Google, Inc.");
157 MODULE_LICENSE("GPL");