View | Details | Raw Unified | Return to bug 3774 | Differences between
and this patch

Collapse All | Expand All

(-)a/drivers/acpi/Kconfig (+17 lines)
Lines 290-295 config ACPI_CUSTOM_DSDT_FILE Link Here
290
	  Enter the full path name to the file which includes the AmlCode
290
	  Enter the full path name to the file which includes the AmlCode
291
	  declaration.
291
	  declaration.
292
292
293
config ACPI_CUSTOM_DSDT_INITRD
294
	bool "Read Custom DSDT from initramfs"
295
	depends on BLK_DEV_INITRD
296
	default y
297
	help
298
	  The DSDT (Differentiated System Description Table) often needs to be
299
	  overridden because of broken BIOS implementations. If this feature is
300
	  activated you will be able to provide a customized DSDT by adding it
301
	  to your initramfs.  For now you need to use a special mkinitrd tool.
302
	  For more details see <file:Documentation/dsdt-initrd.txt> or
303
	  <http://gaugusch.at/kernel.shtml>. If there is no table found, it
304
	  will fallback to the custom DSDT in-kernel (if activated) or to the
305
	  DSDT from the BIOS.
306
307
	  Even if you do not need a new one at the moment, you may want to use a
308
	  better implemented DSDT later. It is safe to say Y here.
309
293
config ACPI_BLACKLIST_YEAR
310
config ACPI_BLACKLIST_YEAR
294
	int "Disable ACPI for systems before Jan 1st this year" if X86_32
311
	int "Disable ACPI for systems before Jan 1st this year" if X86_32
295
	default 0
312
	default 0
(-)a/drivers/acpi/osl.c (-4 / +123 lines)
Lines 68-73 EXPORT_SYMBOL(acpi_in_debugger); Link Here
68
extern char line_buf[80];
68
extern char line_buf[80];
69
#endif				/*ENABLE_DEBUGGER */
69
#endif				/*ENABLE_DEBUGGER */
70
70
71
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
72
int acpi_must_unregister_table = FALSE;
73
#endif
74
71
static unsigned int acpi_irq_irq;
75
static unsigned int acpi_irq_irq;
72
static acpi_osd_handler acpi_irq_handler;
76
static acpi_osd_handler acpi_irq_handler;
73
static void *acpi_irq_context;
77
static void *acpi_irq_context;
Lines 275-280 acpi_os_predefined_override(const struct Link Here
275
	return AE_OK;
279
	return AE_OK;
276
}
280
}
277
281
282
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
283
#define MAX_DS_SDTS 10
284
static struct acpi_table_header *ds_sdt_buffers[MAX_DS_SDTS];
285
static unsigned int tables_loaded = 0;
286
287
void acpi_load_override_tables(void){
288
	struct file         *firmware_file;
289
	mm_segment_t        oldfs;
290
	unsigned long       len, len2;
291
	struct kstat        stat;
292
	unsigned int        x, y;
293
	char *ramfs_ds_sdt_names[MAX_DS_SDTS] = {
294
		"/DSDT.aml",
295
		"/SSDT.aml",
296
		"/SSDT1.aml",
297
		"/SSDT2.aml",
298
		"/SSDT3.aml",
299
		"/SSDT4.aml",
300
		"/SSDT5.aml",
301
		"/SSDT6.aml",
302
		"/SSDT7.aml",
303
		"/SSDT8.aml",
304
	};
305
	/*
306
	 * Never do this at home, only the user-space is allowed to open a file.
307
	 * The clean way would be to use the firmware loader. But this code must be run
308
	 * before there is any userspace available. So we need a static/init firmware
309
	 * infrastructure, which doesn't exist yet...
310
	 */
311
	for (x = 0; x < MAX_DS_SDTS; x++){
312
		if (vfs_stat(ramfs_ds_sdt_names[x], &stat) < 0) {
313
			continue;
314
		}
315
		len = stat.size;
316
		/* check especially against empty files */
317
		if (len <= 4) {
318
			printk("error file %s is too small, only %lu bytes.\n",
319
			       ramfs_ds_sdt_names[x], len);
320
			continue;
321
		}
322
323
		ds_sdt_buffers[x] = kmalloc(len, GFP_KERNEL);
324
		if (!ds_sdt_buffers[x]) {
325
			printk("error when allocating %lu bytes of memory.\n",
326
			       len);
327
			/* better free all tables again */
328
			for (y = 0; y < x; y++){
329
				if (ds_sdt_buffers[y])
330
					kfree(ds_sdt_buffers[x]);
331
			}
332
			acpi_must_unregister_table = FALSE;
333
			return;
334
		}
335
336
		firmware_file = filp_open(ramfs_ds_sdt_names[x], O_RDONLY, 0);
337
		if (IS_ERR(firmware_file)) {
338
			printk("error, could not open file %s.\n",
339
			       ramfs_ds_sdt_names[x]);
340
			kfree(ds_sdt_buffers[x]);
341
			continue;
342
		}
343
344
		oldfs = get_fs();
345
		set_fs(KERNEL_DS);
346
		len2 = vfs_read(firmware_file,
347
				(char __user *)ds_sdt_buffers[x],
348
				len,
349
				&firmware_file->f_pos);
350
		set_fs(oldfs);
351
		filp_close(firmware_file, NULL);
352
		if (len2 < len) {
353
			printk("error trying to read %lu bytes from %s.\n",
354
			       len, ramfs_ds_sdt_names[x]);
355
			kfree(ds_sdt_buffers[x]);
356
			continue;
357
		}
358
		printk(PREFIX "successfully read %lu bytes from file %s\n",
359
		       len, ramfs_ds_sdt_names[x]);
360
	}
361
}
362
363
struct acpi_table_header * acpi_find_dsdt_initrd(struct acpi_table_header * t)
364
{
365
	struct acpi_table_header	*ret = NULL;
366
	unsigned int                     x;
367
	for (x = 0; x < MAX_DS_SDTS; x++){
368
		if (ds_sdt_buffers[x]){
369
			if (!memcmp(ds_sdt_buffers[x]->signature,
370
				    t->signature, 4) &&
371
			    !memcmp(ds_sdt_buffers[x]->oem_table_id,
372
				    t->oem_table_id, 8)){
373
				ret = ds_sdt_buffers[x];
374
				printk(PREFIX "Override [%4.4s-%8.8s]"
375
				       " from initramfs -"
376
				       " tainting kernel\n",
377
				       t->signature,
378
				       t->oem_table_id);
379
				add_taint(TAINT_NO_SUPPORT);
380
				acpi_must_unregister_table = TRUE;
381
				break;
382
			}
383
		}
384
	}
385
	return ret;
386
}
387
#endif
388
278
acpi_status
389
acpi_status
279
acpi_os_table_override(struct acpi_table_header * existing_table,
390
acpi_os_table_override(struct acpi_table_header * existing_table,
280
		       struct acpi_table_header ** new_table)
391
		       struct acpi_table_header ** new_table)
Lines 282-294 acpi_os_table_override(struct acpi_table Link Here
282
	if (!existing_table || !new_table)
393
	if (!existing_table || !new_table)
283
		return AE_BAD_PARAMETER;
394
		return AE_BAD_PARAMETER;
284
395
396
	*new_table = NULL;
397
285
#ifdef CONFIG_ACPI_CUSTOM_DSDT
398
#ifdef CONFIG_ACPI_CUSTOM_DSDT
286
	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
399
	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
287
		*new_table = (struct acpi_table_header *)AmlCode;
400
		*new_table = (struct acpi_table_header *)AmlCode;
288
	else
401
#endif
289
		*new_table = NULL;
402
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
290
#else
403
	if (!tables_loaded){
291
	*new_table = NULL;
404
		acpi_load_override_tables();
405
		tables_loaded = 1;
406
	}
407
	if (!strncmp(existing_table->signature, "DSDT", 4) ||
408
	    !strncmp(existing_table->signature, "SSDT", 4)){
409
		*new_table = acpi_find_dsdt_initrd(existing_table);
410
	}
292
#endif
411
#endif
293
	return AE_OK;
412
	return AE_OK;
294
}
413
}
(-)a/include/acpi/acpiosxf.h (+4 lines)
Lines 95-100 acpi_status Link Here
95
acpi_os_table_override(struct acpi_table_header *existing_table,
95
acpi_os_table_override(struct acpi_table_header *existing_table,
96
		       struct acpi_table_header **new_table);
96
		       struct acpi_table_header **new_table);
97
97
98
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
99
extern int acpi_must_unregister_table;
100
#endif
101
98
/*
102
/*
99
 * Spinlock primitives
103
 * Spinlock primitives
100
 */
104
 */
(-)a/init/initramfs.c (-1 / +3 lines)
Lines 541-547 skip: Link Here
541
541
542
#endif
542
#endif
543
543
544
static int __init populate_rootfs(void)
544
int __init populate_rootfs(void)
545
{
545
{
546
	char *err = unpack_to_rootfs(__initramfs_start,
546
	char *err = unpack_to_rootfs(__initramfs_start,
547
			 __initramfs_end - __initramfs_start, 0);
547
			 __initramfs_end - __initramfs_start, 0);
Lines 582-585 static int __init populate_rootfs(void) Link Here
582
#endif
582
#endif
583
	return 0;
583
	return 0;
584
}
584
}
585
#ifndef CONFIG_ACPI_CUSTOM_DSDT_INITRD
585
rootfs_initcall(populate_rootfs);
586
rootfs_initcall(populate_rootfs);
587
#endif
(-)a/init/main.c (+9 lines)
Lines 112-117 static inline void mark_rodata_ro(void) Link Here
112
extern void tc_init(void);
112
extern void tc_init(void);
113
#endif
113
#endif
114
114
115
#ifdef CONFIG_BLK_DEV_INITRD
116
extern int populate_rootfs(void);
117
#else
118
static inline void populate_rootfs(void) {}
119
#endif
120
115
enum system_states system_state;
121
enum system_states system_state;
116
EXPORT_SYMBOL(system_state);
122
EXPORT_SYMBOL(system_state);
117
123
Lines 662-667 asmlinkage void __init start_kernel(void Link Here
662
668
663
	check_bugs();
669
	check_bugs();
664
670
671
#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
672
	populate_rootfs(); /* For DSDT override from initramfs */
673
#endif
665
	acpi_early_init(); /* before LAPIC and SMP init */
674
	acpi_early_init(); /* before LAPIC and SMP init */
666
675
667
	/* Do the rest non-__init'ed, we're now alive */
676
	/* Do the rest non-__init'ed, we're now alive */

Return to bug 3774