cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

memconsole-x86-legacy.c (3629B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * memconsole-x86-legacy.c
      4 *
      5 * EBDA specific parts of the memory based BIOS console.
      6 *
      7 * Copyright 2017 Google Inc.
      8 */
      9
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/dmi.h>
     13#include <linux/mm.h>
     14#include <asm/bios_ebda.h>
     15#include <linux/acpi.h>
     16
     17#include "memconsole.h"
     18
     19#define BIOS_MEMCONSOLE_V1_MAGIC	0xDEADBABE
     20#define BIOS_MEMCONSOLE_V2_MAGIC	(('M')|('C'<<8)|('O'<<16)|('N'<<24))
     21
     22struct biosmemcon_ebda {
     23	u32 signature;
     24	union {
     25		struct {
     26			u8  enabled;
     27			u32 buffer_addr;
     28			u16 start;
     29			u16 end;
     30			u16 num_chars;
     31			u8  wrapped;
     32		} __packed v1;
     33		struct {
     34			u32 buffer_addr;
     35			/* Misdocumented as number of pages! */
     36			u16 num_bytes;
     37			u16 start;
     38			u16 end;
     39		} __packed v2;
     40	};
     41} __packed;
     42
     43static char *memconsole_baseaddr;
     44static size_t memconsole_length;
     45
     46static ssize_t memconsole_read(char *buf, loff_t pos, size_t count)
     47{
     48	return memory_read_from_buffer(buf, count, &pos, memconsole_baseaddr,
     49				       memconsole_length);
     50}
     51
     52static void found_v1_header(struct biosmemcon_ebda *hdr)
     53{
     54	pr_info("memconsole: BIOS console v1 EBDA structure found at %p\n",
     55		hdr);
     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);
     59
     60	memconsole_baseaddr = phys_to_virt(hdr->v1.buffer_addr);
     61	memconsole_length = hdr->v1.num_chars;
     62	memconsole_setup(memconsole_read);
     63}
     64
     65static void found_v2_header(struct biosmemcon_ebda *hdr)
     66{
     67	pr_info("memconsole: BIOS console v2 EBDA structure found at %p\n",
     68		hdr);
     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);
     72
     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);
     76}
     77
     78/*
     79 * Search through the EBDA for the BIOS Memory Console, and
     80 * set the global variables to point to it.  Return true if found.
     81 */
     82static bool memconsole_ebda_init(void)
     83{
     84	unsigned int address;
     85	size_t length, cur;
     86
     87	address = get_bios_ebda();
     88	if (!address) {
     89		pr_info("memconsole: BIOS EBDA non-existent.\n");
     90		return false;
     91	}
     92
     93	/* EBDA length is byte 0 of EBDA (in KB) */
     94	length = *(u8 *)phys_to_virt(address);
     95	length <<= 10; /* convert to bytes */
     96
     97	/*
     98	 * Search through EBDA for BIOS memory console structure
     99	 * note: signature is not necessarily dword-aligned
    100	 */
    101	for (cur = 0; cur < length; cur++) {
    102		struct biosmemcon_ebda *hdr = phys_to_virt(address + cur);
    103
    104		/* memconsole v1 */
    105		if (hdr->signature == BIOS_MEMCONSOLE_V1_MAGIC) {
    106			found_v1_header(hdr);
    107			return true;
    108		}
    109
    110		/* memconsole v2 */
    111		if (hdr->signature == BIOS_MEMCONSOLE_V2_MAGIC) {
    112			found_v2_header(hdr);
    113			return true;
    114		}
    115	}
    116
    117	pr_info("memconsole: BIOS console EBDA structure not found!\n");
    118	return false;
    119}
    120
    121static const struct dmi_system_id memconsole_dmi_table[] __initconst = {
    122	{
    123		.ident = "Google Board",
    124		.matches = {
    125			DMI_MATCH(DMI_BOARD_VENDOR, "Google, Inc."),
    126		},
    127	},
    128	{}
    129};
    130MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table);
    131
    132static bool __init memconsole_find(void)
    133{
    134	if (!dmi_check_system(memconsole_dmi_table))
    135		return false;
    136
    137	return memconsole_ebda_init();
    138}
    139
    140static int __init memconsole_x86_init(void)
    141{
    142	if (!memconsole_find())
    143		return -ENODEV;
    144
    145	return memconsole_sysfs_init();
    146}
    147
    148static void __exit memconsole_x86_exit(void)
    149{
    150	memconsole_exit();
    151}
    152
    153module_init(memconsole_x86_init);
    154module_exit(memconsole_x86_exit);
    155
    156MODULE_AUTHOR("Google, Inc.");
    157MODULE_LICENSE("GPL");