aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/bootflag.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/bootflag.c')
-rw-r--r--arch/x86/kernel/bootflag.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/arch/x86/kernel/bootflag.c b/arch/x86/kernel/bootflag.c
new file mode 100644
index 000000000000..0b9860530a6b
--- /dev/null
+++ b/arch/x86/kernel/bootflag.c
@@ -0,0 +1,98 @@
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
25int sbf_port __initdata = -1; /* set via acpi_boot_init() */
26
27
28static 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
41static 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
58static 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
70static 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
79static 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
98module_init(sbf_init);