From 4de979f6646d05d13572ecd2b652f0358dfa5de6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Jul 2023 09:04:32 -0600 Subject: bootstd: Use bootdev instead of bootdevice It seems better to call this a 'bootdev' since this is name used in the documentation. The older 'Bootdevice' name is no-longer used and may cause confusion with the 'bootdevice' environment variable. Update throughout to use bootdev. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/mmc/mmc_bootdev.c | 2 +- drivers/scsi/scsi_bootdev.c | 2 +- drivers/usb/host/usb_bootdev.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc_bootdev.c b/drivers/mmc/mmc_bootdev.c index b57b8a62276..55ecead2ddf 100644 --- a/drivers/mmc/mmc_bootdev.c +++ b/drivers/mmc/mmc_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for MMC + * Bootdev for MMC * * Copyright 2021 Google LLC * Written by Simon Glass diff --git a/drivers/scsi/scsi_bootdev.c b/drivers/scsi/scsi_bootdev.c index 991013fe1ef..218221fa306 100644 --- a/drivers/scsi/scsi_bootdev.c +++ b/drivers/scsi/scsi_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for USB + * Bootdev for SCSI * * Copyright 2021 Google LLC * Written by Simon Glass diff --git a/drivers/usb/host/usb_bootdev.c b/drivers/usb/host/usb_bootdev.c index 06e8f61aa1c..7fa1c601dff 100644 --- a/drivers/usb/host/usb_bootdev.c +++ b/drivers/usb/host/usb_bootdev.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Bootdevice for USB + * Bootdev for USB * * Copyright 2021 Google LLC * Written by Simon Glass -- cgit v1.3.1 From 603363927a0da1be12ff7e7b073202861c979693 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:38 -0600 Subject: bios_emulator: Add Kconfig and adjust Makefile for SPL The Kconfig for this is currently inside a particular board. Move it into the correct place and allow use in SPL, so that video can be used there if needed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- board/google/Kconfig | 7 ------- drivers/Kconfig | 2 ++ drivers/Makefile | 2 +- drivers/bios_emulator/Kconfig | 10 ++++++++++ 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 drivers/bios_emulator/Kconfig (limited to 'drivers') diff --git a/board/google/Kconfig b/board/google/Kconfig index a0f1a609764..e4f9b5b68aa 100644 --- a/board/google/Kconfig +++ b/board/google/Kconfig @@ -4,13 +4,6 @@ if VENDOR_GOOGLE -config BIOSEMU - bool - select X86EMU_RAW_IO - -config X86EMU_RAW_IO - bool - choice prompt "Mainboard model" optional diff --git a/drivers/Kconfig b/drivers/Kconfig index 75937fbb6d9..a25f6ae02fd 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -10,6 +10,8 @@ source "drivers/ata/Kconfig" source "drivers/axi/Kconfig" +source "drivers/bios_emulator/Kconfig" + source "drivers/bus/Kconfig" source "drivers/block/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 78dcf62f76a..3bc6d279d7c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0+ +obj-$(CONFIG_$(SPL_TPL_)BIOSEMU) += bios_emulator/ obj-$(CONFIG_$(SPL_TPL_)BLK) += block/ obj-$(CONFIG_$(SPL_TPL_)BOOTCOUNT_LIMIT) += bootcount/ obj-$(CONFIG_$(SPL_TPL_)BUTTON) += button/ @@ -80,7 +81,6 @@ ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) obj-y += adc/ obj-y += ata/ obj-$(CONFIG_DM_DEMO) += demo/ -obj-$(CONFIG_BIOSEMU) += bios_emulator/ obj-y += block/ obj-y += cache/ obj-$(CONFIG_CPU) += cpu/ diff --git a/drivers/bios_emulator/Kconfig b/drivers/bios_emulator/Kconfig new file mode 100644 index 00000000000..3660576772d --- /dev/null +++ b/drivers/bios_emulator/Kconfig @@ -0,0 +1,10 @@ +config BIOSEMU + bool + select X86EMU_RAW_IO + +config SPL_BIOSEMU + bool + select X86EMU_RAW_IO + +config X86EMU_RAW_IO + bool -- cgit v1.3.1 From 70f2030f02696ee1820d8df690e878de078b01b3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:39 -0600 Subject: bios_emulator: Drop VIDEO_IO_OFFSET This is always zero in the source tree, so drop it. While we are here, add a comment to _X86EMU_env since the symbol is actually defined twice, which can cause confusion when building. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/bios_emulator/biosemui.h | 18 +++++++++--------- drivers/bios_emulator/x86emu/sys.c | 1 + include/configs/conga-qeval20-qa3-e3845.h | 2 -- include/configs/dfi-bt700.h | 2 -- include/configs/minnowmax.h | 2 -- include/configs/som-db5800-som-6867.h | 2 -- include/configs/theadorable-x86-common.h | 2 -- include/configs/x86-chromebook.h | 2 -- 8 files changed, 10 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/bios_emulator/biosemui.h b/drivers/bios_emulator/biosemui.h index 7853015c1e2..954cd883158 100644 --- a/drivers/bios_emulator/biosemui.h +++ b/drivers/bios_emulator/biosemui.h @@ -128,19 +128,19 @@ typedef struct { u32 finalVal; } BE_portInfo; -#define PM_inpb(port) inb(port+VIDEO_IO_OFFSET) -#define PM_inpw(port) inw(port+VIDEO_IO_OFFSET) -#define PM_inpd(port) inl(port+VIDEO_IO_OFFSET) -#define PM_outpb(port,val) outb(val,port+VIDEO_IO_OFFSET) -#define PM_outpw(port,val) outw(val,port+VIDEO_IO_OFFSET) -#define PM_outpd(port,val) outl(val,port+VIDEO_IO_OFFSET) +#define PM_inpb(port) inb(port) +#define PM_inpw(port) inw(port) +#define PM_inpd(port) inl(port) +#define PM_outpb(port, val) outb(val, port) +#define PM_outpw(port, val) outw(val, port) +#define PM_outpd(port, val) outl(val, port) #define LOG_inpb(port) PM_inpb(port) #define LOG_inpw(port) PM_inpw(port) #define LOG_inpd(port) PM_inpd(port) -#define LOG_outpb(port,val) PM_outpb(port,val) -#define LOG_outpw(port,val) PM_outpw(port,val) -#define LOG_outpd(port,val) PM_outpd(port,val) +#define LOG_outpb(port, val) PM_outpb(port, val) +#define LOG_outpw(port, val) PM_outpw(port, val) +#define LOG_outpd(port, val) PM_outpd(port, val) /*-------------------------- Function Prototypes --------------------------*/ diff --git a/drivers/bios_emulator/x86emu/sys.c b/drivers/bios_emulator/x86emu/sys.c index c2db1213fe6..882a8a34cc3 100644 --- a/drivers/bios_emulator/x86emu/sys.c +++ b/drivers/bios_emulator/x86emu/sys.c @@ -44,6 +44,7 @@ /*------------------------- Global Variables ------------------------------*/ +/* Note: bios.c defines this if the emulator is not enabled */ X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */ X86EMU_intrFuncs _X86EMU_intrTab[256]; diff --git a/include/configs/conga-qeval20-qa3-e3845.h b/include/configs/conga-qeval20-qa3-e3845.h index 60617e6fec2..03c364f29fb 100644 --- a/include/configs/conga-qeval20-qa3-e3845.h +++ b/include/configs/conga-qeval20-qa3-e3845.h @@ -16,8 +16,6 @@ "stdout=serial\0" \ "stderr=serial\0" -#define VIDEO_IO_OFFSET 0 - #undef CFG_EXTRA_ENV_SETTINGS #define CFG_EXTRA_ENV_SETTINGS \ "kernel-ver=4.4.0-22\0" \ diff --git a/include/configs/dfi-bt700.h b/include/configs/dfi-bt700.h index 05389a435be..be095e28a1b 100644 --- a/include/configs/dfi-bt700.h +++ b/include/configs/dfi-bt700.h @@ -20,8 +20,6 @@ "stdout=serial\0" \ "stderr=serial\0" -#define VIDEO_IO_OFFSET 0 - #undef CFG_EXTRA_ENV_SETTINGS #define CFG_EXTRA_ENV_SETTINGS \ "kernel-ver=4.4.0-24\0" \ diff --git a/include/configs/minnowmax.h b/include/configs/minnowmax.h index 4a12c2f72c6..842672d5575 100644 --- a/include/configs/minnowmax.h +++ b/include/configs/minnowmax.h @@ -17,6 +17,4 @@ "stderr=vidconsole,serial\0" \ "usb_pgood_delay=40\0" -#define VIDEO_IO_OFFSET 0 - #endif /* __CONFIG_H */ diff --git a/include/configs/som-db5800-som-6867.h b/include/configs/som-db5800-som-6867.h index b2e7aa1514c..5f7eabd3fc6 100644 --- a/include/configs/som-db5800-som-6867.h +++ b/include/configs/som-db5800-som-6867.h @@ -16,6 +16,4 @@ "stdout=serial,vidconsole\0" \ "stderr=serial,vidconsole\0" -#define VIDEO_IO_OFFSET 0 - #endif /* __CONFIG_H */ diff --git a/include/configs/theadorable-x86-common.h b/include/configs/theadorable-x86-common.h index b23b8783076..46aef238213 100644 --- a/include/configs/theadorable-x86-common.h +++ b/include/configs/theadorable-x86-common.h @@ -15,8 +15,6 @@ "stdout=serial\0" \ "stderr=serial\0" -#define VIDEO_IO_OFFSET 0 - /* Environment settings */ #undef CFG_EXTRA_ENV_SETTINGS diff --git a/include/configs/x86-chromebook.h b/include/configs/x86-chromebook.h index 98abb00927a..6bf90c7de43 100644 --- a/include/configs/x86-chromebook.h +++ b/include/configs/x86-chromebook.h @@ -10,8 +10,6 @@ #define CFG_X86_REFCODE_ADDR 0xffea0000 #define CFG_X86_REFCODE_RUN_ADDR 0 -#define VIDEO_IO_OFFSET 0 - #define CFG_STD_DEVICES_SETTINGS "stdin=usbkbd,i8042-kbd,serial\0" \ "stdout=vidconsole,serial\0" \ "stderr=vidconsole,serial\0" -- cgit v1.3.1 From 854624c277295fe6c2de66c08750442969b5e584 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:50 -0600 Subject: qfw: Set the address of the ACPI tables Once the ACPI tables have been set up, record their address so that it is possible to list them with 'acpi list'. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/misc/qfw.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 9ef95caa895..0a93feeb4b2 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -18,6 +18,7 @@ #include #include #include +#include #if defined(CONFIG_GENERATE_ACPI_TABLE) && !defined(CONFIG_SANDBOX) /* @@ -227,6 +228,9 @@ out: } free(table_loader); + + gd_set_acpi_start(acpi_get_rsdp_addr()); + return addr; } -- cgit v1.3.1 From 1dd00b1be82556c35a68c90b187a0f096192fd5f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:54 -0600 Subject: nvme: Provide more useful debugging messages When scanning fails it is useful to be able to decode what went wrong. Add some debugging for this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/nvme/nvme.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/nvme/nvme.c b/drivers/nvme/nvme.c index 74e7a5b0110..a7add66ab4d 100644 --- a/drivers/nvme/nvme.c +++ b/drivers/nvme/nvme.c @@ -578,17 +578,22 @@ static int nvme_set_queue_count(struct nvme_dev *dev, int count) return min(result & 0xffff, result >> 16) + 1; } -static void nvme_create_io_queues(struct nvme_dev *dev) +static int nvme_create_io_queues(struct nvme_dev *dev) { unsigned int i; + int ret; for (i = dev->queue_count; i <= dev->max_qid; i++) if (!nvme_alloc_queue(dev, i, dev->q_depth)) - break; + return log_msg_ret("all", -ENOMEM); - for (i = dev->online_queues; i <= dev->queue_count - 1; i++) - if (nvme_create_queue(dev->queues[i], i)) - break; + for (i = dev->online_queues; i <= dev->queue_count - 1; i++) { + ret = nvme_create_queue(dev->queues[i], i); + if (ret) + return log_msg_ret("cre", ret); + } + + return 0; } static int nvme_setup_io_queues(struct nvme_dev *dev) @@ -598,14 +603,18 @@ static int nvme_setup_io_queues(struct nvme_dev *dev) nr_io_queues = 1; result = nvme_set_queue_count(dev, nr_io_queues); - if (result <= 0) + if (result <= 0) { + log_debug("Cannot set queue count (err=%dE)\n", result); return result; + } dev->max_qid = nr_io_queues; /* Free previously allocated queues */ nvme_free_queues(dev, nr_io_queues + 1); - nvme_create_io_queues(dev); + result = nvme_create_io_queues(dev); + if (result) + return result; return 0; } @@ -683,8 +692,11 @@ int nvme_scan_namespace(void) uclass_foreach_dev(dev, uc) { ret = device_probe(dev); - if (ret) + if (ret) { + log_err("Failed to probe '%s': err=%dE\n", dev->name, + ret); return ret; + } } return 0; @@ -842,8 +854,10 @@ int nvme_init(struct udevice *udev) ndev->dbs = ((void __iomem *)ndev->bar) + 4096; ret = nvme_configure_admin_queue(ndev); - if (ret) + if (ret) { + log_debug("Unable to configure admin queue (err=%dE)\n", ret); goto free_queue; + } /* Allocate after the page size is known */ ndev->prp_pool = memalign(ndev->page_size, MAX_PRP_POOL); @@ -855,8 +869,10 @@ int nvme_init(struct udevice *udev) ndev->prp_entry_num = MAX_PRP_POOL >> 3; ret = nvme_setup_io_queues(ndev); - if (ret) + if (ret) { + log_debug("Unable to setup I/O queues(err=%dE)\n", ret); goto free_queue; + } nvme_get_info_from_identify(ndev); -- cgit v1.3.1 From db3820a2883ada53ca704fc393148657e44e0706 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:55 -0600 Subject: pci: Support autoconfig in SPL Allow PCI autoconfig to be handled in SPL, so that we can set it up correctly for boards which need to do this before U-Boot proper. This includes qemu-x64_64 which needs to set up the video device while in 32-bit mode. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/Kconfig | 5 +++++ drivers/pci/pci-uclass.c | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 84a2ae951f7..aca439d9213 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -44,8 +44,13 @@ config SPL_PCI_PNP bool "Enable Plug & Play support for PCI" help Enable PCI memory and I/O space resource allocation and assignment. + This is required to auto configure the enumerated devices. + This is normally not done in SPL, but can be enabled if devices must + be set up in the SPL phase. Often it is enough to manually configure + one device, so this option can be disabled. + config PCI_REGION_MULTI_ENTRY bool "Enable Multiple entries of region type MEMORY in ranges for PCI" help diff --git a/drivers/pci/pci-uclass.c b/drivers/pci/pci-uclass.c index 8d27e40338c..632c1a63cfc 100644 --- a/drivers/pci/pci-uclass.c +++ b/drivers/pci/pci-uclass.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -722,6 +723,9 @@ static bool pci_need_device_pre_reloc(struct udevice *bus, uint vendor, u32 vendev; int index; + if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(PCI_PNP)) + return true; + for (index = 0; !dev_read_u32_index(bus, "u-boot,pci-pre-reloc", index, &vendev); @@ -793,7 +797,9 @@ static int pci_find_and_bind_driver(struct udevice *parent, * space is pretty limited (ie: using Cache As RAM). */ if (!(gd->flags & GD_FLG_RELOC) && - !(drv->flags & DM_FLAG_PRE_RELOC)) + !(drv->flags & DM_FLAG_PRE_RELOC) && + (!CONFIG_IS_ENABLED(PCI_PNP) || + spl_phase() != PHASE_SPL)) return log_msg_ret("pre", -EPERM); /* @@ -918,6 +924,8 @@ int pci_bind_bus_devices(struct udevice *bus) } ret = pci_find_and_bind_driver(bus, &find_id, bdf, &dev); + } else { + debug("device: %s\n", dev->name); } if (ret == -EPERM) continue; -- cgit v1.3.1 From d424553675e93495f346ea7b24beb8c3dd750c67 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:57 -0600 Subject: pci: Tidy up logging and reporting for video BIOS When running the ROM the code is not very helpful when something goes wrong. Add a little more debugging and some logging of return values to improve this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index f0dfe631490..51dcdf9749a 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -254,14 +254,16 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), ret = pci_rom_probe(dev, &rom); if (ret) - return ret; + return log_msg_ret("pro", ret); ret = pci_rom_load(rom, &ram, &alloced); - if (ret) + if (ret) { + ret = log_msg_ret("ld", ret); goto err; + } if (!board_should_run_oprom(dev)) { - ret = -ENXIO; + ret = log_msg_ret("run", -ENXIO); goto err; } @@ -299,21 +301,25 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), #ifdef CONFIG_BIOSEMU BE_VGAInfo *info; + log_debug("Running video BIOS with emulator..."); ret = biosemu_setup(dev, &info); if (ret) goto err; biosemu_set_interrupt_handler(0x15, int15_handler); ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, true, vesa_mode, &mode_info); + log_debug("done\n"); if (ret) goto err; #endif } else { #if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL) + log_debug("Running video BIOS..."); bios_set_interrupt_handler(0x15, int15_handler); bios_run_on_x86(dev, (unsigned long)ram, vesa_mode, &mode_info); + log_debug("done\n"); #endif } debug("Final vesa mode %#x\n", mode_info.video_mode); -- cgit v1.3.1 From 5345700d2af425a8c5a36c078db5d71bf31280c7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:58 -0600 Subject: x86: Allow video-BIOS code to be built for SPL With qemu-x86_64 we need to run the video BIOS while in 32-bit mode, i.e. SPL. Add a Kconfig option for this, adjust the Makefile rules and use CONFIG_IS_ENABLED() where needed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/lib/Makefile | 7 ++++--- arch/x86/lib/bios.c | 2 +- drivers/pci/pci_rom.c | 28 ++++++++++++++-------------- 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index b0612ae6dd5..90a7618ecfd 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -4,16 +4,17 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y += bdinfo.o -ifndef CONFIG_X86_64 -ifndef CONFIG_TPL_BUILD + +ifndef CONFIG_$(SPL_TPL_)X86_64 obj-y += bios.o obj-y += bios_asm.o obj-y += bios_interrupts.o endif -endif + ifndef CONFIG_SPL_BUILD obj-$(CONFIG_X86_32BIT_INIT) += string.o endif + ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o endif diff --git a/arch/x86/lib/bios.c b/arch/x86/lib/bios.c index 8cc686fd146..e29cae78e50 100644 --- a/arch/x86/lib/bios.c +++ b/arch/x86/lib/bios.c @@ -23,7 +23,7 @@ static int (*int_handler[256])(void); /* to have a common register file for interrupt handlers */ -#ifndef CONFIG_BIOSEMU +#if !CONFIG_IS_ENABLED(BIOSEMU) X86EMU_sysEnv _X86EMU_env; #endif diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 51dcdf9749a..228ab7fca72 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -298,20 +298,20 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), } if (emulate) { -#ifdef CONFIG_BIOSEMU - BE_VGAInfo *info; - - log_debug("Running video BIOS with emulator..."); - ret = biosemu_setup(dev, &info); - if (ret) - goto err; - biosemu_set_interrupt_handler(0x15, int15_handler); - ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, - true, vesa_mode, &mode_info); - log_debug("done\n"); - if (ret) - goto err; -#endif + if (CONFIG_IS_ENABLED(BIOSEMU)) { + BE_VGAInfo *info; + + log_debug("Running video BIOS with emulator..."); + ret = biosemu_setup(dev, &info); + if (ret) + goto err; + biosemu_set_interrupt_handler(0x15, int15_handler); + ret = biosemu_run(dev, (uchar *)ram, 1 << 16, info, + true, vesa_mode, &mode_info); + log_debug("done\n"); + if (ret) + goto err; + } } else { #if defined(CONFIG_X86) && (CONFIG_IS_ENABLED(X86_32BIT_INIT) || CONFIG_TPL) log_debug("Running video BIOS..."); -- cgit v1.3.1 From 03fe79c091cee0bd591070dd24adfa8f556b50df Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:38:59 -0600 Subject: x86: Pass video settings from SPL to U-Boot proper When video is set up in SPL, U-Boot proper needs to use the correct parameters so it can write to the display. Put these in a bloblist so they are available to U-Boot proper. Signed-off-by: Simon Glass Reviewed-by: Nikhil M Jain Reviewed-by: Bin Meng --- common/bloblist.c | 1 + drivers/pci/pci_rom.c | 78 +++++++++++++++++++++++++++++++++++++-------------- include/bloblist.h | 1 + include/video.h | 24 ++++++++++++++++ 4 files changed, 83 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/common/bloblist.c b/common/bloblist.c index 0d63b6e8817..2144b10e1d0 100644 --- a/common/bloblist.c +++ b/common/bloblist.c @@ -51,6 +51,7 @@ static struct tag_name { /* BLOBLISTT_PROJECT_AREA */ { BLOBLISTT_U_BOOT_SPL_HANDOFF, "SPL hand-off" }, + { BLOBLISTT_U_BOOT_VIDEO, "SPL video handoff" }, /* BLOBLISTT_VENDOR_AREA */ }; diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 228ab7fca72..bdfd1f03e79 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -374,34 +376,68 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void)) printf("Not available (previous bootloader prevents it)\n"); return -EPERM; } - bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); - ret = dm_pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE | - PCI_ROM_ALLOW_FALLBACK); - bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); - if (ret) { - debug("failed to run video BIOS: %d\n", ret); - return ret; - } - ret = vesa_setup_video_priv(&mode_info.vesa, - mode_info.vesa.phys_base_ptr, uc_priv, - plat); - if (ret) { - if (ret == -ENFILE) { - /* - * See video-uclass.c for how to set up reserved memory - * in your video driver - */ - log_err("CONFIG_VIDEO_COPY enabled but driver '%s' set up no reserved memory\n", - dev->driver->name); + /* In U-Boot proper, collect the information added by SPL (see below) */ + if (IS_ENABLED(CONFIG_SPL_VIDEO) && spl_phase() > PHASE_SPL && + CONFIG_IS_ENABLED(BLOBLIST)) { + struct video_handoff *ho; + + ho = bloblist_find(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho)); + if (!ho) + return log_msg_ret("blf", -ENOENT); + plat->base = ho->fb; + plat->size = ho->size; + uc_priv->xsize = ho->xsize; + uc_priv->ysize = ho->ysize; + uc_priv->line_length = ho->line_length; + uc_priv->bpix = ho->bpix; + } else { + bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); + ret = dm_pci_run_vga_bios(dev, int15_handler, + PCI_ROM_USE_NATIVE | + PCI_ROM_ALLOW_FALLBACK); + bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); + if (ret) { + debug("failed to run video BIOS: %d\n", ret); + return ret; } - debug("No video mode configured\n"); - return ret; + ret = vesa_setup_video_priv(&mode_info.vesa, + mode_info.vesa.phys_base_ptr, + uc_priv, plat); + if (ret) { + if (ret == -ENFILE) { + /* + * See video-uclass.c for how to set up reserved + * memory in your video driver + */ + log_err("CONFIG_VIDEO_COPY enabled but driver '%s' set up no reserved memory\n", + dev->driver->name); + } + + debug("No video mode configured\n"); + return ret; + } } printf("Video: %dx%dx%d\n", uc_priv->xsize, uc_priv->ysize, mode_info.vesa.bits_per_pixel); + /* In SPL, store the information for use by U-Boot proper */ + if (spl_phase() == PHASE_SPL && CONFIG_IS_ENABLED(BLOBLIST)) { + struct video_handoff *ho; + + ho = bloblist_add(BLOBLISTT_U_BOOT_VIDEO, sizeof(*ho), 0); + if (!ho) + return log_msg_ret("blc", -ENOMEM); + + ho->fb = plat->base; + ho->size = plat->size; + ho->xsize = uc_priv->xsize; + ho->ysize = uc_priv->ysize; + ho->line_length = uc_priv->line_length; + ho->bpix = uc_priv->bpix; + } + return 0; } diff --git a/include/bloblist.h b/include/bloblist.h index 2a2f1700eb0..7ea72c6bd46 100644 --- a/include/bloblist.h +++ b/include/bloblist.h @@ -113,6 +113,7 @@ enum bloblist_tag_t { BLOBLISTT_PROJECT_AREA = 0x8000, BLOBLISTT_U_BOOT_SPL_HANDOFF = 0x8000, /* Hand-off info from SPL */ BLOBLISTT_VBE = 0x8001, /* VBE per-phase state */ + BLOBLISTT_U_BOOT_VIDEO = 0x8002, /* Video information from SPL */ /* * Vendor-specific tags are permitted here. Projects can be open source diff --git a/include/video.h b/include/video.h index e98d0f9c895..9729fa348aa 100644 --- a/include/video.h +++ b/include/video.h @@ -134,6 +134,30 @@ struct video_ops { #define video_get_ops(dev) ((struct video_ops *)(dev)->driver->ops) +/** + * struct video_handoff - video information passed from SPL + * + * This is used when video is set up by SPL, to provide the details to U-Boot + * proper. + * + * @fb: Base address of frame buffer, 0 if not yet known + * @size: Frame-buffer size, in bytes + * @xsize: Number of pixel columns (e.g. 1366) + * @ysize: Number of pixels rows (e.g.. 768) + * @line_length: Length of each frame buffer line, in bytes. This can be + * set by the driver, but if not, the uclass will set it after + * probing + * @bpix: Encoded bits per pixel (enum video_log2_bpp) + */ +struct video_handoff { + u64 fb; + u32 size; + u16 xsize; + u16 ysize; + u32 line_length; + u8 bpix; +}; + /** enum colour_idx - the 16 colors supported by consoles */ enum colour_idx { VID_BLACK = 0, -- cgit v1.3.1 From b7d4df5a04733c19747de80b9dfdfdee58c9850d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:02 -0600 Subject: pci: Adjust video BIOS debugging to be SPL-friendly A hex value is expected for the VGA mode. Add a 0x prefix, since the # construct is not supported in SPL. We don't want to add it, due to code-size constraints. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index bdfd1f03e79..503feb1e6d4 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -273,7 +273,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), defined(CONFIG_FRAMEBUFFER_VESA_MODE) vesa_mode = CONFIG_FRAMEBUFFER_VESA_MODE; #endif - debug("Selected vesa mode %#x\n", vesa_mode); + debug("Selected vesa mode 0x%x\n", vesa_mode); if (exec_method & PCI_ROM_USE_NATIVE) { #ifdef CONFIG_X86 @@ -324,7 +324,7 @@ int dm_pci_run_vga_bios(struct udevice *dev, int (*int15_handler)(void), log_debug("done\n"); #endif } - debug("Final vesa mode %#x\n", mode_info.video_mode); + debug("Final vesa mode %x\n", mode_info.video_mode); ret = 0; err: -- cgit v1.3.1 From fa5690c1f53929b78f9d9f4e270bd64befcda755 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:03 -0600 Subject: pci: Mask the ROM address in case it is already enabled In some cases the video ROM may have been enabled previously, such as by a previous firmware stage. Use the correct address in that case. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/pci/pci_rom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 503feb1e6d4..438583aa017 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -93,6 +93,7 @@ static int pci_rom_probe(struct udevice *dev, struct pci_rom_header **hdrp) debug("%s: rom_address=%x\n", __func__, rom_address); return -ENOENT; } + rom_address &= PCI_ROM_ADDRESS_MASK; /* Enable expansion ROM address decoding. */ dm_pci_write_config32(dev, PCI_ROM_ADDRESS, -- cgit v1.3.1 From 6a324897825acdd54f31aeebfe0d29b7f6ab4d86 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:10 -0600 Subject: x86: Record the start and end of the tables The ACPI tables are special in that they are passed to EFI as a separate piece, independent of other tables. Also they can be spread over two areas of memory, e.g. with QEMU we end up with tables kept in high memory as well. Add new global_data fields to hold this information and update the bdinfo command to show the table areas. Move the rom_table_end variable into the loop that uses it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/include/asm/global_data.h | 4 ++++ arch/x86/include/asm/global_data.h | 4 ++++ arch/x86/lib/bdinfo.c | 4 ++++ arch/x86/lib/tables.c | 20 +++++++++++++++++++- drivers/misc/qfw.c | 9 +++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h index f4ce72d5660..f0ab3ba5c14 100644 --- a/arch/sandbox/include/asm/global_data.h +++ b/arch/sandbox/include/asm/global_data.h @@ -13,6 +13,10 @@ struct arch_global_data { uint8_t *ram_buf; /* emulated RAM buffer */ void *text_base; /* pointer to base of text region */ + ulong table_start; /* Start address of x86 tables */ + ulong table_end; /* End address of x86 tables */ + ulong table_start_high; /* Start address of high x86 tables */ + ulong table_end_high; /* End address of high x86 tables */ }; #include diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 22d103df4ee..ea58259ad77 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -123,6 +123,10 @@ struct arch_global_data { #endif void *itss_priv; /* Private ITSS data pointer */ ulong coreboot_table; /* Address of coreboot table */ + ulong table_start; /* Start address of x86 tables */ + ulong table_end; /* End address of x86 tables */ + ulong table_start_high; /* Start address of high x86 tables */ + ulong table_end_high; /* End address of high x86 tables */ }; #endif diff --git a/arch/x86/lib/bdinfo.c b/arch/x86/lib/bdinfo.c index a20d0954416..124058442c5 100644 --- a/arch/x86/lib/bdinfo.c +++ b/arch/x86/lib/bdinfo.c @@ -23,6 +23,10 @@ void arch_print_bdinfo(void) bdinfo_print_str(" name", cpu_vendor_name(gd->arch.x86_vendor)); bdinfo_print_num_l("model", gd->arch.x86_model); bdinfo_print_num_l("phys_addr in bits", cpu_phys_address_size()); + bdinfo_print_num_l("table start", gd->arch.table_start); + bdinfo_print_num_l("table end", gd->arch.table_end); + bdinfo_print_num_l(" high start", gd->arch.table_start_high); + bdinfo_print_num_l(" high end", gd->arch.table_end_high); if (IS_ENABLED(CONFIG_EFI_STUB)) efi_show_bdinfo(); diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 772c04f1e55..67bc0a72aeb 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -54,6 +54,10 @@ static struct table_info table_list[] = { #ifdef CONFIG_GENERATE_MP_TABLE { "mp", write_mp_table, }, #endif + /* + * tables which can go in the bloblist must be last in this list, so + * that the calculation of gd->table_end works properly + */ #ifdef CONFIG_GENERATE_ACPI_TABLE { "acpi", write_acpi_tables, BLOBLISTT_ACPI_TABLES, 0x10000, 0x1000}, #endif @@ -80,10 +84,12 @@ int write_tables(void) { u32 high_table, table_size; struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1]; + bool use_high = false; u32 rom_addr; int i; - rom_addr = ROM_TABLE_ADDR; + gd->arch.table_start = ROM_TABLE_ADDR; + rom_addr = gd->arch.table_start; debug("Writing tables to %x:\n", rom_addr); for (i = 0; i < ARRAY_SIZE(table_list); i++) { @@ -92,10 +98,17 @@ int write_tables(void) u32 rom_table_end; if (IS_ENABLED(CONFIG_BLOBLIST_TABLES) && table->tag) { + if (!gd->arch.table_end) + gd->arch.table_end = rom_addr; rom_addr = (ulong)bloblist_add(table->tag, size, table->align); if (!rom_addr) return log_msg_ret("bloblist", -ENOBUFS); + + /* the bloblist is always in high memory */ + use_high = true; + if (!gd->arch.table_start_high) + gd->arch.table_start_high = rom_addr; } rom_table_end = table->write(rom_addr); if (!rom_table_end) { @@ -132,6 +145,11 @@ int write_tables(void) rom_addr = rom_table_end; } + if (use_high) + gd->arch.table_end_high = rom_addr; + else + gd->arch.table_end = rom_addr; + if (IS_ENABLED(CONFIG_SEABIOS)) { /* make sure the last item is zero */ cfg_tables[i].size = 0; diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 0a93feeb4b2..7c01bf23d53 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -65,6 +65,11 @@ static int bios_linker_allocate(struct udevice *dev, printf("error: allocating resource\n"); return -ENOMEM; } + if (aligned_addr < gd->arch.table_start_high) + gd->arch.table_start_high = aligned_addr; + if (aligned_addr + size > gd->arch.table_end_high) + gd->arch.table_end_high = aligned_addr + size; + } else if (entry->alloc.zone == BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG) { aligned_addr = ALIGN(*addr, align); } else { @@ -189,6 +194,10 @@ ulong write_acpi_tables(ulong addr) return addr; } + /* QFW always puts tables at high addresses */ + gd->arch.table_start_high = (ulong)table_loader; + gd->arch.table_end_high = (ulong)table_loader; + qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader); for (i = 0; i < (size / sizeof(*entry)); i++) { -- cgit v1.3.1 From e2e7de874766a1e7b21a7174bf88efa2ef6b6e56 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:11 -0600 Subject: x86: Convert some debug statements to use logging Move from using debug() to log_debug() so that we don't have to use the __func__ parameter and can access other logging features. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/intel_common/mrc.c | 10 +++++----- arch/x86/cpu/ivybridge/sdram.c | 4 +++- arch/x86/lib/mrccache.c | 6 ++++-- arch/x86/lib/spl.c | 22 ++++++++++++++-------- drivers/gpio/intel_ich6_gpio.c | 5 +++-- drivers/pch/pch9.c | 6 ++++-- 6 files changed, 33 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/arch/x86/cpu/intel_common/mrc.c b/arch/x86/cpu/intel_common/mrc.c index 69405d740b4..56cc253831a 100644 --- a/arch/x86/cpu/intel_common/mrc.c +++ b/arch/x86/cpu/intel_common/mrc.c @@ -3,6 +3,8 @@ * Copyright (c) 2016 Google, Inc */ +#define LOG_CATEGORY UCLASS_RAM + #include #include #include @@ -144,12 +146,10 @@ int mrc_locate_spd(struct udevice *dev, int size, const void **spd_datap) ret = gpio_request_list_by_name(dev, "board-id-gpios", desc, ARRAY_SIZE(desc), GPIOD_IS_IN); - if (ret < 0) { - debug("%s: gpio ret=%d\n", __func__, ret); - return ret; - } + if (ret < 0) + return log_msg_ret("gpio", ret); spd_index = dm_gpio_get_values_as_int(desc, ret); - debug("spd index %d\n", spd_index); + log_debug("spd index %d\n", spd_index); node = fdt_first_subnode(blob, dev_of_offset(dev)); if (node < 0) diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 1a0ec433e65..0718aefbb1f 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -9,6 +9,8 @@ * Copyright (C) 2011 Google Inc. */ +#define LOG_CATEGORY UCLASS_RAM + #include #include #include @@ -213,7 +215,7 @@ static int copy_spd(struct udevice *dev, struct pei_data *peid) ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data); if (ret) { - debug("%s: Could not locate SPD (ret=%d)\n", __func__, ret); + log_debug("Could not locate SPD (err=%d)\n", ret); return ret; } diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index 2f6f6880003..6494b8d2634 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -6,6 +6,8 @@ * Copyright (C) 2015 Bin Meng */ +#define LOG_CATEGORY UCLASS_RAM + #include #include #include @@ -197,8 +199,8 @@ static void mrccache_setup(struct mrc_output *mrc, void *data) cache->signature = MRC_DATA_SIGNATURE; cache->data_size = mrc->len; checksum = compute_ip_checksum(mrc->buf, cache->data_size); - debug("Saving %d bytes for MRC output data, checksum %04x\n", - cache->data_size, checksum); + log_debug("Saving %d bytes for MRC output data, checksum %04x\n", + cache->data_size, checksum); cache->checksum = checksum; cache->reserved = 0; memcpy(cache->data, mrc->buf, cache->data_size); diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 92a5e6aec71..ba3434b055c 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -3,6 +3,8 @@ * Copyright (c) 2016 Google, Inc */ +#define LOG_CATEGORY LOGC_BOOT + #include #include #include @@ -76,25 +78,25 @@ static int x86_spl_init(void) #endif int ret; - debug("%s starting\n", __func__); + log_debug("x86 spl starting\n"); if (IS_ENABLED(TPL)) ret = x86_cpu_reinit_f(); else ret = x86_cpu_init_f(); ret = spl_init(); if (ret) { - debug("%s: spl_init() failed\n", __func__); + log_debug("spl_init() failed (err=%d)\n", ret); return ret; } ret = arch_cpu_init(); if (ret) { - debug("%s: arch_cpu_init() failed\n", __func__); + log_debug("arch_cpu_init() failed (err=%d)\n", ret); return ret; } #ifndef CONFIG_TPL ret = fsp_setup_pinctrl(NULL, NULL); if (ret) { - debug("%s: fsp_setup_pinctrl() failed\n", __func__); + log_debug("fsp_setup_pinctrl() failed (err=%d)\n", ret); return ret; } #endif @@ -108,23 +110,25 @@ static int x86_spl_init(void) #if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU) ret = print_cpuinfo(); if (ret) { - debug("%s: print_cpuinfo() failed\n", __func__); + log_debug("print_cpuinfo() failed (err=%d)\n", ret); return ret; } #endif ret = dram_init(); if (ret) { - debug("%s: dram_init() failed\n", __func__); + log_debug("dram_init() failed (err=%d)\n", ret); return ret; } + log_debug("mrc\n"); if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) { ret = mrccache_spl_save(); if (ret) - debug("%s: Failed to write to mrccache (err=%d)\n", - __func__, ret); + log_debug("Failed to write to mrccache (err=%d)\n", + ret); } #ifndef CONFIG_SYS_COREBOOT + log_debug("bss\n"); debug("BSS clear from %lx to %lx len %lx\n", (ulong)&__bss_start, (ulong)&__bss_end, (ulong)&__bss_end - (ulong)&__bss_start); memset(&__bss_start, 0, (ulong)&__bss_end - (ulong)&__bss_start); @@ -145,6 +149,7 @@ static int x86_spl_init(void) gd->new_gd = (struct global_data *)ptr; memcpy(gd->new_gd, gd, sizeof(*gd)); + log_debug("logging\n"); /* * Make sure logging is disabled when we switch, since the log system * list head will move @@ -184,6 +189,7 @@ static int x86_spl_init(void) debug("Failed to set CPU frequency (err=%d)\n", ret); # endif #endif + log_debug("done\n"); return 0; } diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index 63a07b9592a..2ed0d0bea9a 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -26,6 +26,8 @@ * reserved or subject to arcane restrictions. */ +#define LOG_CATEGORY UCLASS_GPIO + #include #include #include @@ -155,8 +157,7 @@ static int ich6_gpio_request(struct udevice *dev, unsigned offset, */ tmplong = inl(bank->use_sel); if (!(tmplong & (1UL << offset))) { - debug("%s: gpio %d is reserved for internal use\n", __func__, - offset); + log_debug("gpio %d is reserved for internal use\n", offset); return -EPERM; } diff --git a/drivers/pch/pch9.c b/drivers/pch/pch9.c index 3bd011518b3..3137eb2c28f 100644 --- a/drivers/pch/pch9.c +++ b/drivers/pch/pch9.c @@ -3,6 +3,8 @@ * Copyright (C) 2014 Google, Inc */ +#define LOG_CATEGORY UCLASS_PCH + #include #include #include @@ -38,7 +40,7 @@ static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep) */ dm_pci_read_config32(dev, GPIO_BASE, &base); if (base == 0x00000000 || base == 0xffffffff) { - debug("%s: unexpected BASE value\n", __func__); + log_debug("unexpected BASE value\n"); return -ENODEV; } @@ -59,7 +61,7 @@ static int pch9_get_io_base(struct udevice *dev, u32 *iobasep) dm_pci_read_config32(dev, IO_BASE, &base); if (base == 0x00000000 || base == 0xffffffff) { - debug("%s: unexpected BASE value\n", __func__); + log_debug("unexpected BASE value\n"); return -ENODEV; } -- cgit v1.3.1 From e2d934b4dae97493db2a74211a82b433776e2000 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 15 Jul 2023 21:39:18 -0600 Subject: x86: video: Add a driver for QEMU bochs emulation Bochs is convenient with QEMU on x86 since it does not require a video BIOS. Add a driver for it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- drivers/video/Kconfig | 30 ++++++++++++ drivers/video/Makefile | 1 + drivers/video/bochs.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/video/bochs.h | 36 +++++++++++++++ 4 files changed, 190 insertions(+) create mode 100644 drivers/video/bochs.c create mode 100644 drivers/video/bochs.h (limited to 'drivers') diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 49762950719..2ba4f5eac7f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -278,6 +278,36 @@ config VIDCONSOLE_AS_NAME possible to update the environment, the breakage may be confusing for users. This option will be removed around the end of 2020. +config VIDEO_BOCHS + bool "Enable Bochs video emulation for QEMU" + depends on X86 + help + Enable this to use the Bochs video support provided in the QEMU + emulator. This appears as a PCI device which U-Boot can set up to + provide a frame buffer. + +if VIDEO_BOCHS + +config VIDEO_BOCHS_SIZE_X + int "Width of display (X resolution)" + default 1280 + help + Sets the width of the display. + + These two options control the size of the display set up by QEMU. + Typical sizes are 1024 x 768 or 1280 x 1024. + +config VIDEO_BOCHS_SIZE_Y + int "High of display (Y resolution)" + default 1024 + help + Sets the height of the display. + + These two options control the size of the display set up by QEMU. + Typical sizes are 1024 x 768 or 1280 x 1024. + +endif + config VIDEO_COREBOOT bool "Enable coreboot framebuffer driver support" depends on X86 diff --git a/drivers/video/Makefile b/drivers/video/Makefile index f99d7e3c3d9..a9263709084 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_OSD) += video_osd-uclass.o obj-$(CONFIG_SANDBOX_OSD) += sandbox_osd.o obj-$(CONFIG_VIDEO_ARM_MALIDP) += mali_dp.o obj-$(CONFIG_VIDEO_BCM2835) += bcm2835.o +obj-$(CONFIG_VIDEO_BOCHS) += bochs.o obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o obj-$(CONFIG_VIDEO_DW_HDMI) += dw_hdmi.o diff --git a/drivers/video/bochs.c b/drivers/video/bochs.c new file mode 100644 index 00000000000..2136b511936 --- /dev/null +++ b/drivers/video/bochs.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Modified from coreboot bochs.c + */ + +#define LOG_CATEGORY UCLASS_VIDEO + +#include +#include +#include +#include +#include +#include +#include +#include +#include "bochs.h" + +static int xsize = CONFIG_VIDEO_BOCHS_SIZE_X; +static int ysize = CONFIG_VIDEO_BOCHS_SIZE_Y; + +static void bochs_write(void *mmio, int index, int val) +{ + writew(val, mmio + MMIO_BASE + index * 2); +} + +static int bochs_read(void *mmio, int index) +{ + return readw(mmio + MMIO_BASE + index * 2); +} + +static void bochs_vga_write(int index, uint8_t val) +{ + outb(val, VGA_INDEX); +} + +static int bochs_init_fb(struct udevice *dev) +{ + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + ulong fb; + void *mmio; + int id, mem; + + log_debug("probing %s at PCI %x\n", dev->name, dm_pci_get_bdf(dev)); + fb = dm_pci_read_bar32(dev, 0); + if (!fb) + return log_msg_ret("fb", -EIO); + + /* MMIO bar supported since qemu 3.0+ */ + mmio = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, PCI_REGION_TYPE, + PCI_REGION_MEM); + + if (!mmio) + return log_msg_ret("map", -EIO); + + /* bochs dispi detection */ + id = bochs_read(mmio, INDEX_ID); + if ((id & 0xfff0) != ID0) { + log_debug("ID mismatch\n"); + return -EPROTONOSUPPORT; + } + mem = bochs_read(mmio, INDEX_VIDEO_MEMORY_64K) * SZ_64K; + log_debug("QEMU VGA: bochs @ %p: %d MiB FB at %lx\n", mmio, mem / SZ_1M, + fb); + + uc_priv->xsize = xsize; + uc_priv->ysize = ysize; + uc_priv->bpix = VIDEO_BPP32; + + /* setup video mode */ + bochs_write(mmio, INDEX_ENABLE, 0); + bochs_write(mmio, INDEX_BANK, 0); + bochs_write(mmio, INDEX_BPP, VNBITS(uc_priv->bpix)); + bochs_write(mmio, INDEX_XRES, xsize); + bochs_write(mmio, INDEX_YRES, ysize); + bochs_write(mmio, INDEX_VIRT_WIDTH, xsize); + bochs_write(mmio, INDEX_VIRT_HEIGHT, ysize); + bochs_write(mmio, INDEX_X_OFFSET, 0); + bochs_write(mmio, INDEX_Y_OFFSET, 0); + bochs_write(mmio, INDEX_ENABLE, ENABLED | LFB_ENABLED); + + bochs_vga_write(0, 0x20); /* disable blanking */ + + plat->base = fb; + + return 0; +} + +static int bochs_video_probe(struct udevice *dev) +{ + int ret; + + ret = bochs_init_fb(dev); + if (ret) + return log_ret(ret); + + return 0; +} + +static int bochs_video_bind(struct udevice *dev) +{ + struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); + + /* Set the maximum supported resolution */ + uc_plat->size = 2560 * 1600 * 4; + log_debug("%s: Frame buffer size %x\n", __func__, uc_plat->size); + + return 0; +} + +U_BOOT_DRIVER(bochs_video) = { + .name = "bochs_video", + .id = UCLASS_VIDEO, + .bind = bochs_video_bind, + .probe = bochs_video_probe, +}; + +static struct pci_device_id bochs_video_supported[] = { + { PCI_DEVICE(0x1234, 0x1111) }, + { }, +}; + +U_BOOT_PCI_DEVICE(bochs_video, bochs_video_supported); diff --git a/drivers/video/bochs.h b/drivers/video/bochs.h new file mode 100644 index 00000000000..4c8ec83a550 --- /dev/null +++ b/drivers/video/bochs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Modified from coreboot bochs.c + */ + +#ifndef __BOCHS_H +#define __BOCHS_H + +#define VGA_INDEX 0x3c0 + +#define IOPORT_INDEX 0x01ce +#define IOPORT_DATA 0x01cf + +enum { + INDEX_ID, + INDEX_XRES, + INDEX_YRES, + INDEX_BPP, + INDEX_ENABLE, + INDEX_BANK, + INDEX_VIRT_WIDTH, + INDEX_VIRT_HEIGHT, + INDEX_X_OFFSET, + INDEX_Y_OFFSET, + INDEX_VIDEO_MEMORY_64K +}; + +#define ID0 0xb0c0 + +#define ENABLED BIT(0) +#define LFB_ENABLED BIT(6) +#define NOCLEARMEM BIT(7) + +#define MMIO_BASE 0x500 + +#endif -- cgit v1.3.1