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

📄 setup.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Sanitize the BIOS e820 map. * * Some e820 responses include overlapping entries.  The following  * replaces the original e820 map with a new one, removing overlaps. * */static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map){	struct change_member {		struct e820entry *pbios; /* pointer to original bios entry */		unsigned long long addr; /* address for this change point */	};	struct change_member change_point_list[2*E820MAX];	struct change_member *change_point[2*E820MAX];	struct e820entry *overlap_list[E820MAX];	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;}/* * 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 __init amd_adv_spec_cache_feature(void){	char vendor_id[16];	int ident;	int family, model; 	/* Must have CPUID */	if(!have_cpuid_p())		goto donthave;	if(cpuid_eax(0)<1)		goto donthave;		/* Must be x86 architecture */	cpuid(0, &ident,  		(int *)&vendor_id[0],		(int *)&vendor_id[8],		(int *)&vendor_id[4]);	if (memcmp(vendor_id, "AuthenticAMD", 12)) 	       goto donthave;	ident = cpuid_eax(1);	family = (ident >> 8) & 0xf;	model  = (ident >> 4) & 0xf;	if (((family == 6)  && (model >= 6)) || (family == 15)) {		printk(KERN_INFO "Advanced speculative caching feature present\n");		return 1;	}donthave:	printk(KERN_INFO "Advanced speculative caching feature not present\n");	return 0;}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);			} 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;		/* "acpismp=force" forces parsing and use of the ACPI SMP table */		else if (!memcmp(from, "acpismp=force", 13))			enable_acpi_smp_table = 1;		/*		 * 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;		/*		 * unsafe-gart-alias overrides the short-term fix for a		 * conflicting cache attribute bug in the kernel that is		 * exposed by advanced speculative caching in newer AMD		 * Athlon processors.  Overriding the fix will allow		 * higher performance but the kernel bug can cause system		 * lock-ups if the system uses an AGP card.  unsafe-gart-alias		 * can be turned on for higher performance in servers.		 */		else if (!memcmp(from, "unsafe-gart-alias", 17))			disable_adv_spec_cache = 0;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");	}}void __init setup_arch(char **cmdline_p){	unsigned long bootmap_size, low_mem_size;	unsigned long start_pfn, max_pfn, max_low_pfn;	int i;#ifdef CONFIG_VISWS	visws_get_board_type_and_rev();#endif 	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); 	drive_info = DRIVE_INFO; 	screen_info = SCREEN_INFO;	apm_info.bios = APM_BIOS_INFO;	if( SYS_DESC_TABLE.length != 0 ) {		MCA_bus = SYS_DESC_TABLE.table[3] &0x2;		machine_id = SYS_DESC_TABLE.table[0];		machine_submodel_id = SYS_DESC_TABLE.table[1];		BIOS_revision = SYS_DESC_TABLE.table[2];	}	aux_device_present = AUX_DEVICE_INFO;#ifdef CONFIG_BLK_DEV_RAM	rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);#endif	setup_memory_region();	if (!MOUNT_ROOT_RDONLY)		root_mountflags &= ~MS_RDONLY;	init_mm.start_code = (unsigned long) &_text;	init_mm.end_code = (unsigned long) &_etext;	init_mm.end_data = (unsigned long) &_edata;	init_mm.brk = (unsigned long) &_end;	code_resource.start = virt_to_bus(&_text);	code_resource.end = virt_to_bus(&_etext)-1;	data_resource.start = virt_to_bus(&_etext);	data_resource.end = virt_to_bus(&_edata)-1;	parse_cmdline_early(cmdline_p);#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)	/*	 * partially used pages are not usable - thus	 * we are rounding upwards:	 */	start_pfn = PFN_UP(__pa(&_end));	/*	 * Find the highest page frame number we have available	 */	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:	 */	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;

⌨️ 快捷键说明

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