grml...
[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 LGPLv3 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 char pnp_string[];
29
30 #if CONFIG_PNPBIOS
31 struct pnpheader PNPHEADER __aligned(16) VAR16EXPORT = {
32     .signature = PNP_SIGNATURE,
33     .version = 0x10,
34     .length = sizeof(PNPHEADER),
35     .real_cs = SEG_BIOS,
36     .prot_base = BUILD_BIOS_ADDR,
37     .real_ds = SEG_BIOS,
38     .prot_database = BUILD_BIOS_ADDR,
39 };
40 #else
41 // We need a copy of this string in the 0xf000 segment, but we are not
42 // actually a PnP BIOS, so make sure it is *not* aligned, so OSes will
43 // not see it if they scan.
44 char pnp_string[] __aligned(2) VAR16VISIBLE = " $PnP";
45 #endif
46
47 #define FUNCTION_NOT_SUPPORTED 0x82
48
49 // BBS - Get Version and Installation Check
50 static u16
51 handle_pnp60(u16 *args)
52 {
53     u16 version_ptr = args[1];
54     u16 version_seg = args[2];
55     SET_FARVAR(version_seg, *(u16*)(version_ptr+0), 0x0101);
56     return 0;
57 }
58
59 static u16
60 handle_pnpXX(u16 *args)
61 {
62     return FUNCTION_NOT_SUPPORTED;
63 }
64
65 u16 VISIBLE16
66 handle_pnp(u16 *args)
67 {
68     if (! CONFIG_PNPBIOS)
69         return FUNCTION_NOT_SUPPORTED;
70
71     u16 arg1 = args[0];
72     dprintf(DEBUG_HDL_pnp, "pnp call arg1=%x\n", arg1);
73
74     switch (arg1) {
75     case 0x60: return handle_pnp60(args);
76     default:   return handle_pnpXX(args);
77     }
78 }
79
80 u16
81 get_pnp_offset(void)
82 {
83     if (! CONFIG_PNPBIOS)
84         return (u32)pnp_string + 1 - BUILD_BIOS_ADDR;
85     return (u32)&PNPHEADER - BUILD_BIOS_ADDR;
86 }
87
88 // romlayout.S
89 extern void entry_pnp_real(void);
90 extern void entry_pnp_prot(void);
91
92 void
93 pnp_setup(void)
94 {
95     if (! CONFIG_PNPBIOS)
96         return;
97
98     dprintf(3, "init PNPBIOS table\n");
99
100     PNPHEADER.real_ip = (u32)entry_pnp_real - BUILD_BIOS_ADDR;
101     PNPHEADER.prot_ip = (u32)entry_pnp_prot - BUILD_BIOS_ADDR;
102     PNPHEADER.checksum -= checksum(&PNPHEADER, sizeof(PNPHEADER));
103 }