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

📄 setup.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		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];	static struct change_member *change_point[2*E820MAX];	static struct e820entry *overlap_list[E820MAX];	static struct e820entry new_bios[E820MAX];	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;	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) */	chgidx = 0;	for (i=0; i < old_nr; i++)	{		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];	}	/* sort change-point list by memory addresses (low -> high) */	still_changing = 1;	while (still_changing)	{		still_changing = 0;		for (i=1; i < 2*old_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) &&				 (change_point[i]->addr == change_point[i]->pbios->addr) &&				 (change_point[i-1]->addr != change_point[i-1]->pbios->addr))			   )			{				change_tmp = change_point[i];				change_point[i] = change_point[i-1];				change_point[i-1] = change_tmp;				still_changing=1;			}		}	}	/* create a new bios memory map, removing overlaps */	overlap_entries=0;	 /* number of entries in the overlap table */	new_bios_entry=0;	 /* index for creating new bios map entries */	last_type = 0;		 /* start with undefined memory type */	last_addr = 0;		 /* start with 0 as last starting address */	/* loop through change-points, determining affect on the new bios map */	for (chgidx=0; chgidx < 2*old_nr; chgidx++)	{		/* keep track of all overlapping bios entries */		if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)		{			/* add map entry to overlap list (> 1 entry implies an overlap) */			overlap_list[overlap_entries++]=change_point[chgidx]->pbios;		}		else		{			/* remove entry from list (order independent, so swap with last) */			for (i=0; i<overlap_entries; i++)			{				if (overlap_list[i] == change_point[chgidx]->pbios)					overlap_list[i] = overlap_list[overlap_entries-1];			}			overlap_entries--;		}		/* if there are overlapping entries, decide which "type" to use */		/* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */		current_type = 0;		for (i=0; i<overlap_entries; i++)			if (overlap_list[i]->type > current_type)				current_type = overlap_list[i]->type;		/* continue building up new bios map based on this information */		if (current_type != last_type)	{			if (last_type != 0)	 {				new_bios[new_bios_entry].size =					change_point[chgidx]->addr - last_addr;				/* move forward only if the new size was non-zero */				if (new_bios[new_bios_entry].size != 0)					if (++new_bios_entry >= E820MAX)						break; 	/* no more space left for new bios entries */			}			if (current_type != 0)	{				new_bios[new_bios_entry].addr = change_point[chgidx]->addr;				new_bios[new_bios_entry].type = current_type;				last_addr=change_point[chgidx]->addr;			}			last_type = current_type;		}	}	new_nr = new_bios_entry;   /* retain count for new bios entries */	/* copy new bios mapping into original location */	memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));	*pnr_map = new_nr;	return 0;}/* * Copy the BIOS e820 map into a safe place. * * Sanity-check it while we're at it.. * * If we're lucky and live on a modern system, the setup code * will have given us a memory map that we can use to properly * set up memory.  If we aren't, we'll fake a memory map. * * We check to see that the memory map contains at least 2 elements * before we'll use it, because the detection code in setup.S may * not be perfect and most every PC known to man has two memory * regions: one from 0 to 640k, and one from 1mb up.  (The IBM * thinkpad 560x, for example, does not cooperate with the memory * detection code.) */static int __init copy_e820_map(struct e820entry * biosmap, int nr_map){	/* Only one memory region (or negative)? Ignore it */	if (nr_map < 2)		return -1;	do {		unsigned long long start = biosmap->addr;		unsigned long long size = biosmap->size;		unsigned long long end = start + size;		unsigned long type = biosmap->type;		/* Overflow in 64 bits? Ignore the memory map. */		if (start > end)			return -1;		/*		 * Some BIOSes claim RAM in the 640k - 1M region.		 * Not right. Fix it up.		 */		if (type == E820_RAM) {			if (start < 0x100000ULL && end > 0xA0000ULL) {				if (start < 0xA0000ULL)					add_memory_region(start, 0xA0000ULL-start, type);				if (end <= 0x100000ULL)					continue;				start = 0x100000ULL;				size = end - start;			}		}		add_memory_region(start, size, type);	} while (biosmap++,--nr_map);	return 0;}#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)unsigned char eddnr;struct edd_info edd[EDDMAXNR];/** * copy_edd() - Copy the BIOS EDD information *              from empty_zero_page into a safe place. * */static inline void copy_edd(void){     eddnr = EDD_NR;     memcpy(edd, EDD_BUF, sizeof(edd));}#else#define copy_edd() do {} while (0)#endif/* * Do NOT EVER look at the BIOS memory size location. * It does not work on many machines. */#define LOWMEMSIZE()	(0x9f000)static void __init setup_memory_region(void){	char *who = "BIOS-e820";	/*	 * Try to copy the BIOS-supplied E820-map.	 *	 * Otherwise fake a memory map; one section from 0k->640k,	 * the next section from 1mb->appropriate_mem_k	 */	sanitize_e820_map(E820_MAP, &E820_MAP_NR);	if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {		unsigned long mem_size;		/* compare results from other methods and take the greater */		if (ALT_MEM_K < EXT_MEM_K) {			mem_size = EXT_MEM_K;			who = "BIOS-88";		} else {			mem_size = ALT_MEM_K;			who = "BIOS-e801";		}		e820.nr_map = 0;		add_memory_region(0, LOWMEMSIZE(), E820_RAM);		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);  	}	printk(KERN_INFO "BIOS-provided physical RAM map:\n");	print_memory_map(who);} /* setup_memory_region */int allowsysinfo = 1;static void __init parse_cmdline_early (char ** cmdline_p){	char c = ' ', *to = command_line, *from = COMMAND_LINE;	int len = 0;	int userdef = 0;	/* Save unparsed command line copy for /proc/cmdline */	memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';	for (;;) {		if (c != ' ')			goto nextchar;		/*		 * "mem=nopentium" disables the 4MB page tables.		 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM		 * to <mem>, overriding the bios size.		 * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from		 * <start> to <start>+<mem>, overriding the bios size.		 */		if (!memcmp(from, "mem=", 4)) {			if (to != command_line)				to--;			if (!memcmp(from+4, "nopentium", 9)) {				from += 9+4;				clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability);				set_bit(X86_FEATURE_PSE, &disabled_x86_caps);			} else if (!memcmp(from+4, "exactmap", 8)) {				from += 8+4;				e820.nr_map = 0;				userdef = 1;			} else {				/* If the user specifies memory size, we				 * limit the BIOS-provided memory map to				 * that size. exactmap can be used to specify				 * the exact map. mem=number can be used to				 * trim the existing memory map.				 */				unsigned long long start_at, mem_size; 				mem_size = memparse(from+4, &from);				if (*from == '@') {					start_at = memparse(from+1, &from);					add_memory_region(start_at, mem_size, E820_RAM);				} else {					limit_regions(mem_size);					userdef=1;				}			}		}		/* "noht" disables HyperThreading (2 logical cpus per Xeon) */		else if (!memcmp(from, "noht", 4)) { 			disable_x86_ht = 1;			set_bit(X86_FEATURE_HT, disabled_x86_caps);		}		/* "acpismp=force" forces parsing and use of the ACPI SMP table */		else if (!memcmp(from, "acpismp=force", 13))			enable_acpi_smp_table = 1;		else if (!memcmp(from, "nosysinfo", 9))			allowsysinfo = 0;		/*		 * highmem=size forces highmem to be exactly 'size' bytes.		 * This works even on boxes that have no highmem otherwise.		 * This also works to reduce highmem size on bigger boxes.		 */		else if (!memcmp(from, "highmem=", 8))			highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;nextchar:		c = *(from++);		if (!c)			break;		if (COMMAND_LINE_SIZE <= ++len)			break;		*(to++) = c;	}	*to = '\0';	*cmdline_p = command_line;	if (userdef) {		printk(KERN_INFO "user-defined physical RAM map:\n");		print_memory_map("user");	}}#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)#define PFN_PHYS(x)	((x) << PAGE_SHIFT)/* * Reserved space for vmalloc and iomap - defined in asm/page.h */#define MAXMEM_PFN	PFN_DOWN(MAXMEM)#define MAX_NONPAE_PFN	(1 << 20)/* * Find the highest page frame number we have available */static void __init find_max_pfn(void){	int i;	max_pfn = 0;	for (i = 0; i < e820.nr_map; i++) {		unsigned long start, end;		/* RAM? */		if (e820.map[i].type != E820_RAM)			continue;		start = PFN_UP(e820.map[i].addr);		end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);		if (start >= end)			continue;		if (end > max_pfn)			max_pfn = end;	}}/* * Determine low and high memory ranges: */static unsigned long __init find_max_low_pfn(void){	unsigned long max_low_pfn;	max_low_pfn = max_pfn;	if (max_low_pfn > MAXMEM_PFN) {		if (highmem_pages == -1)			highmem_pages = max_pfn - MAXMEM_PFN;		if (highmem_pages + MAXMEM_PFN < max_pfn)			max_pfn = MAXMEM_PFN + highmem_pages;		if (highmem_pages + MAXMEM_PFN > max_pfn) {			printk("only %luMB highmem pages available, ignoring highmem size of %uMB.\n", pages_to_mb(max_pfn - MAXMEM_PFN), pages_to_mb(highmem_pages));			highmem_pages = 0;		}		max_low_pfn = MAXMEM_PFN;#ifndef CONFIG_HIGHMEM		/* Maximum memory usable is what is directly addressable */		printk(KERN_WARNING "Warning only %ldMB will be used.\n",					MAXMEM>>20);		if (max_pfn > MAX_NONPAE_PFN)			printk(KERN_WARNING "Use a PAE enabled kernel.\n");		else			printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");#else /* !CONFIG_HIGHMEM */#ifndef CONFIG_X86_PAE		if (max_pfn > MAX_NONPAE_PFN) {			max_pfn = MAX_NONPAE_PFN;			printk(KERN_WARNING "Warning only 4GB will be used.\n");			printk(KERN_WARNING "Use a PAE enabled kernel.\n");		}#endif /* !CONFIG_X86_PAE */#endif /* !CONFIG_HIGHMEM */	} else {		if (highmem_pages == -1)			highmem_pages = 0;#if CONFIG_HIGHMEM		if (highmem_pages >= max_pfn) {			printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn));			highmem_pages = 0;		}		if (highmem_pages) {			if (max_low_pfn-highmem_pages < 64*1024*1024/PAGE_SIZE){				printk(KERN_ERR "highmem size %uMB results in smaller than 64MB lowmem, ignoring it.\n", pages_to_mb(highmem_pages));				highmem_pages = 0;			}			max_low_pfn -= highmem_pages;		}#else		if (highmem_pages)			printk(KERN_ERR "ignoring highmem size on non-highmem kernel!\n");#endif	}	return max_low_pfn;}/* * Register fully available low RAM pages with the bootmem allocator. */static void __init register_bootmem_low_pages(unsigned long max_low_pfn){	int i;	for (i = 0; i < e820.nr_map; i++) {		unsigned long curr_pfn, last_pfn, size;		/*		 * Reserve usable low memory		 */		if (e820.map[i].type != E820_RAM)			continue;		/*		 * We are rounding up the start address of usable memory:		 */		curr_pfn = PFN_UP(e820.map[i].addr);		if (curr_pfn >= max_low_pfn)			continue;		/*		 * ... and at the end of the usable range downwards:		 */		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);		if (last_pfn > max_low_pfn)			last_pfn = max_low_pfn;		/*		 * .. finally, did all the rounding and playing		 * around just make the area go away?		 */		if (last_pfn <= curr_pfn)			continue;		size = last_pfn - curr_pfn;		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));	}}static unsigned long __init setup_memory(void){	unsigned long bootmap_size, start_pfn, max_low_pfn;	/*	 * partially used pages are not usable - thus	 * we are rounding upwards:	 */	start_pfn = PFN_UP(__pa(&_end));	find_max_pfn();	max_low_pfn = find_max_low_pfn();

⌨️ 快捷键说明

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