Merge branch 'master' of git://git.infradead.org/~dedekind/ubi-2.6
[deliverable/linux.git] / arch / x86 / kernel / bootflag.c
1 /*
2 * Implement 'Simple Boot Flag Specification 2.0'
3 */
4
5
6 #include <linux/types.h>
7 #include <linux/kernel.h>
8 #include <linux/init.h>
9 #include <linux/string.h>
10 #include <linux/slab.h>
11 #include <linux/spinlock.h>
12 #include <linux/acpi.h>
13 #include <asm/io.h>
14
15 #include <linux/mc146818rtc.h>
16
17
18 #define SBF_RESERVED (0x78)
19 #define SBF_PNPOS (1<<0)
20 #define SBF_BOOTING (1<<1)
21 #define SBF_DIAG (1<<2)
22 #define SBF_PARITY (1<<7)
23
24
25 int sbf_port __initdata = -1; /* set via acpi_boot_init() */
26
27
28 static int __init parity(u8 v)
29 {
30 int x = 0;
31 int i;
32
33 for(i=0;i<8;i++)
34 {
35 x^=(v&1);
36 v>>=1;
37 }
38 return x;
39 }
40
41 static void __init sbf_write(u8 v)
42 {
43 unsigned long flags;
44 if(sbf_port != -1)
45 {
46 v &= ~SBF_PARITY;
47 if(!parity(v))
48 v|=SBF_PARITY;
49
50 printk(KERN_INFO "Simple Boot Flag at 0x%x set to 0x%x\n", sbf_port, v);
51
52 spin_lock_irqsave(&rtc_lock, flags);
53 CMOS_WRITE(v, sbf_port);
54 spin_unlock_irqrestore(&rtc_lock, flags);
55 }
56 }
57
58 static u8 __init sbf_read(void)
59 {
60 u8 v;
61 unsigned long flags;
62 if(sbf_port == -1)
63 return 0;
64 spin_lock_irqsave(&rtc_lock, flags);
65 v = CMOS_READ(sbf_port);
66 spin_unlock_irqrestore(&rtc_lock, flags);
67 return v;
68 }
69
70 static int __init sbf_value_valid(u8 v)
71 {
72 if(v&SBF_RESERVED) /* Reserved bits */
73 return 0;
74 if(!parity(v))
75 return 0;
76 return 1;
77 }
78
79 static int __init sbf_init(void)
80 {
81 u8 v;
82 if(sbf_port == -1)
83 return 0;
84 v = sbf_read();
85 if(!sbf_value_valid(v))
86 printk(KERN_WARNING "Simple Boot Flag value 0x%x read from CMOS RAM was invalid\n",v);
87
88 v &= ~SBF_RESERVED;
89 v &= ~SBF_BOOTING;
90 v &= ~SBF_DIAG;
91 #if defined(CONFIG_ISAPNP)
92 v |= SBF_PNPOS;
93 #endif
94 sbf_write(v);
95 return 0;
96 }
97
98 module_init(sbf_init);
This page took 0.03405 seconds and 6 git commands to generate.