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