Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  Implement 'Simple Boot Flag Specification 2.0'
0004  */
0005 #include <linux/types.h>
0006 #include <linux/kernel.h>
0007 #include <linux/init.h>
0008 #include <linux/string.h>
0009 #include <linux/spinlock.h>
0010 #include <linux/acpi.h>
0011 #include <asm/io.h>
0012 
0013 #include <linux/mc146818rtc.h>
0014 
0015 #define SBF_RESERVED (0x78)
0016 #define SBF_PNPOS    (1<<0)
0017 #define SBF_BOOTING  (1<<1)
0018 #define SBF_DIAG     (1<<2)
0019 #define SBF_PARITY   (1<<7)
0020 
0021 int sbf_port __initdata = -1;   /* set via acpi_boot_init() */
0022 
0023 static int __init parity(u8 v)
0024 {
0025     int x = 0;
0026     int i;
0027 
0028     for (i = 0; i < 8; i++) {
0029         x ^= (v & 1);
0030         v >>= 1;
0031     }
0032 
0033     return x;
0034 }
0035 
0036 static void __init sbf_write(u8 v)
0037 {
0038     unsigned long flags;
0039 
0040     if (sbf_port != -1) {
0041         v &= ~SBF_PARITY;
0042         if (!parity(v))
0043             v |= SBF_PARITY;
0044 
0045         printk(KERN_INFO "Simple Boot Flag at 0x%x set to 0x%x\n",
0046             sbf_port, v);
0047 
0048         spin_lock_irqsave(&rtc_lock, flags);
0049         CMOS_WRITE(v, sbf_port);
0050         spin_unlock_irqrestore(&rtc_lock, flags);
0051     }
0052 }
0053 
0054 static u8 __init sbf_read(void)
0055 {
0056     unsigned long flags;
0057     u8 v;
0058 
0059     if (sbf_port == -1)
0060         return 0;
0061 
0062     spin_lock_irqsave(&rtc_lock, flags);
0063     v = CMOS_READ(sbf_port);
0064     spin_unlock_irqrestore(&rtc_lock, flags);
0065 
0066     return v;
0067 }
0068 
0069 static int __init sbf_value_valid(u8 v)
0070 {
0071     if (v & SBF_RESERVED)       /* Reserved bits */
0072         return 0;
0073     if (!parity(v))
0074         return 0;
0075 
0076     return 1;
0077 }
0078 
0079 static int __init sbf_init(void)
0080 {
0081     u8 v;
0082 
0083     if (sbf_port == -1)
0084         return 0;
0085 
0086     v = sbf_read();
0087     if (!sbf_value_valid(v)) {
0088         printk(KERN_WARNING "Simple Boot Flag value 0x%x read from "
0089             "CMOS RAM was invalid\n", v);
0090     }
0091 
0092     v &= ~SBF_RESERVED;
0093     v &= ~SBF_BOOTING;
0094     v &= ~SBF_DIAG;
0095 #if defined(CONFIG_ISAPNP)
0096     v |= SBF_PNPOS;
0097 #endif
0098     sbf_write(v);
0099 
0100     return 0;
0101 }
0102 arch_initcall(sbf_init);