root/drivers/firmware/google/memconsole-x86-legacy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. memconsole_read
  2. found_v1_header
  3. found_v2_header
  4. memconsole_ebda_init
  5. memconsole_find
  6. memconsole_x86_init
  7. memconsole_x86_exit

   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 
  22 struct 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 
  43 static char *memconsole_baseaddr;
  44 static size_t memconsole_length;
  45 
  46 static 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 
  52 static 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 
  65 static 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  */
  82 static 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 
 121 static 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 };
 130 MODULE_DEVICE_TABLE(dmi, memconsole_dmi_table);
 131 
 132 static 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 
 140 static int __init memconsole_x86_init(void)
 141 {
 142         if (!memconsole_find())
 143                 return -ENODEV;
 144 
 145         return memconsole_sysfs_init();
 146 }
 147 
 148 static void __exit memconsole_x86_exit(void)
 149 {
 150         memconsole_exit();
 151 }
 152 
 153 module_init(memconsole_x86_init);
 154 module_exit(memconsole_x86_exit);
 155 
 156 MODULE_AUTHOR("Google, Inc.");
 157 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */