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

📄 setup.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		}	}	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) &&				 (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 < chg_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)struct edd edd;#ifdef CONFIG_EDD_MODULEEXPORT_SYMBOL(edd);#endif/** * copy_edd() - Copy the BIOS EDD information *              from boot_params into a safe place. * */static inline void copy_edd(void){     memcpy(edd.mbr_signature, EDD_MBR_SIGNATURE, sizeof(edd.mbr_signature));     memcpy(edd.edd_info, EDD_BUF, sizeof(edd.edd_info));     edd.mbr_signature_nr = EDD_MBR_SIG_NR;     edd.edd_info_nr = EDD_NR;}#elsestatic inline void copy_edd(void){}#endif/* * Do NOT EVER look at the BIOS memory size location. * It does not work on many machines. */#define LOWMEMSIZE()	(0x9f000)static void __init parse_cmdline_early (char ** cmdline_p){	char c = ' ', *to = command_line, *from = saved_command_line;	int len = 0;	int userdef = 0;	/* Save unparsed command line copy for /proc/cmdline */	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';	for (;;) {		if (c != ' ')			goto next_char;		/*		 * "mem=nopentium" disables the 4MB page tables.		 * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM		 * to <mem>, overriding the bios size.		 * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from		 * <start> to <start>+<mem>, overriding the bios size.		 *		 * HPA tells me bootloaders need to parse mem=, so no new		 * option should be mem=  [also see Documentation/i386/boot.txt]		 */		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);				disable_pse = 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 mem_size; 				mem_size = memparse(from+4, &from);				limit_regions(mem_size);				userdef=1;			}		}		else if (!memcmp(from, "memmap=", 7)) {			if (to != command_line)				to--;			if (!memcmp(from+7, "exactmap", 8)) {#ifdef CONFIG_CRASH_DUMP				/* If we are doing a crash dump, we				 * still need to know the real mem				 * size before original memory map is				 * reset.				 */				find_max_pfn();				saved_max_pfn = max_pfn;#endif				from += 8+7;				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+7, &from);				if (*from == '@') {					start_at = memparse(from+1, &from);					add_memory_region(start_at, mem_size, E820_RAM);				} else if (*from == '#') {					start_at = memparse(from+1, &from);					add_memory_region(start_at, mem_size, E820_ACPI);				} else if (*from == '$') {					start_at = memparse(from+1, &from);					add_memory_region(start_at, mem_size, E820_RESERVED);				} else {					limit_regions(mem_size);					userdef=1;				}			}		}		else if (!memcmp(from, "noexec=", 7))			noexec_setup(from + 7);#ifdef  CONFIG_X86_SMP		/*		 * If the BIOS enumerates physical processors before logical,		 * maxcpus=N at enumeration-time can be used to disable HT.		 */		else if (!memcmp(from, "maxcpus=", 8)) {			extern unsigned int maxcpus;			maxcpus = simple_strtoul(from + 8, NULL, 0);		}#endif#ifdef CONFIG_ACPI		/* "acpi=off" disables both ACPI table parsing and interpreter */		else if (!memcmp(from, "acpi=off", 8)) {			disable_acpi();		}		/* acpi=force to over-ride black-list */		else if (!memcmp(from, "acpi=force", 10)) {			acpi_force = 1;			acpi_ht = 1;			acpi_disabled = 0;		}		/* acpi=strict disables out-of-spec workarounds */		else if (!memcmp(from, "acpi=strict", 11)) {			acpi_strict = 1;		}		/* Limit ACPI just to boot-time to enable HT */		else if (!memcmp(from, "acpi=ht", 7)) {			if (!acpi_force)				disable_acpi();			acpi_ht = 1;		}				/* "pci=noacpi" disable ACPI IRQ routing and PCI scan */		else if (!memcmp(from, "pci=noacpi", 10)) {			acpi_disable_pci();		}		/* "acpi=noirq" disables ACPI interrupt routing */		else if (!memcmp(from, "acpi=noirq", 10)) {			acpi_noirq_set();		}		else if (!memcmp(from, "acpi_sci=edge", 13))			acpi_sci_flags.trigger =  1;		else if (!memcmp(from, "acpi_sci=level", 14))			acpi_sci_flags.trigger = 3;		else if (!memcmp(from, "acpi_sci=high", 13))			acpi_sci_flags.polarity = 1;		else if (!memcmp(from, "acpi_sci=low", 12))			acpi_sci_flags.polarity = 3;#ifdef CONFIG_X86_IO_APIC		else if (!memcmp(from, "acpi_skip_timer_override", 24))			acpi_skip_timer_override = 1;		if (!memcmp(from, "disable_timer_pin_1", 19))			disable_timer_pin_1 = 1;		if (!memcmp(from, "enable_timer_pin_1", 18))			disable_timer_pin_1 = -1;		/* disable IO-APIC */		else if (!memcmp(from, "noapic", 6))			disable_ioapic_setup();#endif /* CONFIG_X86_IO_APIC */#endif /* CONFIG_ACPI */#ifdef CONFIG_X86_LOCAL_APIC		/* enable local APIC */		else if (!memcmp(from, "lapic", 5))			lapic_enable();		/* disable local APIC */		else if (!memcmp(from, "nolapic", 6))			lapic_disable();#endif /* CONFIG_X86_LOCAL_APIC */#ifdef CONFIG_KEXEC		/* crashkernel=size@addr specifies the location to reserve for		 * a crash kernel.  By reserving this memory we guarantee		 * that linux never set's it up as a DMA target.		 * Useful for holding code to do something appropriate		 * after a kernel panic.		 */		else if (!memcmp(from, "crashkernel=", 12)) {			unsigned long size, base;			size = memparse(from+12, &from);			if (*from == '@') {				base = memparse(from+1, &from);				/* FIXME: Do I want a sanity check				 * to validate the memory range?				 */				crashk_res.start = base;				crashk_res.end   = base + size - 1;			}		}#endif#ifdef CONFIG_CRASH_DUMP		/* elfcorehdr= specifies the location of elf core header		 * stored by the crashed kernel.		 */		else if (!memcmp(from, "elfcorehdr=", 11))			elfcorehdr_addr = memparse(from+11, &from);#endif		/*		 * 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;			/*		 * vmalloc=size forces the vmalloc area to be exactly 'size'		 * bytes. This can be used to increase (or decrease) the		 * vmalloc area - the default is 128m.		 */		else if (!memcmp(from, "vmalloc=", 8))			__VMALLOC_RESERVE = memparse(from+8, &from);	next_char:		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");	}}/* * Callback for efi_memory_walk. */static int __initefi_find_max_pfn(unsigned long start, unsigned long end, void *arg){	unsigned long *max_pfn = arg, pfn;	if (start < end) {		pfn = PFN_UP(end -1);		if (pfn > *max_pfn)			*max_pfn = pfn;	}	return 0;}/* * Find the highest page frame number we have available */void __init find_max_pfn(void){	int i;	max_pfn = 0;	if (efi_enabled) {		efi_memmap_walk(efi_find_max_pfn, &max_pfn);		return;	}	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: */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");		max_pfn = MAXMEM_PFN;#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;#ifdef 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;}/* * Free all available memory for boot time allocation.  Used * as a callback function by efi_memory_walk() */static int __initfree_available_memory(unsigned long start, unsigned long end, void *arg){	/* check max_low_pfn */	if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))		return 0;	if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))		end = (max_low_pfn + 1) << PAGE_SHIFT;	if (start < end)		free_bootmem(start, end - start);	return 0;}/* * Register fully available low RAM pages with the bootmem allocator. */static void __init register_bootmem_low_pages(unsigned long max_low_pfn){	int i;	if (efi_enabled) {		efi_memmap_walk(free_available_memory, NULL);		return;	}	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);

⌨️ 快捷键说明

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