aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Tolentino <metolent@snoqualmie.dp.intel.com>2005-09-03 18:56:27 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:06:09 -0400
commit7ae65fd334232468a9d6b523a4fc141cd6ec5ea4 (patch)
treecbc63abb55033d88f9a631741603a2a379bebee2
parent4116c527ea9517623369a5b3b037aedde280d672 (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>
-rw-r--r--arch/i386/kernel/efi.c101
-rw-r--r--arch/i386/kernel/setup.c14
-rw-r--r--arch/i386/mm/init.c5
-rw-r--r--include/asm-i386/setup.h2
-rw-r--r--include/linux/efi.h14
5 files changed, 67 insertions, 69 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
245static void __init print_efi_memmap(void) 245static 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
444static 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,
613u32 efi_mem_type(unsigned long phys_addr) 612u32 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)
627u64 efi_mem_attributes(unsigned long phys_addr) 626u64 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;
diff --git a/include/asm-i386/setup.h b/include/asm-i386/setup.h
index 7a32184d54bf..826a8ca50ac8 100644
--- a/include/asm-i386/setup.h
+++ b/include/asm-i386/setup.h
@@ -44,7 +44,7 @@ extern unsigned char boot_params[PARAM_SIZE];
44#define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4))) 44#define EFI_SYSTAB ((efi_system_table_t *) *((unsigned long *)(PARAM+0x1c4)))
45#define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8))) 45#define EFI_MEMDESC_SIZE (*((unsigned long *) (PARAM+0x1c8)))
46#define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc))) 46#define EFI_MEMDESC_VERSION (*((unsigned long *) (PARAM+0x1cc)))
47#define EFI_MEMMAP ((efi_memory_desc_t *) *((unsigned long *)(PARAM+0x1d0))) 47#define EFI_MEMMAP ((void *) *((unsigned long *)(PARAM+0x1d0)))
48#define EFI_MEMMAP_SIZE (*((unsigned long *) (PARAM+0x1d4))) 48#define EFI_MEMMAP_SIZE (*((unsigned long *) (PARAM+0x1d4)))
49#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2)) 49#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
50#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8)) 50#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 73781ec165b4..c7c5dd316182 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -91,11 +91,6 @@ typedef struct {
91 91
92#define EFI_PAGE_SHIFT 12 92#define EFI_PAGE_SHIFT 12
93 93
94/*
95 * For current x86 implementations of EFI, there is
96 * additional padding in the mem descriptors. This is not
97 * the case in ia64. Need to have this fixed in the f/w.
98 */
99typedef struct { 94typedef struct {
100 u32 type; 95 u32 type;
101 u32 pad; 96 u32 pad;
@@ -103,9 +98,6 @@ typedef struct {
103 u64 virt_addr; 98 u64 virt_addr;
104 u64 num_pages; 99 u64 num_pages;
105 u64 attribute; 100 u64 attribute;
106#if defined (__i386__)
107 u64 pad1;
108#endif
109} efi_memory_desc_t; 101} efi_memory_desc_t;
110 102
111typedef int (*efi_freemem_callback_t) (unsigned long start, unsigned long end, void *arg); 103typedef int (*efi_freemem_callback_t) (unsigned long start, unsigned long end, void *arg);
@@ -240,10 +232,12 @@ typedef struct {
240} efi_system_table_t; 232} efi_system_table_t;
241 233
242struct efi_memory_map { 234struct efi_memory_map {
243 efi_memory_desc_t *phys_map; 235 void *phys_map;
244 efi_memory_desc_t *map; 236 void *map;
237 void *map_end;
245 int nr_map; 238 int nr_map;
246 unsigned long desc_version; 239 unsigned long desc_version;
240 unsigned long desc_size;
247}; 241};
248 242
249/* 243/*