This commit provides just enough PnP support for gPXE to not hook int19.
# Source files
SRCBOTH=output.c util.c floppy.c ata.c system.c mouse.c kbd.c pci.c \
- serial.c clock.c pic.c cdrom.c ps2port.c smpdetect.c resume.c
+ serial.c clock.c pic.c cdrom.c ps2port.c smpdetect.c resume.c \
+ pnpbios.c
SRC16=$(SRCBOTH) disk.c apm.c pcibios.c vgahooks.c
SRC32=$(SRCBOTH) post.c shadow.c post_menu.c memmap.c coreboot.c boot.c \
acpi.c pirtable.c smm.c mptable.c smbios.c pciinit.c \
#define CONFIG_PCIBIOS 1
// Support int 15/53 APM BIOS calls
#define CONFIG_APMBIOS 1
+// Support PnP BIOS entry point.
+#define CONFIG_PNPBIOS 1
// Support int 19/18 system bootup support
#define CONFIG_BOOT 1
// Support int 14 serial port calls
#define DEBUG_ISR_76 10
#define DEBUG_ISR_hwpic1 1
#define DEBUG_ISR_hwpic2 1
+#define DEBUG_HDL_pnp 1
#endif // config.h
* Definitions
****************************************************************/
-// $PnP string with special alignment in romlayout.S
-extern char pnp_string[];
-
struct rom_header {
u16 signature;
u8 size;
br.bx = 0xffff;
br.dx = 0xffff;
br.es = SEG_BIOS;
- br.di = (u32)pnp_string - BUILD_BIOS_ADDR;
+ br.di = get_pnp_offset();
br.cs = seg;
br.ip = offset;
call16big(&br);
get_pnp_rom(struct rom_header *rom)
{
struct pnp_data *pnp = (struct pnp_data *)((u8*)rom + rom->pnpoffset);
- if (pnp->signature != *(u32*)pnp_string)
+ if (pnp->signature != PNP_SIGNATURE)
return NULL;
return pnp;
}
if (! pnp->nextoffset)
return NULL;
pnp = (struct pnp_data *)((u8*)rom + pnp->nextoffset);
- if (pnp->signature != *(u32*)pnp_string)
+ if (pnp->signature != PNP_SIGNATURE)
return NULL;
return pnp;
}
--- /dev/null
+// PNP BIOS calls
+//
+// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU GPLv3 license.
+
+#include "util.h" // checksum
+#include "config.h" // BUILD_BIOS_ADDR
+#include "farptr.h" // SET_FARVAR
+
+struct pnpheader {
+ u32 signature;
+ u8 version;
+ u8 length;
+ u16 control;
+ u8 checksum;
+ u32 eventloc;
+ u16 real_ip;
+ u16 real_cs;
+ u16 prot_ip;
+ u32 prot_base;
+ u32 oemid;
+ u16 real_ds;
+ u32 prot_database;
+} PACKED;
+
+extern struct pnpheader PNPHEADER;
+extern const char pnp_string[];
+
+#if MODE16
+# if CONFIG_PNPBIOS
+struct pnpheader PNPHEADER __aligned(16) VISIBLE16 = {
+ .signature = PNP_SIGNATURE,
+ .version = 0x10,
+ .length = sizeof(PNPHEADER),
+ .real_cs = SEG_BIOS,
+ .prot_base = BUILD_BIOS_ADDR,
+ .real_ds = SEG_BIOS,
+ .prot_database = BUILD_BIOS_ADDR,
+};
+# else
+// We need a copy of this string in the 0xf000 segment, but we are not
+// actually a PnP BIOS, so make sure it is *not* aligned, so OSes will
+// not see it if they scan.
+const char pnp_string[] __aligned(2) VISIBLE16 = " $PnP";
+# endif
+#endif
+
+#define FUNCTION_NOT_SUPPORTED 0x82
+
+// BBS - Get Version and Installation Check
+static u16
+handle_pnp60(u16 *args)
+{
+ u16 version_ptr = args[1];
+ u16 version_seg = args[2];
+ SET_FARVAR(version_seg, *(u16*)(version_ptr+0), 0x0101);
+ return 0;
+}
+
+static u16
+handle_pnpXX(u16 *args)
+{
+ return FUNCTION_NOT_SUPPORTED;
+}
+
+u16 VISIBLE16
+handle_pnp(u16 *args)
+{
+ if (! CONFIG_PNPBIOS)
+ return FUNCTION_NOT_SUPPORTED;
+
+ u16 arg1 = args[0];
+ dprintf(DEBUG_HDL_pnp, "pnp call arg1=%x\n", arg1);
+
+ switch (arg1) {
+ case 0x60: return handle_pnp60(args);
+ default: return handle_pnpXX(args);
+ }
+}
+
+u16
+get_pnp_offset()
+{
+ if (! CONFIG_PNPBIOS)
+ return (u32)pnp_string + 1 - BUILD_BIOS_ADDR;
+ return (u32)&PNPHEADER - BUILD_BIOS_ADDR;
+}
+
+// romlayout.S
+extern void entry_pnp_real();
+extern void entry_pnp_prot();
+
+void
+pnp_setup()
+{
+ if (! CONFIG_PNPBIOS)
+ return;
+
+ dprintf(3, "init PNPBIOS table\n");
+
+ PNPHEADER.real_ip = (u32)entry_pnp_real - BUILD_BIOS_ADDR;
+ PNPHEADER.prot_ip = (u32)entry_pnp_prot - BUILD_BIOS_ADDR;
+ PNPHEADER.checksum = -checksum((u8*)&PNPHEADER, sizeof(PNPHEADER));
+}
memmap_setup();
ram_probe();
+ pnp_setup();
vga_setup();
kbd_setup();
cli
jmp handle_resume
+// PnP trampolines
+ .global entry_pnp_real, entry_pnp_prot
+entry_pnp_prot:
+ pushl %esp
+ jmp 1f
+entry_pnp_real:
+ pushl %esp // Backup %esp, then clear high bits
+ movzwl %sp, %esp
+1:
+ pushfl // Save registers clobbered by C code
+ pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushw %es
+ pushw %ds
+ movw %ss, %cx // Move %ss to %ds
+ movw %cx, %ds
+ lea 28(%esp), %eax // %eax points to start of u16 args
+ calll handle_pnp
+ movw %ax, 12(%esp) // Modify %eax to return %ax
+ popw %ds
+ popw %es
+ popl %edx
+ popl %ecx
+ popl %eax
+ popfl
+ popl %esp
+ lretw
+
// APM trampolines
.global apm16protected_entry
apm16protected_entry:
.word 0xffff, 0, 0x9300, 0x008f
rombios32_gdt_end:
-// We need a copy of this string in the 0xf000 segment, but we are not
-// actually a PnP BIOS, so make sure it is *not* aligned, so OSes will
-// not see it if they scan.
- .global pnp_string
- .type pnp_string, @object
- .balign 2
- .byte 0
-pnp_string:
- .ascii "$PnP"
-
/****************************************************************
* Interrupt entry points (continued)
// resume.c
void init_dma();
+// pnpbios.c
+#define PNP_SIGNATURE 0x506e5024 // $PnP
+u16 get_pnp_offset();
+void pnp_setup();
+
// romlayout.S
void reset_vector() __attribute__ ((noreturn));