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