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, numpages: (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(eax: 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(eax: 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(eax: 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(size: 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(eax: 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 | |