Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/pci/pcbios.c
26442 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* BIOS32 and PCI BIOS handling.
4
*/
5
6
#include <linux/bits.h>
7
#include <linux/bitfield.h>
8
#include <linux/pci.h>
9
#include <linux/init.h>
10
#include <linux/slab.h>
11
#include <linux/module.h>
12
#include <linux/uaccess.h>
13
14
#include <asm/pci_x86.h>
15
#include <asm/e820/types.h>
16
#include <asm/pci-functions.h>
17
#include <asm/set_memory.h>
18
19
/* BIOS32 signature: "_32_" */
20
#define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
21
22
/* PCI signature: "PCI " */
23
#define PCI_SIGNATURE (('P' << 0) + ('C' << 8) + ('I' << 16) + (' ' << 24))
24
25
/* PCI service signature: "$PCI" */
26
#define PCI_SERVICE (('$' << 0) + ('P' << 8) + ('C' << 16) + ('I' << 24))
27
28
/* PCI BIOS hardware mechanism flags */
29
#define PCIBIOS_HW_TYPE1 0x01
30
#define PCIBIOS_HW_TYPE2 0x02
31
#define PCIBIOS_HW_TYPE1_SPEC 0x10
32
#define PCIBIOS_HW_TYPE2_SPEC 0x20
33
34
/*
35
* Returned in EAX:
36
* - AH: return code
37
*/
38
#define PCIBIOS_RETURN_CODE GENMASK(15, 8)
39
40
int pcibios_enabled;
41
42
static u8 pcibios_get_return_code(u32 eax)
43
{
44
return FIELD_GET(PCIBIOS_RETURN_CODE, eax);
45
}
46
47
/* According to the BIOS specification at:
48
* http://members.datafast.net.au/dft0802/specs/bios21.pdf, we could
49
* restrict the x zone to some pages and make it ro. But this may be
50
* broken on some bios, complex to handle with static_protections.
51
* We could make the 0xe0000-0x100000 range rox, but this can break
52
* some ISA mapping.
53
*
54
* So we let's an rw and x hole when pcibios is used. This shouldn't
55
* happen for modern system with mmconfig, and if you don't want it
56
* you could disable pcibios...
57
*/
58
static inline void set_bios_x(void)
59
{
60
pcibios_enabled = 1;
61
set_memory_x(PAGE_OFFSET + BIOS_BEGIN, (BIOS_END - BIOS_BEGIN) >> PAGE_SHIFT);
62
if (__supported_pte_mask & _PAGE_NX)
63
printk(KERN_INFO "PCI: PCI BIOS area is rw and x. Use pci=nobios if you want it NX.\n");
64
}
65
66
/*
67
* This is the standard structure used to identify the entry point
68
* to the BIOS32 Service Directory, as documented in
69
* Standard BIOS 32-bit Service Directory Proposal
70
* Revision 0.4 May 24, 1993
71
* Phoenix Technologies Ltd.
72
* Norwood, MA
73
* and the PCI BIOS specification.
74
*/
75
76
union bios32 {
77
struct {
78
unsigned long signature; /* _32_ */
79
unsigned long entry; /* 32 bit physical address */
80
unsigned char revision; /* Revision level, 0 */
81
unsigned char length; /* Length in paragraphs should be 01 */
82
unsigned char checksum; /* All bytes must add up to zero */
83
unsigned char reserved[5]; /* Must be zero */
84
} fields;
85
char chars[16];
86
};
87
88
/*
89
* Physical address of the service directory. I don't know if we're
90
* allowed to have more than one of these or not, so just in case
91
* we'll make pcibios_present() take a memory start parameter and store
92
* the array there.
93
*/
94
95
static struct {
96
unsigned long address;
97
unsigned short segment;
98
} bios32_indirect __initdata = { 0, __KERNEL_CS };
99
100
/*
101
* Returns the entry point for the given service, NULL on error
102
*/
103
104
static unsigned long __init bios32_service(unsigned long service)
105
{
106
unsigned char return_code; /* %al */
107
unsigned long address; /* %ebx */
108
unsigned long length; /* %ecx */
109
unsigned long entry; /* %edx */
110
unsigned long flags;
111
112
local_irq_save(flags);
113
__asm__("lcall *(%%edi); cld"
114
: "=a" (return_code),
115
"=b" (address),
116
"=c" (length),
117
"=d" (entry)
118
: "0" (service),
119
"1" (0),
120
"D" (&bios32_indirect));
121
local_irq_restore(flags);
122
123
switch (return_code) {
124
case 0:
125
return address + entry;
126
case 0x80: /* Not present */
127
printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service);
128
return 0;
129
default: /* Shouldn't happen */
130
printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n",
131
service, return_code);
132
return 0;
133
}
134
}
135
136
static struct {
137
unsigned long address;
138
unsigned short segment;
139
} pci_indirect __ro_after_init = {
140
.address = 0,
141
.segment = __KERNEL_CS,
142
};
143
144
static int pci_bios_present __ro_after_init;
145
146
static int __init check_pcibios(void)
147
{
148
u32 signature, eax, ebx, ecx;
149
u8 status, major_ver, minor_ver, hw_mech;
150
unsigned long flags, pcibios_entry;
151
152
if ((pcibios_entry = bios32_service(PCI_SERVICE))) {
153
pci_indirect.address = pcibios_entry + PAGE_OFFSET;
154
155
local_irq_save(flags);
156
__asm__(
157
"lcall *(%%edi); cld\n\t"
158
"jc 1f\n\t"
159
"xor %%ah, %%ah\n"
160
"1:"
161
: "=d" (signature),
162
"=a" (eax),
163
"=b" (ebx),
164
"=c" (ecx)
165
: "1" (PCIBIOS_PCI_BIOS_PRESENT),
166
"D" (&pci_indirect)
167
: "memory");
168
local_irq_restore(flags);
169
170
status = pcibios_get_return_code(eax);
171
hw_mech = eax & 0xff;
172
major_ver = (ebx >> 8) & 0xff;
173
minor_ver = ebx & 0xff;
174
if (pcibios_last_bus < 0)
175
pcibios_last_bus = ecx & 0xff;
176
DBG("PCI: BIOS probe returned s=%02x hw=%02x ver=%02x.%02x l=%02x\n",
177
status, hw_mech, major_ver, minor_ver, pcibios_last_bus);
178
if (status || signature != PCI_SIGNATURE) {
179
printk (KERN_ERR "PCI: BIOS BUG #%x[%08x] found\n",
180
status, signature);
181
return 0;
182
}
183
printk(KERN_INFO "PCI: PCI BIOS revision %x.%02x entry at 0x%lx, last bus=%d\n",
184
major_ver, minor_ver, pcibios_entry, pcibios_last_bus);
185
#ifdef CONFIG_PCI_DIRECT
186
if (!(hw_mech & PCIBIOS_HW_TYPE1))
187
pci_probe &= ~PCI_PROBE_CONF1;
188
if (!(hw_mech & PCIBIOS_HW_TYPE2))
189
pci_probe &= ~PCI_PROBE_CONF2;
190
#endif
191
return 1;
192
}
193
return 0;
194
}
195
196
static int pci_bios_read(unsigned int seg, unsigned int bus,
197
unsigned int devfn, int reg, int len, u32 *value)
198
{
199
unsigned long result = 0;
200
unsigned long flags;
201
unsigned long bx = (bus << 8) | devfn;
202
u16 number = 0, mask = 0;
203
204
WARN_ON(seg);
205
if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
206
return -EINVAL;
207
208
raw_spin_lock_irqsave(&pci_config_lock, flags);
209
210
switch (len) {
211
case 1:
212
number = PCIBIOS_READ_CONFIG_BYTE;
213
mask = 0xff;
214
break;
215
case 2:
216
number = PCIBIOS_READ_CONFIG_WORD;
217
mask = 0xffff;
218
break;
219
case 4:
220
number = PCIBIOS_READ_CONFIG_DWORD;
221
break;
222
}
223
224
__asm__("lcall *(%%esi); cld\n\t"
225
"jc 1f\n\t"
226
"xor %%ah, %%ah\n"
227
"1:"
228
: "=c" (*value),
229
"=a" (result)
230
: "1" (number),
231
"b" (bx),
232
"D" ((long)reg),
233
"S" (&pci_indirect));
234
/*
235
* Zero-extend the result beyond 8 or 16 bits, do not trust the
236
* BIOS having done it:
237
*/
238
if (mask)
239
*value &= mask;
240
241
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
242
243
return pcibios_get_return_code(result);
244
}
245
246
static int pci_bios_write(unsigned int seg, unsigned int bus,
247
unsigned int devfn, int reg, int len, u32 value)
248
{
249
unsigned long result = 0;
250
unsigned long flags;
251
unsigned long bx = (bus << 8) | devfn;
252
u16 number = 0;
253
254
WARN_ON(seg);
255
if ((bus > 255) || (devfn > 255) || (reg > 255))
256
return -EINVAL;
257
258
raw_spin_lock_irqsave(&pci_config_lock, flags);
259
260
switch (len) {
261
case 1:
262
number = PCIBIOS_WRITE_CONFIG_BYTE;
263
break;
264
case 2:
265
number = PCIBIOS_WRITE_CONFIG_WORD;
266
break;
267
case 4:
268
number = PCIBIOS_WRITE_CONFIG_DWORD;
269
break;
270
}
271
272
__asm__("lcall *(%%esi); cld\n\t"
273
"jc 1f\n\t"
274
"xor %%ah, %%ah\n"
275
"1:"
276
: "=a" (result)
277
: "0" (number),
278
"c" (value),
279
"b" (bx),
280
"D" ((long)reg),
281
"S" (&pci_indirect));
282
283
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
284
285
return pcibios_get_return_code(result);
286
}
287
288
289
/*
290
* Function table for BIOS32 access
291
*/
292
293
static const struct pci_raw_ops pci_bios_access = {
294
.read = pci_bios_read,
295
.write = pci_bios_write
296
};
297
298
/*
299
* Try to find PCI BIOS.
300
*/
301
302
static const struct pci_raw_ops *__init pci_find_bios(void)
303
{
304
union bios32 *check;
305
unsigned char sum;
306
int i, length;
307
308
/*
309
* Follow the standard procedure for locating the BIOS32 Service
310
* directory by scanning the permissible address range from
311
* 0xe0000 through 0xfffff for a valid BIOS32 structure.
312
*/
313
314
for (check = (union bios32 *) __va(0xe0000);
315
check <= (union bios32 *) __va(0xffff0);
316
++check) {
317
long sig;
318
if (get_kernel_nofault(sig, &check->fields.signature))
319
continue;
320
321
if (check->fields.signature != BIOS32_SIGNATURE)
322
continue;
323
length = check->fields.length * 16;
324
if (!length)
325
continue;
326
sum = 0;
327
for (i = 0; i < length ; ++i)
328
sum += check->chars[i];
329
if (sum != 0)
330
continue;
331
if (check->fields.revision != 0) {
332
printk("PCI: unsupported BIOS32 revision %d at 0x%p\n",
333
check->fields.revision, check);
334
continue;
335
}
336
DBG("PCI: BIOS32 Service Directory structure at 0x%p\n", check);
337
if (check->fields.entry >= 0x100000) {
338
printk("PCI: BIOS32 entry (0x%p) in high memory, "
339
"cannot use.\n", check);
340
return NULL;
341
} else {
342
unsigned long bios32_entry = check->fields.entry;
343
DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n",
344
bios32_entry);
345
bios32_indirect.address = bios32_entry + PAGE_OFFSET;
346
set_bios_x();
347
if (check_pcibios())
348
return &pci_bios_access;
349
}
350
break; /* Hopefully more than one BIOS32 cannot happen... */
351
}
352
353
return NULL;
354
}
355
356
/*
357
* BIOS Functions for IRQ Routing
358
*/
359
360
struct irq_routing_options {
361
u16 size;
362
struct irq_info *table;
363
u16 segment;
364
} __attribute__((packed));
365
366
struct irq_routing_table * pcibios_get_irq_routing_table(void)
367
{
368
struct irq_routing_options opt;
369
struct irq_routing_table *rt = NULL;
370
int ret, map;
371
unsigned long page;
372
373
if (!pci_bios_present)
374
return NULL;
375
page = __get_free_page(GFP_KERNEL);
376
if (!page)
377
return NULL;
378
opt.table = (struct irq_info *) page;
379
opt.size = PAGE_SIZE;
380
opt.segment = __KERNEL_DS;
381
382
DBG("PCI: Fetching IRQ routing table... ");
383
__asm__("push %%es\n\t"
384
"push %%ds\n\t"
385
"pop %%es\n\t"
386
"lcall *(%%esi); cld\n\t"
387
"pop %%es\n\t"
388
"jc 1f\n\t"
389
"xor %%ah, %%ah\n"
390
"1:"
391
: "=a" (ret),
392
"=b" (map),
393
"=m" (opt)
394
: "0" (PCIBIOS_GET_ROUTING_OPTIONS),
395
"1" (0),
396
"D" ((long) &opt),
397
"S" (&pci_indirect),
398
"m" (opt)
399
: "memory");
400
DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map);
401
ret = pcibios_get_return_code(ret);
402
if (ret) {
403
printk(KERN_ERR "PCI: Error %02x when fetching IRQ routing table.\n", ret);
404
} else if (opt.size) {
405
rt = kmalloc(sizeof(struct irq_routing_table) + opt.size, GFP_KERNEL);
406
if (rt) {
407
memset(rt, 0, sizeof(struct irq_routing_table));
408
rt->size = opt.size + sizeof(struct irq_routing_table);
409
rt->exclusive_irqs = map;
410
memcpy(rt->slots, (void *) page, opt.size);
411
printk(KERN_INFO "PCI: Using BIOS Interrupt Routing Table\n");
412
}
413
}
414
free_page(page);
415
return rt;
416
}
417
EXPORT_SYMBOL(pcibios_get_irq_routing_table);
418
419
int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
420
{
421
int ret;
422
423
__asm__("lcall *(%%esi); cld\n\t"
424
"jc 1f\n\t"
425
"xor %%ah, %%ah\n"
426
"1:"
427
: "=a" (ret)
428
: "0" (PCIBIOS_SET_PCI_HW_INT),
429
"b" ((dev->bus->number << 8) | dev->devfn),
430
"c" ((irq << 8) | (pin + 10)),
431
"S" (&pci_indirect));
432
return pcibios_get_return_code(ret) == PCIBIOS_SUCCESSFUL;
433
}
434
EXPORT_SYMBOL(pcibios_set_irq_routing);
435
436
void __init pci_pcbios_init(void)
437
{
438
if ((pci_probe & PCI_PROBE_BIOS)
439
&& ((raw_pci_ops = pci_find_bios()))) {
440
pci_bios_present = 1;
441
}
442
}
443
444
445