e820.c
来自「linux-2.4.29操作系统的源码」· C语言 代码 · 共 609 行 · 第 1/2 页
C
609 行
____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 start = biosmap->addr; unsigned long size = biosmap->size; unsigned 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. * * This should be removed on Hammer which is supposed to not * have non e820 covered ISA mappings there, but I had some strange * problems so it stays for now. -AK */ 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;}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"); e820_print_map(who);}extern char command_line[], saved_command_line[];extern int fallback_aper_order;extern int iommu_setup(char *opt);void __init parse_mem_cmdline (char ** cmdline_p){ char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 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 next; /* * mem=XXX[kKmM] limits kernel memory to XXX+1MB * * It would be more logical to count from 0 instead of from * HIGH_MEMORY, but we keep that for now for i386 compatibility. -AK */ if (!memcmp(from, "mem=", 4)) { /* * No support for custom mapping like i386. * The reason is that we need to read the e820 map * anyways to handle the ACPI mappings in the * direct map. * Also on x86-64 there should be always a good e820 * map. This is only an upper limit, you cannot force * usage of memory not in e820. */ end_user_pfn = memparse(from+4, &from) + HIGH_MEMORY; end_user_pfn >>= PAGE_SHIFT; }#ifdef CONFIG_GART_IOMMU else if (!memcmp(from,"iommu=",6)) { iommu_setup(from+6); } #endif#ifdef CONFIG_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 max_cpus; max_cpus = simple_strtoul(from + 8, NULL, 0); }#endif#ifdef CONFIG_ACPI_BOOT else if (!memcmp(from, "acpi=off", 8)) disable_acpi(); /* acpi=strict disables out-of-spec workarounds */ else if (!memcmp(from, "acpi=strict", 11)) { acpi_strict = 1; } else if (!memcmp(from, "pci=noacpi", 10)) acpi_disable_pci(); 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;#endif else if (!memcmp(from,"maxcpus=0",9)) { disable_ioapic_setup(); apic_disabled = 1; } else if (!memcmp(from, "noapic", 6)) disable_ioapic_setup(); else if (!memcmp(from, "nolocalapic", 11) || !memcmp(from,"nolapic",7)) apic_disabled = 1; else if (!memcmp(from,"apic",4)) { extern int ioapic_force; ioapic_force = 1; skip_ioapic_setup = 0; } next: c = *(from++); if (!c) break; if (COMMAND_LINE_SIZE <= ++len) break; *(to++) = c; } *to = '\0'; *cmdline_p = command_line;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?