linux/arch/x86/pci/pcbios.c
<<
>>
Prefs
   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
  32int 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 */
  45static 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
  63union 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
  82static 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
  91static 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
 123static struct {
 124        unsigned long address;
 125        unsigned short segment;
 126} pci_indirect __ro_after_init = {
 127        .address = 0,
 128        .segment = __KERNEL_CS,
 129};
 130
 131static int pci_bios_present __ro_after_init;
 132
 133static 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
 183static 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
 233static 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
 280static 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
 289static 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
 347struct irq_routing_options {
 348        u16 size;
 349        struct irq_info *table;
 350        u16 segment;
 351} __attribute__((packed));
 352
 353struct 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}
 403EXPORT_SYMBOL(pcibios_get_irq_routing_table);
 404
 405int 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}
 420EXPORT_SYMBOL(pcibios_set_irq_routing);
 421
 422void __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
 430