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