Initial PnP bios call support.
authorKevin O'Connor <kevin@koconnor.net>
Sun, 21 Dec 2008 22:51:36 +0000 (17:51 -0500)
committerKevin O'Connor <kevin@koconnor.net>
Sun, 21 Dec 2008 22:51:36 +0000 (17:51 -0500)
This commit provides just enough PnP support for gPXE to not hook int19.

Makefile
src/config.h
src/optionroms.c
src/pnpbios.c [new file with mode: 0644]
src/post.c
src/romlayout.S
src/util.h

index f6a85b5f2290e27d84ec6e0e953484730aa2d82e..8faa1f44a7e713470d27f9721e7ee16e8353d364 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,8 @@ OUT=out/
 
 # 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 \
index 35c7e3ecb43b2334f00c508029a4f39dba06bf75..1a1499ab4966a6d0e980da598f890100ff5e7543 100644 (file)
@@ -37,6 +37,8 @@
 #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
index 389d528bd970025a02557f402bbf70a9f6a98f82..893816347539ae838c3d8b62d51295968868f5fe 100644 (file)
@@ -17,9 +17,6 @@
  * Definitions
  ****************************************************************/
 
-// $PnP string with special alignment in romlayout.S
-extern char pnp_string[];
-
 struct rom_header {
     u16 signature;
     u8 size;
@@ -93,7 +90,7 @@ callrom(struct rom_header *rom, u16 offset, u16 bdf)
     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);
@@ -126,7 +123,7 @@ static struct pnp_data *
 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;
 }
@@ -138,7 +135,7 @@ get_pnp_next(struct rom_header *rom, struct pnp_data *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;
 }
diff --git a/src/pnpbios.c b/src/pnpbios.c
new file mode 100644 (file)
index 0000000..6f36a4a
--- /dev/null
@@ -0,0 +1,105 @@
+// 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));
+}
index b286826e81d62fb05eec812a24728bf8f461456c..f55d53d095e4e9b2267bfe49b2a367f976b0482f 100644 (file)
@@ -198,6 +198,7 @@ post()
     memmap_setup();
     ram_probe();
 
+    pnp_setup();
     vga_setup();
 
     kbd_setup();
index 52449b5aeaa0c3c4545b351d2f4f71ab8ddcf1a4..0d8e58a4589cda309ae27319df5a67088f899ee2 100644 (file)
@@ -329,6 +329,35 @@ entry_resume:
         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:
@@ -478,16 +507,6 @@ rombios32_gdt:
         .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)
index 0966c4c71fffa79614d7cb479adbd7460b3cf3b0..ee885f7cff919b68ed90f93e3091d6e623c933a4 100644 (file)
@@ -177,6 +177,11 @@ void optionrom_setup();
 // 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));