This patch implements a way for option ROMs to allocate some space using the bios PMM interface.
Since the VGA option ROM is placed in read only memory, the only way to get memory to store global variables is either use the EBDA, or use the PMM if the BIOS supports it.
This simple patchs adds only pmm_scan and pmm_allocate. The first one is used to scan the memory and find the PMM entry point, the second one is used to request the BIOS to allocate blocks of memory.
The pmm_find and pmm_deallocate functions are yet to be implemented.
Signed-off-by: Julian Pidancet julian.pidancet@gmail.com --- Makefile | 2 +- vgasrc/pmm.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ vgasrc/pmm.h | 16 ++++++++++++++++ 3 files changed, 67 insertions(+), 1 deletions(-) create mode 100644 vgasrc/pmm.c create mode 100644 vgasrc/pmm.h
diff --git a/Makefile b/Makefile index cb00958..1b8ba60 100644 --- a/Makefile +++ b/Makefile @@ -171,7 +171,7 @@ $(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py
# VGA src files SRCVGA=src/output.c src/util.c vgasrc/vga.c vgasrc/vgafb.c vgasrc/vgaio.c \ - vgasrc/vgatables.c vgasrc/vgafonts.c vgasrc/clext.c + vgasrc/vgatables.c vgasrc/vgafonts.c vgasrc/clext.c vgasrc/pmm.c
$(OUT)vgaccode.16.s: $(OUT)autoconf.h ; $(call whole-compile, $(CFLAGS16) -S -Isrc, $(SRCVGA),$@)
diff --git a/vgasrc/pmm.c b/vgasrc/pmm.c new file mode 100644 index 0000000..1732149 --- /dev/null +++ b/vgasrc/pmm.c @@ -0,0 +1,50 @@ +#include "biosvar.h" // GET_GLOBAL +#include "util.h" // memset + +#define PMM_SIGNATURE 0x4d4d5024 // $PMM + +struct pmmheader { + u32 signature; + u8 version; + u8 length; + u8 checksum; + u16 entry_offset; + u16 entry_seg; + u8 reserved[5]; +} PACKED; + +u32 pmm_allocate(u16 seg, u32 length, u32 handle, u16 flags) +{ + u16 ax, dx; + + asm volatile ("movw %2, %%es\n" + "pushw %3\n" + "pushl %4\n" + "pushl %5\n" + "pushw $0x0\n" /* PMM_ALLOCATE */ + "lcallw *%%es:7\n" + "addw $12, %%sp\n" + : "=a"(ax), "=d"(dx) + : "r"(seg), "r"(flags), "r"(handle), "r"(length) + : "cc", "memory"); + + return (dx << 16) | ax; +} + +u16 pmm_scan(void) +{ + u16 seg; + struct pmmheader *hdr = (struct pmmheader *)0; + + for (seg = 0xe000; seg; seg++) { + u32 val = GET_FARVAR(seg, hdr->signature); + + if (val == PMM_SIGNATURE && + !checksum_far(seg, hdr, GET_FARVAR(seg, hdr->length))) { + return seg; + } + } + + return 0; +} + diff --git a/vgasrc/pmm.h b/vgasrc/pmm.h new file mode 100644 index 0000000..f6479ad --- /dev/null +++ b/vgasrc/pmm.h @@ -0,0 +1,16 @@ +#include "biosvar.h" // GET_GLOBAL +#include "util.h" // memset + +#define PMM_MEMORY_TYPE_INVALID (0 << 0) +#define PMM_MEMORY_TYPE_CONVENTION (1 << 0) +#define PMM_MEMORY_TYPE_EXTENDED (2 << 0) + +#define PMM_BLOCK_NOT_ALIGNED (0 << 2) +#define PMM_BLOCK_ALIGNED (1 << 2) + +/* Only in PCI FW spec: */ +#define PMM_MEMORY_ATTR_TEMPORARY (0 << 3) +#define PMM_MEMORY_ATTR_PERMANENT (1 << 3) + +u32 pmm_allocate(u16 seg, u32 length, u32 handle, u16 flags); +u16 pmm_scan(void);