blob: e67425f38034682dd9658bf5048773ee6ae8afd6 [file] [log] [blame]
Kevin O'Connor0c3068d2008-12-21 17:51:36 -05001// PNP BIOS calls
2//
3// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
4//
Kevin O'Connorb1b7c2a2009-01-15 20:52:58 -05005// This file may be distributed under the terms of the GNU LGPLv3 license.
Kevin O'Connor0c3068d2008-12-21 17:51:36 -05006
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -04007#include "util.h" // dprintf
Kevin O'Connor0c3068d2008-12-21 17:51:36 -05008#include "config.h" // BUILD_BIOS_ADDR
9#include "farptr.h" // SET_FARVAR
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -040010#include "string.h" // checksum
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050011
12struct pnpheader {
13 u32 signature;
14 u8 version;
15 u8 length;
16 u16 control;
17 u8 checksum;
18 u32 eventloc;
19 u16 real_ip;
20 u16 real_cs;
21 u16 prot_ip;
22 u32 prot_base;
23 u32 oemid;
24 u16 real_ds;
25 u32 prot_database;
26} PACKED;
27
28extern struct pnpheader PNPHEADER;
Kevin O'Connor9e91c7b2009-01-17 02:30:21 -050029extern char pnp_string[];
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050030
Kevin O'Connor4a754b32008-12-28 21:37:27 -050031#if CONFIG_PNPBIOS
Kevin O'Connor89a2f962013-02-18 23:36:03 -050032struct pnpheader PNPHEADER __aligned(16) VARFSEG = {
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050033 .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};
Kevin O'Connor4a754b32008-12-28 21:37:27 -050041#else
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050042// 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.
Kevin O'Connor89a2f962013-02-18 23:36:03 -050045char pnp_string[] __aligned(2) VARFSEG = " $PnP";
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050046#endif
47
48#define FUNCTION_NOT_SUPPORTED 0x82
49
50// BBS - Get Version and Installation Check
51static u16
52handle_pnp60(u16 *args)
53{
54 u16 version_ptr = args[1];
55 u16 version_seg = args[2];
56 SET_FARVAR(version_seg, *(u16*)(version_ptr+0), 0x0101);
57 return 0;
58}
59
60static u16
61handle_pnpXX(u16 *args)
62{
63 return FUNCTION_NOT_SUPPORTED;
64}
65
66u16 VISIBLE16
67handle_pnp(u16 *args)
68{
69 if (! CONFIG_PNPBIOS)
70 return FUNCTION_NOT_SUPPORTED;
71
72 u16 arg1 = args[0];
73 dprintf(DEBUG_HDL_pnp, "pnp call arg1=%x\n", arg1);
74
75 switch (arg1) {
76 case 0x60: return handle_pnp60(args);
77 default: return handle_pnpXX(args);
78 }
79}
80
81u16
Kevin O'Connor1ca05b02010-01-03 17:43:37 -050082get_pnp_offset(void)
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050083{
84 if (! CONFIG_PNPBIOS)
85 return (u32)pnp_string + 1 - BUILD_BIOS_ADDR;
86 return (u32)&PNPHEADER - BUILD_BIOS_ADDR;
87}
88
89// romlayout.S
Kevin O'Connor1ca05b02010-01-03 17:43:37 -050090extern void entry_pnp_real(void);
91extern void entry_pnp_prot(void);
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050092
93void
Kevin O'Connord83c87b2013-01-21 01:14:12 -050094pnp_init(void)
Kevin O'Connor0c3068d2008-12-21 17:51:36 -050095{
96 if (! CONFIG_PNPBIOS)
97 return;
98
99 dprintf(3, "init PNPBIOS table\n");
100
101 PNPHEADER.real_ip = (u32)entry_pnp_real - BUILD_BIOS_ADDR;
102 PNPHEADER.prot_ip = (u32)entry_pnp_prot - BUILD_BIOS_ADDR;
Kevin O'Connor523e5a92009-07-04 13:46:33 -0400103 PNPHEADER.checksum -= checksum(&PNPHEADER, sizeof(PNPHEADER));
Kevin O'Connor0c3068d2008-12-21 17:51:36 -0500104}