Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/i386/bios/smapi.c
39483 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2003 Matthew N. Dodd <[email protected]>
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/param.h>
30
#include <sys/systm.h>
31
#include <sys/kernel.h>
32
#include <sys/malloc.h>
33
34
#include <sys/module.h>
35
#include <sys/bus.h>
36
#include <sys/conf.h>
37
38
#include <machine/bus.h>
39
#include <machine/resource.h>
40
#include <sys/rman.h>
41
42
/* And all this for BIOS_PADDRTOVADDR() */
43
#include <vm/vm.h>
44
#include <vm/vm_param.h>
45
#include <vm/pmap.h>
46
#include <machine/md_var.h>
47
#include <machine/pc/bios.h>
48
49
#include <machine/smapi.h>
50
51
#define SMAPI_START 0xf0000
52
#define SMAPI_STEP 0x10
53
#define SMAPI_OFF 0
54
#define SMAPI_LEN 4
55
#define SMAPI_SIG "$SMB"
56
57
#define RES2HDR(res) ((struct smapi_bios_header *)rman_get_virtual(res))
58
#define ADDR2HDR(addr) ((struct smapi_bios_header *)BIOS_PADDRTOVADDR(addr))
59
60
struct smapi_softc {
61
struct cdev * cdev;
62
device_t dev;
63
struct resource * res;
64
int rid;
65
66
u_int32_t smapi32_entry;
67
68
struct smapi_bios_header *header;
69
};
70
71
extern u_long smapi32_offset;
72
extern u_short smapi32_segment;
73
74
static d_ioctl_t smapi_ioctl;
75
76
static struct cdevsw smapi_cdevsw = {
77
.d_version = D_VERSION,
78
.d_ioctl = smapi_ioctl,
79
.d_name = "smapi",
80
.d_flags = D_NEEDGIANT,
81
};
82
83
static void smapi_identify(driver_t *, device_t);
84
static int smapi_probe(device_t);
85
static int smapi_attach(device_t);
86
static int smapi_detach(device_t);
87
static int smapi_modevent(module_t, int, void *);
88
89
static int smapi_header_cksum(struct smapi_bios_header *);
90
91
extern int smapi32(struct smapi_bios_parameter *,
92
struct smapi_bios_parameter *);
93
extern int smapi32_new(u_long, u_short,
94
struct smapi_bios_parameter *,
95
struct smapi_bios_parameter *);
96
97
static int
98
smapi_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
99
{
100
struct smapi_softc *sc = dev->si_drv1;
101
int error;
102
103
switch (cmd) {
104
case SMAPIOGHEADER:
105
bcopy((caddr_t)sc->header, data,
106
sizeof(struct smapi_bios_header));
107
error = 0;
108
break;
109
case SMAPIOCGFUNCTION:
110
smapi32_offset = sc->smapi32_entry;
111
error = smapi32((struct smapi_bios_parameter *)data,
112
(struct smapi_bios_parameter *)data);
113
break;
114
default:
115
error = ENOTTY;
116
}
117
118
return (error);
119
}
120
121
static int
122
smapi_header_cksum (struct smapi_bios_header *header)
123
{
124
u_int8_t *ptr;
125
u_int8_t cksum;
126
int i;
127
128
ptr = (u_int8_t *)header;
129
cksum = 0;
130
for (i = 0; i < header->length; i++) {
131
cksum += ptr[i];
132
}
133
134
return (cksum);
135
}
136
137
static void
138
smapi_identify (driver_t *driver, device_t parent)
139
{
140
device_t child;
141
u_int32_t addr;
142
int length;
143
int rid;
144
145
if (!device_is_alive(parent))
146
return;
147
148
addr = bios_sigsearch(SMAPI_START, SMAPI_SIG, SMAPI_LEN,
149
SMAPI_STEP, SMAPI_OFF);
150
if (addr != 0) {
151
rid = 0;
152
length = ADDR2HDR(addr)->length;
153
154
child = BUS_ADD_CHILD(parent, 5, "smapi", DEVICE_UNIT_ANY);
155
device_set_driver(child, driver);
156
bus_set_resource(child, SYS_RES_MEMORY, rid, addr, length);
157
device_set_desc(child, "SMAPI BIOS");
158
}
159
160
return;
161
}
162
163
static int
164
smapi_probe (device_t dev)
165
{
166
struct resource *res;
167
int rid;
168
int error;
169
170
error = 0;
171
rid = 0;
172
res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
173
if (res == NULL) {
174
device_printf(dev, "Unable to allocate memory resource.\n");
175
error = ENOMEM;
176
goto bad;
177
}
178
179
if (smapi_header_cksum(RES2HDR(res))) {
180
device_printf(dev, "SMAPI header checksum failed.\n");
181
error = ENXIO;
182
goto bad;
183
}
184
185
bad:
186
if (res)
187
bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
188
return (error);
189
}
190
191
static int
192
smapi_attach (device_t dev)
193
{
194
struct make_dev_args args;
195
struct smapi_softc *sc;
196
int error;
197
198
sc = device_get_softc(dev);
199
error = 0;
200
201
sc->dev = dev;
202
sc->rid = 0;
203
sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->rid,
204
RF_ACTIVE);
205
if (sc->res == NULL) {
206
device_printf(dev, "Unable to allocate memory resource.\n");
207
error = ENOMEM;
208
goto bad;
209
}
210
sc->header = (struct smapi_bios_header *)rman_get_virtual(sc->res);
211
sc->smapi32_entry = (u_int32_t)BIOS_PADDRTOVADDR(
212
sc->header->prot32_segment +
213
sc->header->prot32_offset);
214
215
make_dev_args_init(&args);
216
args.mda_devsw = &smapi_cdevsw;
217
args.mda_uid = UID_ROOT;
218
args.mda_gid = GID_WHEEL;
219
args.mda_mode = 0600;
220
args.mda_si_drv1 = sc;
221
error = make_dev_s(&args, &sc->cdev, "%s%d",
222
smapi_cdevsw.d_name,
223
device_get_unit(sc->dev));
224
if (error != 0)
225
goto bad;
226
227
device_printf(dev, "Version: %d.%02d, Length: %d, Checksum: 0x%02x\n",
228
bcd2bin(sc->header->version_major),
229
bcd2bin(sc->header->version_minor),
230
sc->header->length,
231
sc->header->checksum);
232
device_printf(dev, "Information=0x%b\n",
233
sc->header->information,
234
"\020"
235
"\001REAL_VM86"
236
"\002PROTECTED_16"
237
"\003PROTECTED_32");
238
239
if (bootverbose) {
240
if (sc->header->information & SMAPI_REAL_VM86)
241
device_printf(dev, "Real/VM86 mode: Segment 0x%04x, Offset 0x%04x\n",
242
sc->header->real16_segment,
243
sc->header->real16_offset);
244
if (sc->header->information & SMAPI_PROT_16BIT)
245
device_printf(dev, "16-bit Protected mode: Segment 0x%08x, Offset 0x%04x\n",
246
sc->header->prot16_segment,
247
sc->header->prot16_offset);
248
if (sc->header->information & SMAPI_PROT_32BIT)
249
device_printf(dev, "32-bit Protected mode: Segment 0x%08x, Offset 0x%08x\n",
250
sc->header->prot32_segment,
251
sc->header->prot32_offset);
252
}
253
254
return (0);
255
bad:
256
if (sc->res)
257
bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
258
return (error);
259
}
260
261
static int
262
smapi_detach (device_t dev)
263
{
264
struct smapi_softc *sc;
265
266
sc = device_get_softc(dev);
267
268
destroy_dev(sc->cdev);
269
270
if (sc->res)
271
bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
272
273
return (0);
274
}
275
276
static device_method_t smapi_methods[] = {
277
/* Device interface */
278
DEVMETHOD(device_identify, smapi_identify),
279
DEVMETHOD(device_probe, smapi_probe),
280
DEVMETHOD(device_attach, smapi_attach),
281
DEVMETHOD(device_detach, smapi_detach),
282
{ 0, 0 }
283
};
284
285
static driver_t smapi_driver = {
286
"smapi",
287
smapi_methods,
288
sizeof(struct smapi_softc),
289
};
290
291
static int
292
smapi_modevent (module_t mod, int what, void *arg)
293
{
294
device_t * devs;
295
int count;
296
int i;
297
298
switch (what) {
299
case MOD_LOAD:
300
break;
301
case MOD_UNLOAD:
302
devclass_get_devices(devclass_find(smapi_driver.name), &devs,
303
&count);
304
for (i = 0; i < count; i++) {
305
device_delete_child(device_get_parent(devs[i]), devs[i]);
306
}
307
free(devs, M_TEMP);
308
break;
309
default:
310
break;
311
}
312
313
return (0);
314
}
315
316
DRIVER_MODULE(smapi, nexus, smapi_driver, smapi_modevent, NULL);
317
MODULE_VERSION(smapi, 1);
318
319