]> xenbits.xensource.com Git - seabios.git/commitdiff
vgabios: Support allocating an extra stack for vgabios calls and default on.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 1 Dec 2013 00:16:15 +0000 (19:16 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Wed, 4 Dec 2013 15:34:18 +0000 (10:34 -0500)
Add code to allocate an extra stack for the main vgabios int 0x10
entry point.  The allocation is done via the PMM spec and uses a PCI
v3 permanent low memory region request.  This request will work with
SeaBIOS - it is unknown how many other main BIOS implementations
support this PMM call.

The extra stack is useful for old DOS programs that call the VGABIOS
and expect it to work with very small amounts of stack space.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Makefile
vgasrc/Kconfig
vgasrc/vgabios.c
vgasrc/vgaentry.S

index e39222be72083c31fbbcf7a5f2458942cd38e5bf..59aae99a6fa7806173ec2c0c2d71f7e8d548e8da 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -215,7 +215,7 @@ $(OUT)vgaccode16.o: $(OUT)vgaccode16.raw.s scripts/vgafixup.py
        $(Q)$(PYTHON) ./scripts/vgafixup.py $< $(OUT)vgaccode16.s
        $(Q)$(AS) --32 src/code16gcc.s $(OUT)vgaccode16.s -o $@
 
-$(OUT)vgaentry.o: vgasrc/vgaentry.S $(OUT)autoconf.h
+$(OUT)vgaentry.o: vgasrc/vgaentry.S $(OUT)autoconf.h $(OUT)asm-offsets.h
        @echo "  Compiling (16bit) $@"
        $(Q)$(CC) $(CFLAGS16VGA) -c -D__ASSEMBLY__ $< -o $@
 
index 0901c045be4e41e0b137298b089735f7b27fd0b1..b442b3e83259a82eed50a735012f117159970f00 100644 (file)
@@ -68,6 +68,20 @@ menu "VGA ROM"
         bool
         default !NO_VGABIOS
 
+    config VGA_ALLOCATE_EXTRA_STACK
+        depends on BUILD_VGABIOS
+        bool "Allocate an internal stack for 16bit interrupt entry point"
+        default y
+        help
+            Attempt to allocate (via BIOS PMM call) an internal stack
+            for the legacy 16bit 0x10 interrupt entry point.  This
+            reduces the amount of space on the caller's stack that
+            SeaVGABIOS uses.
+
+    config VGA_EXTRA_STACK_SIZE
+        int
+        default 512
+
     config VGA_VBE
         depends on BUILD_VGABIOS
         bool "Video BIOS Extensions (VBE)"
index 35d036244657399ececad31dc1835a4e5dfa9f2b..d93b19006025fb44908a1aa77c39e25eef88c762 100644 (file)
@@ -13,6 +13,7 @@
 #include "hw/pci_regs.h" // PCI_VENDOR_ID
 #include "output.h" // dprintf
 #include "std/optionrom.h" // struct pci_data
+#include "std/pmm.h" // struct pmmheader
 #include "std/vbe.h" // VBE_RETURN_STATUS_FAILED
 #include "stdvga.h" // stdvga_set_cursor_shape
 #include "string.h" // memset_far
@@ -1277,6 +1278,46 @@ init_bios_area(void)
     SET_BDA(video_msr, 0x09);
 }
 
+u16 ExtraStackSeg VAR16 VISIBLE16;
+
+static void
+allocate_extra_stack(void)
+{
+    if (!CONFIG_VGA_ALLOCATE_EXTRA_STACK)
+        return;
+    void *pmmscan = (void*)BUILD_BIOS_ADDR;
+    for (; pmmscan < (void*)BUILD_BIOS_ADDR+BUILD_BIOS_SIZE; pmmscan+=16) {
+        struct pmmheader *pmm = pmmscan;
+        if (pmm->signature != PMM_SIGNATURE)
+            continue;
+        if (checksum_far(0, pmm, pmm->length))
+            continue;
+        struct segoff_s entry = pmm->entry;
+        dprintf(1, "Attempting to allocate VGA stack via pmm call to %04x:%04x\n"
+                , entry.seg, entry.offset);
+        u16 res1, res2;
+        asm volatile(
+            "pushl %0\n"
+            "pushw $(8|1)\n"            // Permanent low memory request
+            "pushl $0xffffffff\n"       // Anonymous handle
+            "pushl $" __stringify(CONFIG_VGA_EXTRA_STACK_SIZE) "\n"
+            "pushw $0x00\n"             // PMM allocation request
+            "lcallw *12(%%esp)\n"
+            "addl $16, %%esp\n"
+            "cli\n"
+            "cld\n"
+            : "+r" (entry.segoff), "=a" (res1), "=d" (res2) : : "cc", "memory");
+        u32 res = res1 | (res2 << 16);
+        if (!res || res == PMM_FUNCTION_NOT_SUPPORTED)
+            return;
+        dprintf(1, "VGA stack allocated at %x\n", res);
+        SET_VGA(ExtraStackSeg, res >> 4);
+        extern void entry_10_extrastack(void);
+        SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10_extrastack));
+        return;
+    }
+}
+
 int VgaBDF VAR16 = -1;
 int HaveRunInit VAR16;
 
@@ -1314,6 +1355,8 @@ vga_post(struct bregs *regs)
     extern void entry_10(void);
     SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
 
+    allocate_extra_stack();
+
     SET_VGA(HaveRunInit, 1);
 
     // Fixup checksum
index a65136d00882ea989d154cb52e76495f7d6e7845..1d2fe9271abcfdb6425ef5d3a3176d7e40ff5652 100644 (file)
@@ -5,6 +5,7 @@
 // This file may be distributed under the terms of the GNU LGPLv3 license.
 
 
+#include "asm-offsets.h" // BREGS_*
 #include "config.h" // CONFIG_*
 #include "entryfuncs.S" // ENTRY_*
 
@@ -75,3 +76,55 @@ _optionrom_entry:
 entry_10:
         ENTRY_ARG_VGA handle_10
         iretw
+
+        // Entry point using extra stack
+        DECLFUNC entry_10_extrastack
+entry_10_extrastack:
+        cli
+        cld
+        pushw %ds               // Set %ds:%eax to space on ExtraStack
+        pushl %eax
+        movzwl %cs:ExtraStackSeg, %eax
+        movl %eax, %ds
+        movl $(CONFIG_VGA_EXTRA_STACK_SIZE-BREGS_size-8), %eax
+        popl BREGS_eax(%eax)    // Backup registers
+        popw BREGS_ds(%eax)
+        movl %edi, BREGS_edi(%eax)
+        movl %esi, BREGS_esi(%eax)
+        movl %ebp, BREGS_ebp(%eax)
+        movl %ebx, BREGS_ebx(%eax)
+        movl %edx, BREGS_edx(%eax)
+        movl %ecx, BREGS_ecx(%eax)
+        movw %es, BREGS_es(%eax)
+        movl %esp, BREGS_size+0(%eax)
+        movzwl %sp, %esp
+        movw %ss, BREGS_size+4(%eax)
+        movl (%esp), %edx
+        movl %edx, BREGS_code(%eax)
+        movw 4(%esp), %dx
+        movw %dx, BREGS_flags(%eax)
+
+        movw %ds, %dx           // Setup %ss/%esp and call function
+        movw %dx, %ss
+        movl %eax, %esp
+        pushw %ax ; callw handle_10
+
+        movl %esp, %eax         // Restore registers and return
+        movw BREGS_size+4(%eax), %ss
+        movl BREGS_size+0(%eax), %esp
+        popl %edx
+        popw %dx
+        pushw BREGS_flags(%eax)
+        pushl BREGS_code(%eax)
+        movl BREGS_edi(%eax), %edi
+        movl BREGS_esi(%eax), %esi
+        movl BREGS_ebp(%eax), %ebp
+        movl BREGS_ebx(%eax), %ebx
+        movl BREGS_edx(%eax), %edx
+        movl BREGS_ecx(%eax), %ecx
+        movw BREGS_es(%eax), %es
+        pushw BREGS_ds(%eax)
+        pushl BREGS_eax(%eax)
+        popl %eax
+        popw %ds
+        iretw