root/drivers/pnp/pnpbios/bioscalls.c

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

DEFINITIONS

This source file includes following definitions.
  1. call_pnp_bios
  2. pnpbios_print_status
  3. __pnp_bios_dev_node_info
  4. pnp_bios_dev_node_info
  5. __pnp_bios_get_dev_node
  6. pnp_bios_get_dev_node
  7. __pnp_bios_set_dev_node
  8. pnp_bios_set_dev_node
  9. pnp_bios_dock_station_info
  10. __pnp_bios_get_stat_res
  11. pnp_bios_get_stat_res
  12. __pnp_bios_isapnp_config
  13. pnp_bios_isapnp_config
  14. __pnp_bios_escd_info
  15. pnp_bios_escd_info
  16. __pnp_bios_read_escd
  17. pnp_bios_read_escd
  18. pnpbios_calls_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * bioscalls.c - the lowlevel layer of the PnPBIOS driver
   4  */
   5 
   6 #include <linux/types.h>
   7 #include <linux/module.h>
   8 #include <linux/init.h>
   9 #include <linux/linkage.h>
  10 #include <linux/kernel.h>
  11 #include <linux/device.h>
  12 #include <linux/pnp.h>
  13 #include <linux/mm.h>
  14 #include <linux/smp.h>
  15 #include <linux/kmod.h>
  16 #include <linux/completion.h>
  17 #include <linux/spinlock.h>
  18 
  19 #include <asm/page.h>
  20 #include <asm/desc.h>
  21 #include <asm/byteorder.h>
  22 
  23 #include "pnpbios.h"
  24 
  25 __visible struct {
  26         u16 offset;
  27         u16 segment;
  28 } pnp_bios_callpoint;
  29 
  30 /*
  31  * These are some opcodes for a "static asmlinkage"
  32  * As this code is *not* executed inside the linux kernel segment, but in a
  33  * alias at offset 0, we need a far return that can not be compiled by
  34  * default (please, prove me wrong! this is *really* ugly!)
  35  * This is the only way to get the bios to return into the kernel code,
  36  * because the bios code runs in 16 bit protected mode and therefore can only
  37  * return to the caller if the call is within the first 64kB, and the linux
  38  * kernel begins at offset 3GB...
  39  */
  40 
  41 asmlinkage __visible void pnp_bios_callfunc(void);
  42 
  43 __asm__(".text                  \n"
  44         __ALIGN_STR "\n"
  45         ".globl pnp_bios_callfunc\n"
  46         "pnp_bios_callfunc:\n"
  47         "       pushl %edx      \n"
  48         "       pushl %ecx      \n"
  49         "       pushl %ebx      \n"
  50         "       pushl %eax      \n"
  51         "       lcallw *pnp_bios_callpoint\n"
  52         "       addl $16, %esp  \n"
  53         "       lret            \n"
  54         ".previous              \n");
  55 
  56 #define Q2_SET_SEL(cpu, selname, address, size) \
  57 do { \
  58         struct desc_struct *gdt = get_cpu_gdt_rw((cpu)); \
  59         set_desc_base(&gdt[(selname) >> 3], (u32)(address)); \
  60         set_desc_limit(&gdt[(selname) >> 3], (size) - 1); \
  61 } while(0)
  62 
  63 static struct desc_struct bad_bios_desc = GDT_ENTRY_INIT(0x4092,
  64                         (unsigned long)__va(0x400UL), PAGE_SIZE - 0x400 - 1);
  65 
  66 /*
  67  * At some point we want to use this stack frame pointer to unwind
  68  * after PnP BIOS oopses.
  69  */
  70 
  71 __visible u32 pnp_bios_fault_esp;
  72 __visible u32 pnp_bios_fault_eip;
  73 __visible u32 pnp_bios_is_utter_crap = 0;
  74 
  75 static spinlock_t pnp_bios_lock;
  76 
  77 /*
  78  * Support Functions
  79  */
  80 
  81 static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
  82                                 u16 arg4, u16 arg5, u16 arg6, u16 arg7,
  83                                 void *ts1_base, u32 ts1_size,
  84                                 void *ts2_base, u32 ts2_size)
  85 {
  86         unsigned long flags;
  87         u16 status;
  88         struct desc_struct save_desc_40;
  89         int cpu;
  90 
  91         /*
  92          * PnP BIOSes are generally not terribly re-entrant.
  93          * Also, don't rely on them to save everything correctly.
  94          */
  95         if (pnp_bios_is_utter_crap)
  96                 return PNP_FUNCTION_NOT_SUPPORTED;
  97 
  98         cpu = get_cpu();
  99         save_desc_40 = get_cpu_gdt_rw(cpu)[0x40 / 8];
 100         get_cpu_gdt_rw(cpu)[0x40 / 8] = bad_bios_desc;
 101 
 102         /* On some boxes IRQ's during PnP BIOS calls are deadly.  */
 103         spin_lock_irqsave(&pnp_bios_lock, flags);
 104 
 105         /* The lock prevents us bouncing CPU here */
 106         if (ts1_size)
 107                 Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
 108         if (ts2_size)
 109                 Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
 110 
 111         __asm__ __volatile__("pushl %%ebp\n\t"
 112                              "pushl %%edi\n\t"
 113                              "pushl %%esi\n\t"
 114                              "pushl %%ds\n\t"
 115                              "pushl %%es\n\t"
 116                              "pushl %%fs\n\t"
 117                              "pushl %%gs\n\t"
 118                              "pushfl\n\t"
 119                              "movl %%esp, pnp_bios_fault_esp\n\t"
 120                              "movl $1f, pnp_bios_fault_eip\n\t"
 121                              "lcall %5,%6\n\t"
 122                              "1:popfl\n\t"
 123                              "popl %%gs\n\t"
 124                              "popl %%fs\n\t"
 125                              "popl %%es\n\t"
 126                              "popl %%ds\n\t"
 127                              "popl %%esi\n\t"
 128                              "popl %%edi\n\t"
 129                              "popl %%ebp\n\t":"=a"(status)
 130                              :"0"((func) | (((u32) arg1) << 16)),
 131                              "b"((arg2) | (((u32) arg3) << 16)),
 132                              "c"((arg4) | (((u32) arg5) << 16)),
 133                              "d"((arg6) | (((u32) arg7) << 16)),
 134                              "i"(PNP_CS32), "i"(0)
 135                              :"memory");
 136         spin_unlock_irqrestore(&pnp_bios_lock, flags);
 137 
 138         get_cpu_gdt_rw(cpu)[0x40 / 8] = save_desc_40;
 139         put_cpu();
 140 
 141         /* If we get here and this is set then the PnP BIOS faulted on us. */
 142         if (pnp_bios_is_utter_crap) {
 143                 printk(KERN_ERR
 144                        "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
 145                 printk(KERN_ERR
 146                        "PnPBIOS: You may need to reboot with the \"pnpbios=off\" option to operate stably\n");
 147                 printk(KERN_ERR
 148                        "PnPBIOS: Check with your vendor for an updated BIOS\n");
 149         }
 150 
 151         return status;
 152 }
 153 
 154 void pnpbios_print_status(const char *module, u16 status)
 155 {
 156         switch (status) {
 157         case PNP_SUCCESS:
 158                 printk(KERN_ERR "PnPBIOS: %s: function successful\n", module);
 159                 break;
 160         case PNP_NOT_SET_STATICALLY:
 161                 printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n",
 162                        module);
 163                 break;
 164         case PNP_UNKNOWN_FUNCTION:
 165                 printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n",
 166                        module);
 167                 break;
 168         case PNP_FUNCTION_NOT_SUPPORTED:
 169                 printk(KERN_ERR
 170                        "PnPBIOS: %s: function not supported on this system\n",
 171                        module);
 172                 break;
 173         case PNP_INVALID_HANDLE:
 174                 printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module);
 175                 break;
 176         case PNP_BAD_PARAMETER:
 177                 printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n",
 178                        module);
 179                 break;
 180         case PNP_SET_FAILED:
 181                 printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n",
 182                        module);
 183                 break;
 184         case PNP_EVENTS_NOT_PENDING:
 185                 printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module);
 186                 break;
 187         case PNP_SYSTEM_NOT_DOCKED:
 188                 printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n",
 189                        module);
 190                 break;
 191         case PNP_NO_ISA_PNP_CARDS:
 192                 printk(KERN_ERR
 193                        "PnPBIOS: %s: no isapnp cards are installed on this system\n",
 194                        module);
 195                 break;
 196         case PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES:
 197                 printk(KERN_ERR
 198                        "PnPBIOS: %s: cannot determine the capabilities of the docking station\n",
 199                        module);
 200                 break;
 201         case PNP_CONFIG_CHANGE_FAILED_NO_BATTERY:
 202                 printk(KERN_ERR
 203                        "PnPBIOS: %s: unable to undock, the system does not have a battery\n",
 204                        module);
 205                 break;
 206         case PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT:
 207                 printk(KERN_ERR
 208                        "PnPBIOS: %s: could not dock due to resource conflicts\n",
 209                        module);
 210                 break;
 211         case PNP_BUFFER_TOO_SMALL:
 212                 printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n",
 213                        module);
 214                 break;
 215         case PNP_USE_ESCD_SUPPORT:
 216                 printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module);
 217                 break;
 218         case PNP_MESSAGE_NOT_SUPPORTED:
 219                 printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n",
 220                        module);
 221                 break;
 222         case PNP_HARDWARE_ERROR:
 223                 printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occurred\n",
 224                        module);
 225                 break;
 226         default:
 227                 printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module,
 228                        status);
 229                 break;
 230         }
 231 }
 232 
 233 /*
 234  * PnP BIOS Low Level Calls
 235  */
 236 
 237 #define PNP_GET_NUM_SYS_DEV_NODES               0x00
 238 #define PNP_GET_SYS_DEV_NODE                    0x01
 239 #define PNP_SET_SYS_DEV_NODE                    0x02
 240 #define PNP_GET_EVENT                           0x03
 241 #define PNP_SEND_MESSAGE                        0x04
 242 #define PNP_GET_DOCKING_STATION_INFORMATION     0x05
 243 #define PNP_SET_STATIC_ALLOCED_RES_INFO         0x09
 244 #define PNP_GET_STATIC_ALLOCED_RES_INFO         0x0a
 245 #define PNP_GET_APM_ID_TABLE                    0x0b
 246 #define PNP_GET_PNP_ISA_CONFIG_STRUC            0x40
 247 #define PNP_GET_ESCD_INFO                       0x41
 248 #define PNP_READ_ESCD                           0x42
 249 #define PNP_WRITE_ESCD                          0x43
 250 
 251 /*
 252  * Call PnP BIOS with function 0x00, "get number of system device nodes"
 253  */
 254 static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
 255 {
 256         u16 status;
 257 
 258         if (!pnp_bios_present())
 259                 return PNP_FUNCTION_NOT_SUPPORTED;
 260         status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2,
 261                                PNP_TS1, PNP_DS, 0, 0, data,
 262                                sizeof(struct pnp_dev_node_info), NULL, 0);
 263         data->no_nodes &= 0xff;
 264         return status;
 265 }
 266 
 267 int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
 268 {
 269         int status = __pnp_bios_dev_node_info(data);
 270 
 271         if (status)
 272                 pnpbios_print_status("dev_node_info", status);
 273         return status;
 274 }
 275 
 276 /*
 277  * Note that some PnP BIOSes (e.g., on Sony Vaio laptops) die a horrible
 278  * death if they are asked to access the "current" configuration.
 279  * Therefore, if it's a matter of indifference, it's better to call
 280  * get_dev_node() and set_dev_node() with boot=1 rather than with boot=0.
 281  */
 282 
 283 /* 
 284  * Call PnP BIOS with function 0x01, "get system device node"
 285  * Input: *nodenum = desired node,
 286  *        boot = whether to get nonvolatile boot (!=0)
 287  *               or volatile current (0) config
 288  * Output: *nodenum=next node or 0xff if no more nodes
 289  */
 290 static int __pnp_bios_get_dev_node(u8 *nodenum, char boot,
 291                                    struct pnp_bios_node *data)
 292 {
 293         u16 status;
 294         u16 tmp_nodenum;
 295 
 296         if (!pnp_bios_present())
 297                 return PNP_FUNCTION_NOT_SUPPORTED;
 298         if (!boot && pnpbios_dont_use_current_config)
 299                 return PNP_FUNCTION_NOT_SUPPORTED;
 300         tmp_nodenum = *nodenum;
 301         status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2,
 302                                boot ? 2 : 1, PNP_DS, 0, &tmp_nodenum,
 303                                sizeof(tmp_nodenum), data, 65536);
 304         *nodenum = tmp_nodenum;
 305         return status;
 306 }
 307 
 308 int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
 309 {
 310         int status;
 311 
 312         status = __pnp_bios_get_dev_node(nodenum, boot, data);
 313         if (status)
 314                 pnpbios_print_status("get_dev_node", status);
 315         return status;
 316 }
 317 
 318 /*
 319  * Call PnP BIOS with function 0x02, "set system device node"
 320  * Input: *nodenum = desired node, 
 321  *        boot = whether to set nonvolatile boot (!=0)
 322  *               or volatile current (0) config
 323  */
 324 static int __pnp_bios_set_dev_node(u8 nodenum, char boot,
 325                                    struct pnp_bios_node *data)
 326 {
 327         u16 status;
 328 
 329         if (!pnp_bios_present())
 330                 return PNP_FUNCTION_NOT_SUPPORTED;
 331         if (!boot && pnpbios_dont_use_current_config)
 332                 return PNP_FUNCTION_NOT_SUPPORTED;
 333         status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1,
 334                                boot ? 2 : 1, PNP_DS, 0, 0, data, 65536, NULL,
 335                                0);
 336         return status;
 337 }
 338 
 339 int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
 340 {
 341         int status;
 342 
 343         status = __pnp_bios_set_dev_node(nodenum, boot, data);
 344         if (status) {
 345                 pnpbios_print_status("set_dev_node", status);
 346                 return status;
 347         }
 348         if (!boot) {            /* Update devlist */
 349                 status = pnp_bios_get_dev_node(&nodenum, boot, data);
 350                 if (status)
 351                         return status;
 352         }
 353         return status;
 354 }
 355 
 356 /*
 357  * Call PnP BIOS with function 0x05, "get docking station information"
 358  */
 359 int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
 360 {
 361         u16 status;
 362 
 363         if (!pnp_bios_present())
 364                 return PNP_FUNCTION_NOT_SUPPORTED;
 365         status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1,
 366                                PNP_DS, 0, 0, 0, 0, data,
 367                                sizeof(struct pnp_docking_station_info), NULL,
 368                                0);
 369         return status;
 370 }
 371 
 372 /*
 373  * Call PnP BIOS with function 0x0a, "get statically allocated resource
 374  * information"
 375  */
 376 static int __pnp_bios_get_stat_res(char *info)
 377 {
 378         u16 status;
 379 
 380         if (!pnp_bios_present())
 381                 return PNP_FUNCTION_NOT_SUPPORTED;
 382         status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1,
 383                                PNP_DS, 0, 0, 0, 0, info, 65536, NULL, 0);
 384         return status;
 385 }
 386 
 387 int pnp_bios_get_stat_res(char *info)
 388 {
 389         int status;
 390 
 391         status = __pnp_bios_get_stat_res(info);
 392         if (status)
 393                 pnpbios_print_status("get_stat_res", status);
 394         return status;
 395 }
 396 
 397 /*
 398  * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
 399  */
 400 static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
 401 {
 402         u16 status;
 403 
 404         if (!pnp_bios_present())
 405                 return PNP_FUNCTION_NOT_SUPPORTED;
 406         status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS,
 407                                0, 0, 0, 0, data,
 408                                sizeof(struct pnp_isa_config_struc), NULL, 0);
 409         return status;
 410 }
 411 
 412 int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
 413 {
 414         int status;
 415 
 416         status = __pnp_bios_isapnp_config(data);
 417         if (status)
 418                 pnpbios_print_status("isapnp_config", status);
 419         return status;
 420 }
 421 
 422 /*
 423  * Call PnP BIOS with function 0x41, "get ESCD info"
 424  */
 425 static int __pnp_bios_escd_info(struct escd_info_struc *data)
 426 {
 427         u16 status;
 428 
 429         if (!pnp_bios_present())
 430                 return ESCD_FUNCTION_NOT_SUPPORTED;
 431         status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4,
 432                                PNP_TS1, PNP_DS, data,
 433                                sizeof(struct escd_info_struc), NULL, 0);
 434         return status;
 435 }
 436 
 437 int pnp_bios_escd_info(struct escd_info_struc *data)
 438 {
 439         int status;
 440 
 441         status = __pnp_bios_escd_info(data);
 442         if (status)
 443                 pnpbios_print_status("escd_info", status);
 444         return status;
 445 }
 446 
 447 /*
 448  * Call PnP BIOS function 0x42, "read ESCD"
 449  * nvram_base is determined by calling escd_info
 450  */
 451 static int __pnp_bios_read_escd(char *data, u32 nvram_base)
 452 {
 453         u16 status;
 454 
 455         if (!pnp_bios_present())
 456                 return ESCD_FUNCTION_NOT_SUPPORTED;
 457         status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0,
 458                                0, data, 65536, __va(nvram_base), 65536);
 459         return status;
 460 }
 461 
 462 int pnp_bios_read_escd(char *data, u32 nvram_base)
 463 {
 464         int status;
 465 
 466         status = __pnp_bios_read_escd(data, nvram_base);
 467         if (status)
 468                 pnpbios_print_status("read_escd", status);
 469         return status;
 470 }
 471 
 472 void pnpbios_calls_init(union pnp_bios_install_struct *header)
 473 {
 474         int i;
 475 
 476         spin_lock_init(&pnp_bios_lock);
 477         pnp_bios_callpoint.offset = header->fields.pm16offset;
 478         pnp_bios_callpoint.segment = PNP_CS16;
 479 
 480         for_each_possible_cpu(i) {
 481                 struct desc_struct *gdt = get_cpu_gdt_rw(i);
 482                 if (!gdt)
 483                         continue;
 484                 set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_CS32],
 485                          (unsigned long)&pnp_bios_callfunc);
 486                 set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_CS16],
 487                          (unsigned long)__va(header->fields.pm16cseg));
 488                 set_desc_base(&gdt[GDT_ENTRY_PNPBIOS_DS],
 489                          (unsigned long)__va(header->fields.pm16dseg));
 490         }
 491 }

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