setup.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 2,464 行 · 第 1/5 页

C
2,464
字号
	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 */static void __init parse_mem_cmdline (char ** cmdline_p){	char c = ' ', *to = command_line, *from = COMMAND_LINE;	int len = 0;	int usermem = 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 (;;) {		/*		 * "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 (c == ' ' && !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;				usermem = 1;			} else {				/* If the user specifies memory size, we				 * blow away any automatically generated				 * size				 */				unsigned long long start_at, mem_size; 				if (usermem == 0) {					/* first time in: zap the whitelist					 * and reinitialize it with the					 * standard low-memory region.					 */					e820.nr_map = 0;					usermem = 1;					add_memory_region(0, LOWMEMSIZE(), E820_RAM);				}				mem_size = memparse(from+4, &from);				if (*from == '@')					start_at = memparse(from+1, &from);				else {					start_at = HIGH_MEMORY;					mem_size -= HIGH_MEMORY;					usermem=0;				}				add_memory_region(start_at, mem_size, E820_RAM);			}		}		/*		 * 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.		 */		if (c == ' ' && !memcmp(from, "highmem=", 8))			highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;			c = *(from++);		if (!c)			break;		if (COMMAND_LINE_SIZE <= ++len)			break;		*(to++) = c;	}	*to = '\0';	*cmdline_p = command_line;	if (usermem) {		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_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_phys(&_text);	code_resource.end = virt_to_phys(&_etext)-1;	data_resource.start = virt_to_phys(&_etext);	data_resource.end = virt_to_phys(&_edata)-1;	parse_mem_cmdline(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");		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;#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	}#ifdef CONFIG_HIGHMEM	highstart_pfn = highend_pfn = max_pfn;	if (max_pfn > max_low_pfn) {		highstart_pfn = max_low_pfn;	}	printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",		pages_to_mb(highend_pfn - highstart_pfn));#endif	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",			pages_to_mb(max_low_pfn));	/*	 * Initialize the boot-time allocator (with low memory only):	 */	bootmap_size = init_bootmem(start_pfn, max_low_pfn);	/*	 * Register fully available low RAM pages with the bootmem allocator.	 */	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));	}	/*	 * Reserve the bootmem bitmap itself as well. We do this in two	 * steps (first step was init_bootmem()) because this catches	 * the (very unlikely) case of us accidentally initializing the	 * bootmem allocator with an invalid RAM area.	 */	reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +			 bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));	/*	 * reserve physical page 0 - it's a special BIOS page on many boxes,	 * enabling clean reboots, SMP operation, laptop functions.	 */	reserve_bootmem(0, PAGE_SIZE);#ifdef CONFIG_SMP	/*	 * But first pinch a few for the stack/trampoline stuff	 * FIXME: Don't need the extra page at 4K, but need to fix	 * trampoline before removing it. (see the GDT stuff)	 */	reserve_bootmem(PAGE_SIZE, PAGE_SIZE);#endif#ifdef CONFIG_ACPI_SLEEP	/*	 * Reserve low memory region for sleep support.	 */	acpi_reserve_bootmem();#endif#ifdef CONFIG_X86_LOCAL_APIC	/*	 * Find and reserve possible boot-time SMP configuration:	 */	find_smp_config();#endif#ifdef CONFIG_BLK_DEV_INITRD	if (LOADER_TYPE && INITRD_START) {		if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {			reserve_bootmem(INITRD_START, INITRD_SIZE);			initrd_start =				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;			initrd_end = initrd_start+INITRD_SIZE;		}		else {			printk(KERN_ERR "initrd extends beyond end of memory "			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",			    INITRD_START + INITRD_SIZE,			    max_low_pfn << PAGE_SHIFT);			initrd_start = 0;		}	}#endif	/*	 * NOTE: before this point _nobody_ is allowed to allocate	 * any memory using the bootmem allocator.	 */#ifdef CONFIG_SMP	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/#endif	paging_init();#ifdef CONFIG_ACPI_BOOT	/*	 * Initialize the ACPI boot-time table parser (gets the RSDP and SDT).	 * Must do this after paging_init (due to reliance on fixmap, and thus	 * the bootmem allocator) but before get_smp_config (to allow parsing	 * of MADT).	 */	acpi_boot_init(*cmdline_p);#endif#ifdef CONFIG_X86_LOCAL_APIC	/*	 * get boot-time SMP configuration:	 */	if (smp_found_config)		get_smp_config();#endif	/*	 * Request address space for all standard RAM and ROM resources	 * and also for regions reported as reserved by the e820.	 */	probe_roms();	for (i = 0; i < e820.nr_map; i++) {		struct resource *res;		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)			continue;		res = alloc_bootmem_low(sizeof(struct resource));		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;		request_resource(&iomem_resource, res);		if (e820.map[i].type == E820_RAM) {			/*			 *  We dont'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(&iomem_resource, &vram_resource);	/* request I/O space for devices used on all i[345]86 PCs */	for (i = 0; i < STANDARD_IO_RESOURCES; i++)		request_resource(&ioport_resource, standard_io_resources+i);	/* Tell the PCI layer not to allocate too close to the RAM area.. */	low_mem_size = ((max_low_pfn << PAGE_SHIFT) + 0xfffff) & ~0xfffff;	if (low_mem_size > pci_mem_start)		pci_mem_start = low_mem_size;#ifdef CONFIG_VT#if defined(CONFIG_VGA_CONSOLE)	conswitchp = &vga_con;#elif defined(CONFIG_DUMMY_CONSOLE)	conswitchp = &dummy_con;#endif#endif	dmi_scan_machine();}static int cachesize_override __initdata = -1;static int __init cachesize_setup(char *str){	get_option (&str, &cachesize_override);	return 1;}__setup("cachesize=", cachesize_setup);

⌨️ 快捷键说明

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