linux/arch/x86/kernel/bootflag.c
<<
>>
Prefs
   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
  20int sbf_port __initdata = -1;   /* set via acpi_boot_init() */
  21
  22static 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
  35static 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
  53static 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
  68static 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
  78static 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}
 101module_init(sbf_init);
 102