$(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 $@
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)"
#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
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;
extern void entry_10(void);
SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
+ allocate_extra_stack();
+
SET_VGA(HaveRunInit, 1);
// Fixup checksum
// 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_*
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