Files
linux-stable-mirror/drivers/firmware/pcdp.c
T
Arnd Bergmann 555624c0d1 vgacon: clean up global screen_info instances
To prepare for completely separating the VGA console screen_info from
the one used in EFI/sysfb, rename the vgacon instances and make them
local as much as possible.

ia64 and arm both have confurations with vgacon and efi, but the contents
never overlaps because ia64 has no EFI framebuffer, and arm only has
vga console on legacy platforms without EFI. Renaming these is required
before the EFI screen_info can be moved into drivers/firmware.

The ia64 vga console is actually registered in two places from
setup_arch(), but one of them is wrong, so drop the one in pcdp.c and
fix the one in setup.c to use the correct conditional.

x86 has to keep them together, as the boot protocol is used to switch
between VGA text console and framebuffer through the screen_info data.

Acked-by: Javier Martinez Canillas <javierm@redhat.com>
Acked-by: Khalid Aziz <khalid@gonehiking.org>
Acked-by: Helge Deller <deller@gmx.de>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20231009211845.3136536-7-arnd@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2023-10-17 10:17:02 +02:00

135 lines
3.2 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* Parse the EFI PCDP table to locate the console device.
*
* (c) Copyright 2002, 2003, 2004 Hewlett-Packard Development Company, L.P.
* Khalid Aziz <khalid.aziz@hp.com>
* Alex Williamson <alex.williamson@hp.com>
* Bjorn Helgaas <bjorn.helgaas@hp.com>
*/
#include <linux/acpi.h>
#include <linux/console.h>
#include <linux/efi.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <asm/vga.h>
#include "pcdp.h"
static int __init
setup_serial_console(struct pcdp_uart *uart)
{
#ifdef CONFIG_SERIAL_8250_CONSOLE
int mmio;
static char options[64], *p = options;
char parity;
mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
p += sprintf(p, "uart8250,%s,0x%llx",
mmio ? "mmio" : "io", uart->addr.address);
if (uart->baud) {
p += sprintf(p, ",%llu", uart->baud);
if (uart->bits) {
switch (uart->parity) {
case 0x2: parity = 'e'; break;
case 0x3: parity = 'o'; break;
default: parity = 'n';
}
p += sprintf(p, "%c%d", parity, uart->bits);
}
}
add_preferred_console("uart", 8250, &options[9]);
return setup_earlycon(options);
#else
return -ENODEV;
#endif
}
static int __init
setup_vga_console(struct pcdp_device *dev)
{
#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
u8 *if_ptr;
if_ptr = ((u8 *)dev + sizeof(struct pcdp_device));
if (if_ptr[0] == PCDP_IF_PCI) {
struct pcdp_if_pci if_pci;
/* struct copy since ifptr might not be correctly aligned */
memcpy(&if_pci, if_ptr, sizeof(if_pci));
if (if_pci.trans & PCDP_PCI_TRANS_IOPORT)
vga_console_iobase = if_pci.ioport_tra;
if (if_pci.trans & PCDP_PCI_TRANS_MMIO)
vga_console_membase = if_pci.mmio_tra;
}
if (efi_mem_type(vga_console_membase + 0xA0000) == EFI_CONVENTIONAL_MEMORY) {
printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n");
return -ENODEV;
}
printk(KERN_INFO "PCDP: VGA console\n");
return 0;
#else
return -ENODEV;
#endif
}
extern unsigned long hcdp_phys;
int __init
efi_setup_pcdp_console(char *cmdline)
{
struct pcdp *pcdp;
struct pcdp_uart *uart;
struct pcdp_device *dev, *end;
int i, serial = 0;
int rc = -ENODEV;
if (hcdp_phys == EFI_INVALID_TABLE_ADDR)
return -ENODEV;
pcdp = early_memremap(hcdp_phys, 4096);
printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, hcdp_phys);
if (strstr(cmdline, "console=hcdp")) {
if (pcdp->rev < 3)
serial = 1;
} else if (strstr(cmdline, "console=")) {
printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n");
goto out;
}
if (pcdp->rev < 3 && efi_uart_console_only())
serial = 1;
for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
if (uart->type == PCDP_CONSOLE_UART) {
rc = setup_serial_console(uart);
goto out;
}
}
}
end = (struct pcdp_device *) ((u8 *) pcdp + pcdp->length);
for (dev = (struct pcdp_device *) (pcdp->uart + pcdp->num_uarts);
dev < end;
dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
if (dev->flags & PCDP_PRIMARY_CONSOLE) {
if (dev->type == PCDP_CONSOLE_VGA) {
rc = setup_vga_console(dev);
goto out;
}
}
}
out:
early_memunmap(pcdp, 4096);
return rc;
}