root/arch/x86/pci/pcbios.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_bios_x
  2. bios32_service
  3. check_pcibios
  4. pci_bios_read
  5. pci_bios_write
  6. pci_find_bios
  7. pcibios_get_irq_routing_table
  8. pcibios_set_irq_routing
  9. pci_pcbios_init

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

/* [<][>][^][v][top][bottom][index][help] */