diff options
author | Matt Tolentino <metolent@snoqualmie.dp.intel.com> | 2005-09-03 18:56:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:06:09 -0400 |
commit | 7ae65fd334232468a9d6b523a4fc141cd6ec5ea4 (patch) | |
tree | cbc63abb55033d88f9a631741603a2a379bebee2 /arch/i386 | |
parent | 4116c527ea9517623369a5b3b037aedde280d672 (diff) |
[PATCH] x86: fix EFI memory map parsing
The memory descriptors that comprise the EFI memory map are not fixed in
stone such that the size could change in the future. This uses the memory
descriptor size obtained from EFI to iterate over the memory map entries
during boot. This enables the removal of an x86 specific pad (and ifdef)
in the EFI header. I also couldn't stomach the broken up nature of the
function to put EFI runtime calls into virtual mode any longer so I fixed
that up a bit as well.
For reference, this patch only impacts x86.
Signed-off-by: Matt Tolentino <matthew.e.tolentino@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/kernel/efi.c | 101 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 14 | ||||
-rw-r--r-- | arch/i386/mm/init.c | 5 |
3 files changed, 62 insertions, 58 deletions
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c index 385883ea8c19..850648ae8305 100644 --- a/arch/i386/kernel/efi.c +++ b/arch/i386/kernel/efi.c | |||
@@ -233,22 +233,23 @@ void __init efi_map_memmap(void) | |||
233 | { | 233 | { |
234 | memmap.map = NULL; | 234 | memmap.map = NULL; |
235 | 235 | ||
236 | memmap.map = (efi_memory_desc_t *) | 236 | memmap.map = bt_ioremap((unsigned long) memmap.phys_map, |
237 | bt_ioremap((unsigned long) memmap.phys_map, | 237 | (memmap.nr_map * memmap.desc_size)); |
238 | (memmap.nr_map * sizeof(efi_memory_desc_t))); | ||
239 | |||
240 | if (memmap.map == NULL) | 238 | if (memmap.map == NULL) |
241 | printk(KERN_ERR PFX "Could not remap the EFI memmap!\n"); | 239 | printk(KERN_ERR PFX "Could not remap the EFI memmap!\n"); |
240 | |||
241 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); | ||
242 | } | 242 | } |
243 | 243 | ||
244 | #if EFI_DEBUG | 244 | #if EFI_DEBUG |
245 | static void __init print_efi_memmap(void) | 245 | static void __init print_efi_memmap(void) |
246 | { | 246 | { |
247 | efi_memory_desc_t *md; | 247 | efi_memory_desc_t *md; |
248 | void *p; | ||
248 | int i; | 249 | int i; |
249 | 250 | ||
250 | for (i = 0; i < memmap.nr_map; i++) { | 251 | for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) { |
251 | md = &memmap.map[i]; | 252 | md = p; |
252 | printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, " | 253 | printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, " |
253 | "range=[0x%016llx-0x%016llx) (%lluMB)\n", | 254 | "range=[0x%016llx-0x%016llx) (%lluMB)\n", |
254 | i, md->type, md->attribute, md->phys_addr, | 255 | i, md->type, md->attribute, md->phys_addr, |
@@ -271,10 +272,10 @@ void efi_memmap_walk(efi_freemem_callback_t callback, void *arg) | |||
271 | } prev, curr; | 272 | } prev, curr; |
272 | efi_memory_desc_t *md; | 273 | efi_memory_desc_t *md; |
273 | unsigned long start, end; | 274 | unsigned long start, end; |
274 | int i; | 275 | void *p; |
275 | 276 | ||
276 | for (i = 0; i < memmap.nr_map; i++) { | 277 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
277 | md = &memmap.map[i]; | 278 | md = p; |
278 | 279 | ||
279 | if ((md->num_pages == 0) || (!is_available_memory(md))) | 280 | if ((md->num_pages == 0) || (!is_available_memory(md))) |
280 | continue; | 281 | continue; |
@@ -325,6 +326,7 @@ void __init efi_init(void) | |||
325 | memmap.phys_map = EFI_MEMMAP; | 326 | memmap.phys_map = EFI_MEMMAP; |
326 | memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE; | 327 | memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE; |
327 | memmap.desc_version = EFI_MEMDESC_VERSION; | 328 | memmap.desc_version = EFI_MEMDESC_VERSION; |
329 | memmap.desc_size = EFI_MEMDESC_SIZE; | ||
328 | 330 | ||
329 | efi.systab = (efi_system_table_t *) | 331 | efi.systab = (efi_system_table_t *) |
330 | boot_ioremap((unsigned long) efi_phys.systab, | 332 | boot_ioremap((unsigned long) efi_phys.systab, |
@@ -428,22 +430,30 @@ void __init efi_init(void) | |||
428 | printk(KERN_ERR PFX "Could not map the runtime service table!\n"); | 430 | printk(KERN_ERR PFX "Could not map the runtime service table!\n"); |
429 | 431 | ||
430 | /* Map the EFI memory map for use until paging_init() */ | 432 | /* Map the EFI memory map for use until paging_init() */ |
431 | 433 | memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE); | |
432 | memmap.map = (efi_memory_desc_t *) | ||
433 | boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE); | ||
434 | |||
435 | if (memmap.map == NULL) | 434 | if (memmap.map == NULL) |
436 | printk(KERN_ERR PFX "Could not map the EFI memory map!\n"); | 435 | printk(KERN_ERR PFX "Could not map the EFI memory map!\n"); |
437 | 436 | ||
438 | if (EFI_MEMDESC_SIZE != sizeof(efi_memory_desc_t)) { | 437 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); |
439 | printk(KERN_WARNING PFX "Warning! Kernel-defined memdesc doesn't " | 438 | |
440 | "match the one from EFI!\n"); | ||
441 | } | ||
442 | #if EFI_DEBUG | 439 | #if EFI_DEBUG |
443 | print_efi_memmap(); | 440 | print_efi_memmap(); |
444 | #endif | 441 | #endif |
445 | } | 442 | } |
446 | 443 | ||
444 | static inline void __init check_range_for_systab(efi_memory_desc_t *md) | ||
445 | { | ||
446 | if (((unsigned long)md->phys_addr <= (unsigned long)efi_phys.systab) && | ||
447 | ((unsigned long)efi_phys.systab < md->phys_addr + | ||
448 | ((unsigned long)md->num_pages << EFI_PAGE_SHIFT))) { | ||
449 | unsigned long addr; | ||
450 | |||
451 | addr = md->virt_addr - md->phys_addr + | ||
452 | (unsigned long)efi_phys.systab; | ||
453 | efi.systab = (efi_system_table_t *)addr; | ||
454 | } | ||
455 | } | ||
456 | |||
447 | /* | 457 | /* |
448 | * This function will switch the EFI runtime services to virtual mode. | 458 | * This function will switch the EFI runtime services to virtual mode. |
449 | * Essentially, look through the EFI memmap and map every region that | 459 | * Essentially, look through the EFI memmap and map every region that |
@@ -457,43 +467,32 @@ void __init efi_enter_virtual_mode(void) | |||
457 | { | 467 | { |
458 | efi_memory_desc_t *md; | 468 | efi_memory_desc_t *md; |
459 | efi_status_t status; | 469 | efi_status_t status; |
460 | int i; | 470 | void *p; |
461 | 471 | ||
462 | efi.systab = NULL; | 472 | efi.systab = NULL; |
463 | 473 | ||
464 | for (i = 0; i < memmap.nr_map; i++) { | 474 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
465 | md = &memmap.map[i]; | 475 | md = p; |
466 | 476 | ||
467 | if (md->attribute & EFI_MEMORY_RUNTIME) { | 477 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) |
468 | md->virt_addr = | 478 | continue; |
469 | (unsigned long)ioremap(md->phys_addr, | ||
470 | md->num_pages << EFI_PAGE_SHIFT); | ||
471 | if (!(unsigned long)md->virt_addr) { | ||
472 | printk(KERN_ERR PFX "ioremap of 0x%lX failed\n", | ||
473 | (unsigned long)md->phys_addr); | ||
474 | } | ||
475 | 479 | ||
476 | if (((unsigned long)md->phys_addr <= | 480 | md->virt_addr = (unsigned long)ioremap(md->phys_addr, |
477 | (unsigned long)efi_phys.systab) && | 481 | md->num_pages << EFI_PAGE_SHIFT); |
478 | ((unsigned long)efi_phys.systab < | 482 | if (!(unsigned long)md->virt_addr) { |
479 | md->phys_addr + | 483 | printk(KERN_ERR PFX "ioremap of 0x%lX failed\n", |
480 | ((unsigned long)md->num_pages << | 484 | (unsigned long)md->phys_addr); |
481 | EFI_PAGE_SHIFT))) { | ||
482 | unsigned long addr; | ||
483 | |||
484 | addr = md->virt_addr - md->phys_addr + | ||
485 | (unsigned long)efi_phys.systab; | ||
486 | efi.systab = (efi_system_table_t *)addr; | ||
487 | } | ||
488 | } | 485 | } |
486 | /* update the virtual address of the EFI system table */ | ||
487 | check_range_for_systab(md); | ||
489 | } | 488 | } |
490 | 489 | ||
491 | if (!efi.systab) | 490 | if (!efi.systab) |
492 | BUG(); | 491 | BUG(); |
493 | 492 | ||
494 | status = phys_efi_set_virtual_address_map( | 493 | status = phys_efi_set_virtual_address_map( |
495 | sizeof(efi_memory_desc_t) * memmap.nr_map, | 494 | memmap.desc_size * memmap.nr_map, |
496 | sizeof(efi_memory_desc_t), | 495 | memmap.desc_size, |
497 | memmap.desc_version, | 496 | memmap.desc_version, |
498 | memmap.phys_map); | 497 | memmap.phys_map); |
499 | 498 | ||
@@ -533,10 +532,10 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
533 | { | 532 | { |
534 | struct resource *res; | 533 | struct resource *res; |
535 | efi_memory_desc_t *md; | 534 | efi_memory_desc_t *md; |
536 | int i; | 535 | void *p; |
537 | 536 | ||
538 | for (i = 0; i < memmap.nr_map; i++) { | 537 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
539 | md = &memmap.map[i]; | 538 | md = p; |
540 | 539 | ||
541 | if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) > | 540 | if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) > |
542 | 0x100000000ULL) | 541 | 0x100000000ULL) |
@@ -613,10 +612,10 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
613 | u32 efi_mem_type(unsigned long phys_addr) | 612 | u32 efi_mem_type(unsigned long phys_addr) |
614 | { | 613 | { |
615 | efi_memory_desc_t *md; | 614 | efi_memory_desc_t *md; |
616 | int i; | 615 | void *p; |
617 | 616 | ||
618 | for (i = 0; i < memmap.nr_map; i++) { | 617 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
619 | md = &memmap.map[i]; | 618 | md = p; |
620 | if ((md->phys_addr <= phys_addr) && (phys_addr < | 619 | if ((md->phys_addr <= phys_addr) && (phys_addr < |
621 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) | 620 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) |
622 | return md->type; | 621 | return md->type; |
@@ -627,10 +626,10 @@ u32 efi_mem_type(unsigned long phys_addr) | |||
627 | u64 efi_mem_attributes(unsigned long phys_addr) | 626 | u64 efi_mem_attributes(unsigned long phys_addr) |
628 | { | 627 | { |
629 | efi_memory_desc_t *md; | 628 | efi_memory_desc_t *md; |
630 | int i; | 629 | void *p; |
631 | 630 | ||
632 | for (i = 0; i < memmap.nr_map; i++) { | 631 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
633 | md = &memmap.map[i]; | 632 | md = p; |
634 | if ((md->phys_addr <= phys_addr) && (phys_addr < | 633 | if ((md->phys_addr <= phys_addr) && (phys_addr < |
635 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) | 634 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) |
636 | return md->attribute; | 635 | return md->attribute; |
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index af4de58cab54..9adbf710ec8d 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -370,12 +370,16 @@ static void __init limit_regions(unsigned long long size) | |||
370 | int i; | 370 | int i; |
371 | 371 | ||
372 | if (efi_enabled) { | 372 | if (efi_enabled) { |
373 | for (i = 0; i < memmap.nr_map; i++) { | 373 | efi_memory_desc_t *md; |
374 | current_addr = memmap.map[i].phys_addr + | 374 | void *p; |
375 | (memmap.map[i].num_pages << 12); | 375 | |
376 | if (memmap.map[i].type == EFI_CONVENTIONAL_MEMORY) { | 376 | for (p = memmap.map, i = 0; p < memmap.map_end; |
377 | p += memmap.desc_size, i++) { | ||
378 | md = p; | ||
379 | current_addr = md->phys_addr + (md->num_pages << 12); | ||
380 | if (md->type == EFI_CONVENTIONAL_MEMORY) { | ||
377 | if (current_addr >= size) { | 381 | if (current_addr >= size) { |
378 | memmap.map[i].num_pages -= | 382 | md->num_pages -= |
379 | (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT); | 383 | (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT); |
380 | memmap.nr_map = i + 1; | 384 | memmap.nr_map = i + 1; |
381 | return; | 385 | return; |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 12216b52e28b..d8b23ab76533 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
@@ -198,9 +198,10 @@ int page_is_ram(unsigned long pagenr) | |||
198 | 198 | ||
199 | if (efi_enabled) { | 199 | if (efi_enabled) { |
200 | efi_memory_desc_t *md; | 200 | efi_memory_desc_t *md; |
201 | void *p; | ||
201 | 202 | ||
202 | for (i = 0; i < memmap.nr_map; i++) { | 203 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
203 | md = &memmap.map[i]; | 204 | md = p; |
204 | if (!is_available_memory(md)) | 205 | if (!is_available_memory(md)) |
205 | continue; | 206 | continue; |
206 | addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT; | 207 | addr = (md->phys_addr+PAGE_SIZE-1) >> PAGE_SHIFT; |