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