Initial PnP bios call support.
[seabios.git] / src / pnpbios.c
1 // PNP BIOS calls
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU GPLv3 license.
6
7 #include "util.h" // checksum
8 #include "config.h" // BUILD_BIOS_ADDR
9 #include "farptr.h" // SET_FARVAR
10
11 struct pnpheader {
12     u32 signature;
13     u8 version;
14     u8 length;
15     u16 control;
16     u8 checksum;
17     u32 eventloc;
18     u16 real_ip;
19     u16 real_cs;
20     u16 prot_ip;
21     u32 prot_base;
22     u32 oemid;
23     u16 real_ds;
24     u32 prot_database;
25 } PACKED;
26
27 extern struct pnpheader PNPHEADER;
28 extern const char pnp_string[];
29
30 #if MODE16
31 # if CONFIG_PNPBIOS
32 struct pnpheader PNPHEADER __aligned(16) VISIBLE16 = {
33     .signature = PNP_SIGNATURE,
34     .version = 0x10,
35     .length = sizeof(PNPHEADER),
36     .real_cs = SEG_BIOS,
37     .prot_base = BUILD_BIOS_ADDR,
38     .real_ds = SEG_BIOS,
39     .prot_database = BUILD_BIOS_ADDR,
40 };
41 # else
42 // We need a copy of this string in the 0xf000 segment, but we are not
43 // actually a PnP BIOS, so make sure it is *not* aligned, so OSes will
44 // not see it if they scan.
45 const char pnp_string[] __aligned(2) VISIBLE16 = " $PnP";
46 # endif
47 #endif
48
49 #define FUNCTION_NOT_SUPPORTED 0x82
50
51 // BBS - Get Version and Installation Check
52 static u16
53 handle_pnp60(u16 *args)
54 {
55     u16 version_ptr = args[1];
56     u16 version_seg = args[2];
57     SET_FARVAR(version_seg, *(u16*)(version_ptr+0), 0x0101);
58     return 0;
59 }
60
61 static u16
62 handle_pnpXX(u16 *args)
63 {
64     return FUNCTION_NOT_SUPPORTED;
65 }
66
67 u16 VISIBLE16
68 handle_pnp(u16 *args)
69 {
70     if (! CONFIG_PNPBIOS)
71         return FUNCTION_NOT_SUPPORTED;
72
73     u16 arg1 = args[0];
74     dprintf(DEBUG_HDL_pnp, "pnp call arg1=%x\n", arg1);
75
76     switch (arg1) {
77     case 0x60: return handle_pnp60(args);
78     default:   return handle_pnpXX(args);
79     }
80 }
81
82 u16
83 get_pnp_offset()
84 {
85     if (! CONFIG_PNPBIOS)
86         return (u32)pnp_string + 1 - BUILD_BIOS_ADDR;
87     return (u32)&PNPHEADER - BUILD_BIOS_ADDR;
88 }
89
90 // romlayout.S
91 extern void entry_pnp_real();
92 extern void entry_pnp_prot();
93
94 void
95 pnp_setup()
96 {
97     if (! CONFIG_PNPBIOS)
98         return;
99
100     dprintf(3, "init PNPBIOS table\n");
101
102     PNPHEADER.real_ip = (u32)entry_pnp_real - BUILD_BIOS_ADDR;
103     PNPHEADER.prot_ip = (u32)entry_pnp_prot - BUILD_BIOS_ADDR;
104     PNPHEADER.checksum = -checksum((u8*)&PNPHEADER, sizeof(PNPHEADER));
105 }