brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · a0974c3 Raw
159 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * memconsole-x86-legacy.c4 *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	0xDEADBABE20#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, and80 * 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 structure99	 * note: signature is not necessarily dword-aligned100	 */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_DESCRIPTION("EBDA specific parts of the memory based BIOS console.");158MODULE_LICENSE("GPL");159