We expect to use the space between the top of option ROMs and the bottom
of our own BIOS code as a stack. OVMF was previously marking the whole
region from 0xC0000 to 0xFFFFF read-only before invoking our Legacy16Boot
method. Read-only stack considered harmful.
Version 0.98 of the CSM spec adds the UmaAddress and UmaSize fields, which
allow the CSM to specify a memory region that needs to be writable.
There exists CONFIG_MALLOC_UPPERMEMORY which we could turn off to use
the 9-segment, but that isn't particularly useful for the CSM case
either because that memory isn't ours to play with until the final
Legacy16Boot call. There's a LowPmmMemory given to use by UEFI to play
with, but that's right in the *middle* of low memory and using that for
persistent allocations would be painful. So just require
CONFIG_MALLOC_UPPERMEMORY when building a CSM.
Signed-off-by: David Woodhouse <David.Woodhouse(a)intel.com>
---
v2: Require CONFIG_MALLOC_UPPERMEMORY. Default UmaAddress to &zonelow_base.
src/Kconfig | 2 +-
src/fw/csm.c | 6 +++++-
src/std/LegacyBios.h | 20 ++++++++++++++++++++
3 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig
index a42ab2d..093075c 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -114,7 +114,7 @@ endchoice
the BIOS in 16bit protected mode.
config MALLOC_UPPERMEMORY
- bool "Allocate memory that needs to be in first Meg above 0xc0000"
+ bool "Allocate memory that needs to be in first Meg above 0xc0000" if !CSM
default y
help
Use the "Upper Memory Block" area (0xc0000-0xf0000) for
diff --git a/src/fw/csm.c b/src/fw/csm.c
index dfb0d12..4e4b688 100644
--- a/src/fw/csm.c
+++ b/src/fw/csm.c
@@ -34,6 +34,8 @@ EFI_COMPATIBILITY16_TABLE csm_compat_table VARFSEG __aligned(16) = {
.Compatibility16CallOffset = 0 /* Filled in by checkrom.py */,
.OemIdStringPointer = (u32)"SeaBIOS",
.AcpiRsdPtrPointer = (u32)&csm_rsdp,
+ .UmaAddress = (u32)&zonelow_base,
+ .UmaSize = 0x10000,
};
EFI_TO_COMPATIBILITY16_INIT_TABLE *csm_init_table;
@@ -46,9 +48,11 @@ extern void __csm_return(struct bregs *regs) __noreturn;
static void
csm_return(struct bregs *regs)
{
- dprintf(3, "handle_csm returning AX=%04x\n", regs->ax);
+ u32 top = rom_get_max();
PICMask = pic_irqmask_read();
+ csm_compat_table.UmaAddress = top;
+ csm_compat_table.UmaSize = 0xf0000 - top;
__csm_return(regs);
}
diff --git a/src/std/LegacyBios.h b/src/std/LegacyBios.h
index cf0c3c5..5170c37 100644
--- a/src/std/LegacyBios.h
+++ b/src/std/LegacyBios.h
@@ -228,6 +228,26 @@ typedef struct {
/// Maximum PCI bus number assigned.
///
UINT8 LastPciBus;
+
+ ///
+ /// Start address of UMB RAM
+ ///
+ UINT32 UmaAddress;
+
+ ///
+ /// Size of UMB RAM
+ ///
+ UINT32 UmaSize;
+
+ ///
+ /// Start address of persistent allocation in high (>1MiB) memory
+ ///
+ UINT32 HiPermanentMemoryAddress;
+
+ ///
+ /// Size of persistent allocation in high (>1MiB) memory
+ ///
+ UINT32 HiPermanentMemorySize;
} EFI_COMPATIBILITY16_TABLE;
///
--
1.8.3.1
--
David Woodhouse Open Source Technology Centre
David.Woodhouse(a)intel.com Intel Corporation
As with the recent change to AHCI, if the pvscsi driver needs to jump
into 32bit mode to access a register, then it's better to run the
pvscsi driver entirely in 32bit mode.
Evgeny, can you take a look at this and give it a test? Also, what
command line do you use for testing?
I tried testing locally by adding:
-device pvscsi,id=pvscsi0 -device scsi-disk,bus=pvscsi0.0,drive=drive0 -drive id=drive0,if=none,file=dos-drivec-new
to my qemu command line (both qemu v1.6 and qemu v1.7), but it doesn't
work for me even before my changes. It hangs in
pvscsi_wait_intr_cmpl().
-Kevin
Kevin O'Connor (3):
pvscsi: Don't store reference to struct pci_device.
pvscsi: Always run entirely in 32bit mode.
pvscsi: Remove use of LOWFLAT and GLOBALFLAT macros.
Makefile | 4 +--
src/block.c | 8 +++--
src/hw/blockcmd.c | 3 +-
src/hw/pvscsi.c | 106 +++++++++++++++++++++++++-----------------------------
4 files changed, 58 insertions(+), 63 deletions(-)
--
1.8.3.1
This provides basic debug output on the Quark system, assuming that
*something* (i.e. coreboot or UEFI) has set it up in advance for us.
Signed-off-by: David Woodhouse <David.Woodhouse(a)intel.com>
---
I looked briefly at making this part of the CONFIG_DEBUG_SERIAL code,
and making that generic enough to handle I/O access *or* MMIO access
depending on what's present... but in fact that's probably overkill.
This isn't really limited to Quark; it would work with any 16550 device
wired up as MMIO32. But we can expand it as required, I think. No point
in starting off with the same functionality as the 5000-odd lines of the
Linux kernel's 8250_pci.c.
What do I need to do if called in 32-bit segmented mode? I'm guessing
that's not going to work right now...
src/Kconfig | 5 +++++
src/fw/csm.c | 2 ++
src/output.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+)
diff --git a/src/Kconfig b/src/Kconfig
index a42ab2d..bdc2602 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -472,6 +472,11 @@ menu "Debugging"
Set to zero to disable debugging.
+ config DEBUG_QUARK_UART
+ depends on DEBUG_LEVEL != 0
+ bool "Debug to Quark UART #1"
+ default n
+
config DEBUG_SERIAL
depends on DEBUG_LEVEL != 0
bool "Serial port debugging"
diff --git a/src/fw/csm.c b/src/fw/csm.c
index dfb0d12..afd7ffe 100644
--- a/src/fw/csm.c
+++ b/src/fw/csm.c
@@ -280,6 +280,8 @@ handle_csm(struct bregs *regs)
if (!CONFIG_CSM)
return;
+ debug_serial_preinit();
+
dprintf(3, "handle_csm regs %p AX=%04x\n", regs, regs->ax);
pic_irqmask_write(PICMask);
diff --git a/src/output.c b/src/output.c
index b47625f..a90d350 100644
--- a/src/output.c
+++ b/src/output.c
@@ -17,6 +17,8 @@
#include "stacks.h" // call16_int
#include "string.h" // memset
#include "util.h" // ScreenAndDebug
+#include "hw/pci_regs.h" // PCI_VENDOR_ID, PCI_BASE_ADDRESS_0
+#include "hw/pci.h" // pci_config_readl
struct putcinfo {
void (*func)(struct putcinfo *info, char c);
@@ -31,9 +33,59 @@ struct putcinfo {
u16 DebugOutputPort VARFSEG = 0x402;
+static volatile u32 *quark_uart_addr = 0;
+
+extern void _cfunc32flat_quark_uart_preinit(void);
+extern void _cfunc32flat_quark_uart_putc(void);
+extern void _cfunc32flat_quark_uart_flush(void);
+
+void quark_uart_preinit(void)
+{
+ // debug port is bus 0, device 0x14, function 5.
+ u16 uart_bdf = pci_to_bdf(0, 0x14, 5);
+
+ // If it isn't a Quark UART...
+ if (pci_config_readl(uart_bdf, PCI_VENDOR_ID) != 0x09368086)
+ return;
+
+ u32 bar0 = pci_config_readl(uart_bdf, PCI_BASE_ADDRESS_0);
+ if (!(bar0 & 0xf))
+ quark_uart_addr = (void *)bar0;
+}
+
+void quark_uart_putc(char c)
+{
+ if (!quark_uart_addr)
+ return;
+
+ int timeout = DEBUG_TIMEOUT;
+ while ((quark_uart_addr[SEROFF_LSR] & 0x20) != 0x20)
+ if (!timeout--)
+ // Ran out of time.
+ return;
+ quark_uart_addr[SEROFF_DATA] = c;
+}
+
+void quark_uart_flush(void)
+{
+ if (!quark_uart_addr)
+ return;
+ int timeout = DEBUG_TIMEOUT;
+ while ((quark_uart_addr[SEROFF_LSR] & 0x60) != 0x60)
+ if (!timeout--)
+ // Ran out of time.
+ return;
+}
+
void
debug_serial_preinit(void)
{
+ if (CONFIG_DEBUG_QUARK_UART) {
+ if (MODE16)
+ call32(_cfunc32flat_quark_uart_preinit, 0, 0);
+ else
+ quark_uart_preinit();
+ }
if (!CONFIG_DEBUG_SERIAL)
return;
// setup for serial logging: 8N1
@@ -54,6 +106,12 @@ debug_serial_preinit(void)
static void
debug_serial(char c)
{
+ if (CONFIG_DEBUG_QUARK_UART) {
+ if (MODE16)
+ call32(_cfunc32flat_quark_uart_putc, c, 0);
+ else
+ quark_uart_putc(c);
+ }
if (!CONFIG_DEBUG_SERIAL)
return;
int timeout = DEBUG_TIMEOUT;
@@ -68,6 +126,12 @@ debug_serial(char c)
static void
debug_serial_flush(void)
{
+ if (CONFIG_DEBUG_QUARK_UART) {
+ if (MODE16)
+ call32(_cfunc32flat_quark_uart_flush, 0, 0);
+ else
+ quark_uart_flush();
+ }
if (!CONFIG_DEBUG_SERIAL)
return;
int timeout = DEBUG_TIMEOUT;
--
1.8.3.1
--
dwmw2
This patch improves the io address space allocation. It adds a check
that the region above 0xc000 which is traditionally used for pci io
is actually big enougth. If it isn't it tries the larger window at
0x1000. If that is to small too it errors out.
When creating guests with multiple pci-pci bridges (and devices with
io regions behind them) the 0xc000 -> 0xffff region quickly becomes
too small.
While being at it document the io address space layout used by
qemu/seabios.
Signed-off-by: Gerd Hoffmann <kraxel(a)redhat.com>
---
src/fw/pciinit.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 5 deletions(-)
diff --git a/src/fw/pciinit.c b/src/fw/pciinit.c
index b0d01ca..64f1d41 100644
--- a/src/fw/pciinit.c
+++ b/src/fw/pciinit.c
@@ -705,10 +705,42 @@ static int pci_bios_check_devices(struct pci_bus *busses)
****************************************************************/
// Setup region bases (given the regions' size and alignment)
-static int pci_bios_init_root_regions(struct pci_bus *bus)
-{
- bus->r[PCI_REGION_TYPE_IO].base = 0xc000;
+static int pci_bios_init_root_regions_io(struct pci_bus *bus)
+{
+ /*
+ * QEMU I/O address space usage:
+ * 0000 - 0fff legacy isa, pci config, pci root bus, ...
+ * 1000 - 9fff free
+ * a000 - afff hotplug (cpu, pci via acpi, i440fx/piix only)
+ * b000 - bfff power management (PORT_ACPI_PM_BASE)
+ * [ qemu 1.4+ implements pci config registers
+ * properly so guests can place the registers
+ * where they want, on older versions its fixed ]
+ * c000 - ffff free, traditionally used for pci io
+ */
+ struct pci_region *r_io = &bus->r[PCI_REGION_TYPE_IO];
+ u64 sum = pci_region_sum(r_io);
+ if (sum < 0x4000) {
+ /* traditional region is big enougth, use it */
+ r_io->base = 0xc000;
+ } else if (sum < 0x9000) {
+ /* use the larger region at 0x1000 */
+ r_io->base = 0x1000;
+ } else {
+ /*
+ * Not enougth io address space -> error out.
+ *
+ * TODO: on q35 we can move PORT_ACPI_PM_BASE out of
+ * the way, then use the whole 1000 -> ffff region.
+ */
+ return -1;
+ }
+ dprintf(1, "PCI: IO: %4llx - %4llx\n", r_io->base, r_io->base + sum - 1);
+ return 0;
+}
+static int pci_bios_init_root_regions_mem(struct pci_bus *bus)
+{
struct pci_region *r_end = &bus->r[PCI_REGION_TYPE_PREFMEM];
struct pci_region *r_start = &bus->r[PCI_REGION_TYPE_MEM];
@@ -786,8 +818,11 @@ static void pci_region_map_entries(struct pci_bus *busses, struct pci_region *r)
static void pci_bios_map_devices(struct pci_bus *busses)
{
+ if (pci_bios_init_root_regions_io(busses))
+ panic("PCI: out of I/O address space\n");
+
dprintf(1, "PCI: 32: %016llx - %016llx\n", pcimem_start, pcimem_end);
- if (pci_bios_init_root_regions(busses)) {
+ if (pci_bios_init_root_regions_mem(busses)) {
struct pci_region r64_mem, r64_pref;
r64_mem.list.first = NULL;
r64_pref.list.first = NULL;
@@ -796,7 +831,7 @@ static void pci_bios_map_devices(struct pci_bus *busses)
pci_region_migrate_64bit_entries(&busses[0].r[PCI_REGION_TYPE_PREFMEM],
&r64_pref);
- if (pci_bios_init_root_regions(busses))
+ if (pci_bios_init_root_regions_mem(busses))
panic("PCI: out of 32bit address space\n");
u64 sum_mem = pci_region_sum(&r64_mem);
--
1.8.3.1
The "links" file is a newline separated list where each line is a
"link name" followed by a "destination name" separated by a space
character. For each line, SeaBIOS will consider each "link name" to
be a CBFS file that has the contents found in the CBFS file with
"destination name".
Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
---
This patch may be useful for those using intel option roms where the
same rom is used on a number of VGA devices with different
vendor/device ids. With this patch, one can make a "links" file with
the list of devices (eg, "pci8086,0a06.rom") that all point to the
same physical rom (eg, "pci8086,0406.rom").
It's possible to implement this aliasing approach in a number of
different ways. The approach taken in this patch is a single file
with all the link names. This was done based on feedback that there
could be 20 or more aliases for a single rom and creating individual
CBFS files for each link would be unwieldy.
That said, I'm not sure this is the best approach. I'm circulating it
for comments.
---
src/fw/coreboot.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/src/fw/coreboot.c b/src/fw/coreboot.c
index df8fca8..270d01a 100644
--- a/src/fw/coreboot.c
+++ b/src/fw/coreboot.c
@@ -408,6 +408,40 @@ coreboot_cbfs_init(void)
fhdr = (void*)ALIGN((u32)cfile->data + cfile->rawsize
, be32_to_cpu(hdr->align));
}
+
+ // Process CBFS links file. The links file is a newline separated
+ // file where each line has a "link name" and a destination name
+ // separated by a space character.
+ char *links = romfile_loadfile("links", NULL);
+ if (!links)
+ return;
+ char *p = links;
+ for (;;) {
+ char *linkname = p;
+ char *end = strchr(linkname, '\n');
+ if (!end)
+ break;
+ *end = '\0';
+ p = end + 1;
+ char *linkend = strchr(linkname, ' ');
+ if (!linkend || linkname == linkend)
+ continue;
+ *linkend = '\0';
+ struct romfile_s *ufile = romfile_find(linkend+1);
+ if (!ufile)
+ continue;
+ struct cbfs_romfile_s *cufile
+ = container_of(ufile, struct cbfs_romfile_s, file);
+ struct cbfs_romfile_s *cfile = malloc_tmp(sizeof(*cfile));
+ if (!cfile) {
+ warn_noalloc();
+ break;
+ }
+ memcpy(cfile, cufile, sizeof(*cfile));
+ strtcpy(cfile->file.name, linkname, sizeof(cfile->file.name));
+ romfile_add(&cfile->file);
+ }
+ free(links);
}
struct cbfs_payload_segment {
--
1.8.5.3
On Fri, Jan 17, 2014 at 04:50:27PM -0800, Stefan Reinauer wrote:
> Yes, I think it's worth having them in upstream SeaBIOS!
>
> I've been thinking about creating a way of passing this information between
> coreboot and SeaBIOS in the future, so we don't have to keep the handlers
> around twice. One way of doing that would be to have the handler live in
> SMM and have SeaBIOS do an SMI command to get the right answers. Would you
> be open to something like that?
That seems over kill to me. The Intel VGA stuff seems to be pretty
stable and it's only a few fields that need to be passed back. What
about placing the required info in a coreboot table - then SeaBIOS can
just pass back the desired fields and not have to have board by board
specific logic.
BTW, I didn't port over "Alex" as it seems to be totally different
from the other boards.
-Kevin
On Mon, Jan 27, 2014 at 12:29:11PM -0500, Kevin O'Connor wrote:
> Also, the max packet size for super speed devices is 512 bytes (not
> 256 bytes).
>
> Signed-off-by: Kevin O'Connor <kevin(a)koconnor.net>
> ---
>
> Some additional patches on my xhci-testing branch. Also available at:
>
> https://github.com/KevinOConnor/seabios/tree/xhci-testing
FYI, I have pushed the xhci-testing branch to the seabios master
branch.
-Kevin