⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 e820_32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/kernel.h>#include <linux/types.h>#include <linux/init.h>#include <linux/bootmem.h>#include <linux/ioport.h>#include <linux/string.h>#include <linux/kexec.h>#include <linux/module.h>#include <linux/mm.h>#include <linux/efi.h>#include <linux/pfn.h>#include <linux/uaccess.h>#include <linux/suspend.h>#include <asm/pgtable.h>#include <asm/page.h>#include <asm/e820.h>#include <asm/setup.h>#ifdef CONFIG_EFIint efi_enabled = 0;EXPORT_SYMBOL(efi_enabled);#endifstruct e820map e820;struct change_member {	struct e820entry *pbios; /* pointer to original bios entry */	unsigned long long addr; /* address for this change point */};static struct change_member change_point_list[2*E820MAX] __initdata;static struct change_member *change_point[2*E820MAX] __initdata;static struct e820entry *overlap_list[E820MAX] __initdata;static struct e820entry new_bios[E820MAX] __initdata;/* For PCI or other memory-mapped resources */unsigned long pci_mem_start = 0x10000000;#ifdef CONFIG_PCIEXPORT_SYMBOL(pci_mem_start);#endifextern int user_defined_memmap;struct resource data_resource = {	.name	= "Kernel data",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM};struct resource code_resource = {	.name	= "Kernel code",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM};struct resource bss_resource = {	.name	= "Kernel bss",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM};static struct resource system_rom_resource = {	.name	= "System ROM",	.start	= 0xf0000,	.end	= 0xfffff,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM};static struct resource extension_rom_resource = {	.name	= "Extension ROM",	.start	= 0xe0000,	.end	= 0xeffff,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM};static struct resource adapter_rom_resources[] = { {	.name 	= "Adapter ROM",	.start	= 0xc8000,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM}, {	.name 	= "Adapter ROM",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM}, {	.name 	= "Adapter ROM",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM}, {	.name 	= "Adapter ROM",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM}, {	.name 	= "Adapter ROM",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM}, {	.name 	= "Adapter ROM",	.start	= 0,	.end	= 0,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM} };static struct resource video_rom_resource = {	.name 	= "Video ROM",	.start	= 0xc0000,	.end	= 0xc7fff,	.flags	= IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM};static struct resource video_ram_resource = {	.name	= "Video RAM area",	.start	= 0xa0000,	.end	= 0xbffff,	.flags	= IORESOURCE_BUSY | IORESOURCE_MEM};static struct resource standard_io_resources[] = { {	.name	= "dma1",	.start	= 0x0000,	.end	= 0x001f,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO}, {	.name	= "pic1",	.start	= 0x0020,	.end	= 0x0021,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO}, {	.name   = "timer0",	.start	= 0x0040,	.end    = 0x0043,	.flags  = IORESOURCE_BUSY | IORESOURCE_IO}, {	.name   = "timer1",	.start  = 0x0050,	.end    = 0x0053,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO}, {	.name	= "keyboard",	.start	= 0x0060,	.end	= 0x006f,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO}, {	.name	= "dma page reg",	.start	= 0x0080,	.end	= 0x008f,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO}, {	.name	= "pic2",	.start	= 0x00a0,	.end	= 0x00a1,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO}, {	.name	= "dma2",	.start	= 0x00c0,	.end	= 0x00df,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO}, {	.name	= "fpu",	.start	= 0x00f0,	.end	= 0x00ff,	.flags	= IORESOURCE_BUSY | IORESOURCE_IO} };#define ROMSIGNATURE 0xaa55static int __init romsignature(const unsigned char *rom){	const unsigned short * const ptr = (const unsigned short *)rom;	unsigned short sig;	return probe_kernel_address(ptr, sig) == 0 && sig == ROMSIGNATURE;}static int __init romchecksum(const unsigned char *rom, unsigned long length){	unsigned char sum, c;	for (sum = 0; length && probe_kernel_address(rom++, c) == 0; length--)		sum += c;	return !length && !sum;}static void __init probe_roms(void){	const unsigned char *rom;	unsigned long start, length, upper;	unsigned char c;	int i;	/* video rom */	upper = adapter_rom_resources[0].start;	for (start = video_rom_resource.start; start < upper; start += 2048) {		rom = isa_bus_to_virt(start);		if (!romsignature(rom))			continue;		video_rom_resource.start = start;		if (probe_kernel_address(rom + 2, c) != 0)			continue;		/* 0 < length <= 0x7f * 512, historically */		length = c * 512;		/* if checksum okay, trust length byte */		if (length && romchecksum(rom, length))			video_rom_resource.end = start + length - 1;		request_resource(&iomem_resource, &video_rom_resource);		break;	}	start = (video_rom_resource.end + 1 + 2047) & ~2047UL;	if (start < upper)		start = upper;	/* system rom */	request_resource(&iomem_resource, &system_rom_resource);	upper = system_rom_resource.start;	/* check for extension rom (ignore length byte!) */	rom = isa_bus_to_virt(extension_rom_resource.start);	if (romsignature(rom)) {		length = extension_rom_resource.end - extension_rom_resource.start + 1;		if (romchecksum(rom, length)) {			request_resource(&iomem_resource, &extension_rom_resource);			upper = extension_rom_resource.start;		}	}	/* check for adapter roms on 2k boundaries */	for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) {		rom = isa_bus_to_virt(start);		if (!romsignature(rom))			continue;		if (probe_kernel_address(rom + 2, c) != 0)			continue;		/* 0 < length <= 0x7f * 512, historically */		length = c * 512;		/* but accept any length that fits if checksum okay */		if (!length || start + length > upper || !romchecksum(rom, length))			continue;		adapter_rom_resources[i].start = start;		adapter_rom_resources[i].end = start + length - 1;		request_resource(&iomem_resource, &adapter_rom_resources[i]);		start = adapter_rom_resources[i++].end & ~2047UL;	}}/* * Request address space for all standard RAM and ROM resources * and also for regions reported as reserved by the e820. */static void __initlegacy_init_iomem_resources(struct resource *code_resource,			    struct resource *data_resource,			    struct resource *bss_resource){	int i;	probe_roms();	for (i = 0; i < e820.nr_map; i++) {		struct resource *res;#ifndef CONFIG_RESOURCES_64BIT		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)			continue;#endif		res = kzalloc(sizeof(struct resource), GFP_ATOMIC);		switch (e820.map[i].type) {		case E820_RAM:	res->name = "System RAM"; break;		case E820_ACPI:	res->name = "ACPI Tables"; break;		case E820_NVS:	res->name = "ACPI Non-volatile Storage"; break;		default:	res->name = "reserved";		}		res->start = e820.map[i].addr;		res->end = res->start + e820.map[i].size - 1;		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;		if (request_resource(&iomem_resource, res)) {			kfree(res);			continue;		}		if (e820.map[i].type == E820_RAM) {			/*			 *  We don't know which RAM region contains kernel data,			 *  so we try it repeatedly and let the resource manager			 *  test it.			 */			request_resource(res, code_resource);			request_resource(res, data_resource);			request_resource(res, bss_resource);#ifdef CONFIG_KEXEC			if (crashk_res.start != crashk_res.end)				request_resource(res, &crashk_res);#endif		}	}}/* * Request address space for all standard resources * * This is called just before pcibios_init(), which is also a * subsys_initcall, but is linked in later (in arch/i386/pci/common.c). */static int __init request_standard_resources(void){	int i;	printk("Setting up standard PCI resources\n");	if (efi_enabled)		efi_initialize_iomem_resources(&code_resource,				&data_resource, &bss_resource);	else		legacy_init_iomem_resources(&code_resource,				&data_resource, &bss_resource);	/* EFI systems may still have VGA */	request_resource(&iomem_resource, &video_ram_resource);	/* request I/O space for devices used on all i[345]86 PCs */	for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)		request_resource(&ioport_resource, &standard_io_resources[i]);	return 0;}subsys_initcall(request_standard_resources);#if defined(CONFIG_PM) && defined(CONFIG_HIBERNATION)/** * e820_mark_nosave_regions - Find the ranges of physical addresses that do not * correspond to e820 RAM areas and mark the corresponding pages as nosave for * hibernation. * * This function requires the e820 map to be sorted and without any * overlapping entries and assumes the first e820 area to be RAM. */void __init e820_mark_nosave_regions(void){	int i;	unsigned long pfn;	pfn = PFN_DOWN(e820.map[0].addr + e820.map[0].size);	for (i = 1; i < e820.nr_map; i++) {		struct e820entry *ei = &e820.map[i];		if (pfn < PFN_UP(ei->addr))			register_nosave_region(pfn, PFN_UP(ei->addr));		pfn = PFN_DOWN(ei->addr + ei->size);		if (ei->type != E820_RAM)			register_nosave_region(PFN_UP(ei->addr), pfn);		if (pfn >= max_low_pfn)			break;	}}#endifvoid __init add_memory_region(unsigned long long start,			      unsigned long long size, int type){	int x;	if (!efi_enabled) {       		x = e820.nr_map;		if (x == E820MAX) {		    printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");		    return;		}		e820.map[x].addr = start;		e820.map[x].size = size;		e820.map[x].type = type;		e820.nr_map++;	}} /* add_memory_region *//* * Sanitize the BIOS e820 map. * * Some e820 responses include overlapping entries.  The following * replaces the original e820 map with a new one, removing overlaps. * */int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map){	struct change_member *change_tmp;	unsigned long current_type, last_type;	unsigned long long last_addr;	int chgidx, still_changing;	int overlap_entries;	int new_bios_entry;	int old_nr, new_nr, chg_nr;	int i;	/*		Visually we're performing the following (1,2,3,4 = memory types)...		Sample memory map (w/overlaps):		   ____22__________________		   ______________________4_		   ____1111________________		   _44_____________________		   11111111________________		   ____________________33__		   ___________44___________		   __________33333_________		   ______________22________		   ___________________2222_		   _________111111111______		   _____________________11_		   _________________4______		Sanitized equivalent (no overlap):		   1_______________________		   _44_____________________		   ___1____________________		   ____22__________________		   ______11________________		   _________1______________		   __________3_____________		   ___________44___________		   _____________33_________		   _______________2________		   ________________1_______		   _________________4______		   ___________________2____		   ____________________33__		   ______________________4_	*/	/* if there's only one memory region, don't bother */	if (*pnr_map < 2) {		return -1;	}	old_nr = *pnr_map;	/* bail out if we find any unreasonable addresses in bios map */	for (i=0; i<old_nr; i++)		if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) {			return -1;		}	/* create pointers for initial change-point information (for sorting) */	for (i=0; i < 2*old_nr; i++)		change_point[i] = &change_point_list[i];	/* record all known change-points (starting and ending addresses),	   omitting those that are for empty memory regions */	chgidx = 0;	for (i=0; i < old_nr; i++)	{		if (biosmap[i].size != 0) {			change_point[chgidx]->addr = biosmap[i].addr;			change_point[chgidx++]->pbios = &biosmap[i];			change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;			change_point[chgidx++]->pbios = &biosmap[i];		}	}	chg_nr = chgidx;    	/* true number of change-points */	/* sort change-point list by memory addresses (low -> high) */	still_changing = 1;	while (still_changing)	{		still_changing = 0;		for (i=1; i < chg_nr; i++)  {			/* if <current_addr> > <last_addr>, swap */			/* or, if current=<start_addr> & last=<end_addr>, swap */			if ((change_point[i]->addr < change_point[i-1]->addr) ||				((change_point[i]->addr == change_point[i-1]->addr) &&

⌨️ 快捷键说明

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