1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Implement 'Simple Boot Flag Specification 2.0' 4 */ 5 #include <linux/types.h> 6 #include <linux/kernel.h> 7 #include <linux/init.h> 8 #include <linux/string.h> 9 #include <linux/spinlock.h> 10 #include <linux/acpi.h> 11 #include <linux/bitops.h> 12 #include <asm/io.h> 13 14 #include <linux/mc146818rtc.h> 15 16 #define SBF_RESERVED (0x78) 17 #define SBF_PNPOS (1<<0) 18 #define SBF_BOOTING (1<<1) 19 #define SBF_DIAG (1<<2) 20 #define SBF_PARITY (1<<7) 21 22 int sbf_port __initdata = -1; /* set via acpi_boot_init() */ 23 sbf_write(u8 v)24static void __init sbf_write(u8 v) 25 { 26 unsigned long flags; 27 28 if (sbf_port != -1) { 29 if (!parity8(v)) 30 v ^= SBF_PARITY; 31 32 printk(KERN_INFO "Simple Boot Flag at 0x%x set to 0x%x\n", 33 sbf_port, v); 34 35 spin_lock_irqsave(&rtc_lock, flags); 36 CMOS_WRITE(v, sbf_port); 37 spin_unlock_irqrestore(&rtc_lock, flags); 38 } 39 } 40 sbf_read(void)41static u8 __init sbf_read(void) 42 { 43 unsigned long flags; 44 u8 v; 45 46 if (sbf_port == -1) 47 return 0; 48 49 spin_lock_irqsave(&rtc_lock, flags); 50 v = CMOS_READ(sbf_port); 51 spin_unlock_irqrestore(&rtc_lock, flags); 52 53 return v; 54 } 55 sbf_value_valid(u8 v)56static bool __init sbf_value_valid(u8 v) 57 { 58 if (v & SBF_RESERVED) /* Reserved bits */ 59 return false; 60 if (!parity8(v)) 61 return false; 62 63 return true; 64 } 65 sbf_init(void)66static int __init sbf_init(void) 67 { 68 u8 v; 69 70 if (sbf_port == -1) 71 return 0; 72 73 v = sbf_read(); 74 if (!sbf_value_valid(v)) { 75 printk(KERN_WARNING "Simple Boot Flag value 0x%x read from " 76 "CMOS RAM was invalid\n", v); 77 } 78 79 v &= ~SBF_RESERVED; 80 v &= ~SBF_BOOTING; 81 v &= ~SBF_DIAG; 82 #if defined(CONFIG_ISAPNP) 83 v |= SBF_PNPOS; 84 #endif 85 sbf_write(v); 86 87 return 0; 88 } 89 arch_initcall(sbf_init); 90