bootflag.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 254 行

C
254
字号
/* *	Implement 'Simple Boot Flag Specification 1.0' * */#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/spinlock.h>#include <asm/io.h>#include <linux/mc146818rtc.h>#define SBF_RESERVED (0x78)#define SBF_PNPOS    (1<<0)#define SBF_BOOTING  (1<<1)#define SBF_DIAG     (1<<2)#define SBF_PARITY   (1<<7)struct sbf_boot{	u8 sbf_signature[4];	u32 sbf_len;	u8 sbf_revision __attribute((packed));	u8 sbf_csum __attribute((packed));	u8 sbf_oemid[6] __attribute((packed));	u8 sbf_oemtable[8] __attribute((packed));	u8 sbf_revdata[4] __attribute((packed));	u8 sbf_creator[4] __attribute((packed));	u8 sbf_crearev[4] __attribute((packed));	u8 sbf_cmos __attribute((packed));	u8 sbf_spare[3] __attribute((packed));};static int sbf_port __initdata = -1;static int __init sbf_struct_valid(unsigned long tptr){	u8 *ap;	u8 v;	unsigned int i;	struct sbf_boot sb;		memcpy_fromio(&sb, tptr, sizeof(sb));	if(sb.sbf_len != 40 && sb.sbf_len != 39)		// 39 on IBM ThinkPad A21m, BIOS version 1.02b (KXET24WW; 2000-12-19).		return 0;	ap = (u8 *)&sb;	v= 0;		for(i=0;i<sb.sbf_len;i++)		v+=*ap++;			if(v)		return 0;	if(memcmp(sb.sbf_signature, "BOOT", 4))		return 0;	if (sb.sbf_len == 39)		printk (KERN_WARNING "SBF: ACPI BOOT descriptor is wrong length (%d)\n",			sb.sbf_len);	sbf_port = sb.sbf_cmos;	/* Save CMOS port */	return 1;}static int __init parity(u8 v){	int x = 0;	int i;		for(i=0;i<8;i++)	{		x^=(v&1);		v>>=1;	}	return x;}static void __init sbf_write(u8 v){	unsigned long flags;	if(sbf_port != -1)	{		v &= ~SBF_PARITY;		if(!parity(v))			v|=SBF_PARITY;		printk(KERN_INFO "SBF: Setting boot flags 0x%x\n",v);		spin_lock_irqsave(&rtc_lock, flags);		CMOS_WRITE(v, sbf_port);		spin_unlock_irqrestore(&rtc_lock, flags);	}}static u8 __init sbf_read(void){	u8 v;	unsigned long flags;	if(sbf_port == -1)		return 0;	spin_lock_irqsave(&rtc_lock, flags);	v = CMOS_READ(sbf_port);	spin_unlock_irqrestore(&rtc_lock, flags);	return v;}static int __init sbf_value_valid(u8 v){	if(v&SBF_RESERVED)		/* Reserved bits */		return 0;	if(!parity(v))		return 0;	return 1;}static void __init sbf_bootup(void){	u8 v;	if(sbf_port == -1)		return;	v = sbf_read();	if(!sbf_value_valid(v))		printk(KERN_WARNING "SBF: Simple boot flag value 0x%x read from CMOS RAM was invalid\n",v);	v &= ~SBF_RESERVED;	v &= ~SBF_BOOTING;	v &= ~SBF_DIAG;#if defined(CONFIG_ISAPNP)	v |= SBF_PNPOS;#endif	sbf_write(v);}static int __init sbf_init(void){	unsigned int i;	void *rsdt;	u32 rsdtlen = 0;	u32 rsdtbase = 0;	u8 sum = 0;	int n;		u8 *p;		for(i=0xE0000; i <= 0xFFFE0; i+=16)	{		p = phys_to_virt(i);				if(memcmp(p, "RSD PTR ", 8))			continue;				sum = 0;		for(n=0; n<20; n++)			sum+=p[n];					if(sum != 0)			continue;					/* So it says RSD PTR and it checksums... */		/*		 *	Process the RDSP pointer		 */	 		rsdtbase = *(u32 *)(p+16);				/*		 *	RSDT length is ACPI 2 only, for ACPI 1 we must map		 *	and remap.		 */		 		if(p[15]>1)			rsdtlen = *(u32 *)(p+20);		else			rsdtlen = 36;		if(rsdtlen < 36 || rsdtlen > 1024)			continue;		break;	}	if(i>0xFFFE0)		return 0;					rsdt = ioremap(rsdtbase, rsdtlen);	if(rsdt == 0)		return 0;			i = readl(rsdt + 4);		/*	 *	Remap if needed	 */	 	if(i > rsdtlen)	{		rsdtlen = i;		iounmap(rsdt);		rsdt = ioremap(rsdtbase, rsdtlen);		if(rsdt == 0)			return 0;	}		for(n = 0; n < i; n++)		sum += readb(rsdt + n);			if(sum)	{		iounmap(rsdt);		return 0;	}		/* Ok the RSDT checksums too */		for(n = 36; n+3 < i; n += 4)	{		unsigned long rp = readl(rsdt+n);		int len = 4096;		if(rp > 0xFFFFFFFFUL - len)			len = 0xFFFFFFFFUL - rp;					/* Too close to the end!! */		if(len < 20)			continue;		rp = (unsigned long)ioremap(rp, 4096);		if(rp == 0)			continue;		if(sbf_struct_valid(rp))		{			/* Found the BOOT table and processed it */			printk(KERN_INFO "SBF: Simple Boot Flag extension found and enabled.\n");		}		iounmap((void *)rp);	}	iounmap(rsdt);	sbf_bootup();	return 0;}module_init(sbf_init);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?