[PATCH 2.6.21 2/3] x86_64: EFI64 support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



EFI x86_64 support Patch 2 of 3
-------------------------------
The patch depends on EFI x86_64 patch 1/3.

EFI initialization and memory map set up are done. It should be noted
that support for user-defined memory is not yet implemented. Time
and reboot services go through the EFI service call for x86_64.

Signed-off-by: Chandramouli Narayanan <[email protected]>

diff -uprN -X linux-2.6.21rc7-git2-orig/Documentation/dontdiff linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/e820.c linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/e820.c
--- linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/e820.c	2007-04-19 12:39:39.000000000 -0700
+++ linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/e820.c	2007-04-19 13:01:02.000000000 -0700
@@ -17,6 +17,7 @@
 #include <linux/kexec.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/efi.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -97,11 +98,40 @@ static inline int bad_addr(unsigned long
 /*
  * This function checks if any part of the range <start,end> is mapped
  * with type.
+ * FIXME: here only handle E820_RAM and 0 memory type condition
  */
 int __meminit
 e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
 { 
 	int i;
+	if (efi_enabled) {
+		efi_memory_desc_t *md;
+		void *p;
+		unsigned long map_start, map_end;
+
+		for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+			md = p;
+			map_start = md->phys_addr;
+			map_end = map_start + (md->num_pages << EFI_PAGE_SHIFT);
+			if (type == E820_RAM) {
+				switch (md->type) {
+				case EFI_CONVENTIONAL_MEMORY:
+				case EFI_BOOT_SERVICES_DATA:
+				case EFI_BOOT_SERVICES_CODE:
+				case EFI_LOADER_DATA:
+				case EFI_LOADER_CODE:
+					if (map_start >= end || map_end <= start)
+						continue;
+					return 1;
+					break;
+				default:
+					continue;
+				}
+			}
+		}
+		return 0;
+	}
+
 	for (i = 0; i < e820.nr_map; i++) { 
 		struct e820entry *ei = &e820.map[i]; 
 		if (type && ei->type != type) 
@@ -148,6 +178,29 @@ int __init e820_all_mapped(unsigned long
 unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsigned size) 
 { 
 	int i; 
+	if (efi_enabled) {
+		efi_memory_desc_t *md;
+		void *p;
+		unsigned long map_start, map_end, last;
+		for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+			md = p;
+			if (md->type != EFI_CONVENTIONAL_MEMORY)
+				continue;
+			map_start = md->phys_addr;
+			map_end = map_start + (md->num_pages << EFI_PAGE_SHIFT);
+			if (map_start < start)
+				map_start = start;
+			if (map_start > map_end)
+				continue;
+			while (bad_addr(&map_start, size) && map_start+size <= map_end)
+				;
+			last = PAGE_ALIGN(map_start) + size;
+			if (last > map_end || last > end)
+				continue;
+			return map_start;
+		}
+		return -1UL;		
+	}
 	for (i = 0; i < e820.nr_map; i++) { 
 		struct e820entry *ei = &e820.map[i]; 
 		unsigned long addr = ei->addr, last; 
@@ -186,7 +239,7 @@ unsigned long __init e820_end_of_ram(voi
 	if (end_pfn > end_pfn_map) 
 		end_pfn = end_pfn_map; 
 
-	printk("end_pfn_map = %lu\n", end_pfn_map);
+	printk("e820_end_of_ram: end_pfn_map = %lu\n", end_pfn_map);
 	return end_pfn;	
 }
 
@@ -309,6 +362,28 @@ e820_register_active_regions(int nid, un
 {
 	int i;
 	unsigned long ei_startpfn, ei_endpfn;
+	if (efi_enabled) {
+		efi_memory_desc_t *md;
+		void *p;
+		for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
+			md = p;
+			/* add runtime date & runtime service to memory space */
+			if (md->type >= EFI_MEMORY_MAPPED_IO)
+				continue;
+			ei_startpfn = md->phys_addr >> PAGE_SHIFT;
+			ei_endpfn = ei_startpfn + md->num_pages;
+			if (ei_endpfn > end_pfn_map)
+				end_pfn_map = ei_endpfn;
+			/* Obey end_user_pfn to save on memmap */
+			if (ei_startpfn >= end_user_pfn)
+				continue;
+			if (ei_endpfn > end_user_pfn)
+				ei_endpfn = end_user_pfn;
+			add_active_range(nid, ei_startpfn, ei_endpfn);
+		}
+		return;
+	}
+
 	for (i = 0; i < e820.nr_map; i++) {
 		struct e820entry *ei = &e820.map[i];
 		ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
@@ -595,6 +670,11 @@ void early_panic(char *msg)
 
 void __init setup_memory_region(void)
 {
+	if (efi_enabled) {
+		efi_init();
+		return;
+	}
+	
 	/*
 	 * Try to copy the BIOS-supplied E820-map.
 	 *
@@ -664,7 +744,7 @@ early_param("memmap", parse_memmap_opt);
 
 void __init finish_e820_parsing(void)
 {
-	if (userdef) {
+	if (userdef && !efi_enabled) {
 		printk(KERN_INFO "user-defined physical RAM map:\n");
 		e820_print_map("user");
 	}
@@ -685,15 +765,31 @@ __init void e820_setup_gap(void)
 	unsigned long last;
 	int i;
 	int found = 0;
+	efi_memory_desc_t *md;
+	void *p;
 
 	last = 0x100000000ull;
 	gapstart = 0x10000000;
 	gapsize = 0x400000;
-	i = e820.nr_map;
+	if (efi_enabled) {
+		i = memmap.nr_map;
+		p = (void *)memmap.map + i * memmap.desc_size;
+	}
+	else
+		i = e820.nr_map;
 	while (--i >= 0) {
-		unsigned long long start = e820.map[i].addr;
-		unsigned long long end = start + e820.map[i].size;
-
+		unsigned long start;
+		unsigned long end;
+		if (efi_enabled) {
+			p -= memmap.desc_size;
+			md = p;
+			start = md->phys_addr;
+			end = start + (md->num_pages << EFI_PAGE_SHIFT);
+		} else {
+			start = e820.map[i].addr;
+			end = start + e820.map[i].size;
+		}
+		
 		/*
 		 * Since "last" is at most 4GB, we know we'll
 		 * fit in 32 bits if this condition is true
diff -uprN -X linux-2.6.21rc7-git2-orig/Documentation/dontdiff linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/reboot.c linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/reboot.c
--- linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/reboot.c	2007-02-04 10:44:54.000000000 -0800
+++ linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/reboot.c	2007-04-19 13:01:02.000000000 -0700
@@ -7,6 +7,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/pm.h>
+#include <linux/efi.h>
 #include <asm/io.h>
 #include <asm/kdebug.h>
 #include <asm/delay.h>
@@ -116,9 +117,15 @@ void machine_emergency_restart(void)
 {
 	int i;
 
+	/* If EFI enabled, reset system through EFI protocol. */
+	if (efi_enabled) {
+		efi.reset_system(EFI_RESET_WARM, EFI_SUCCESS, 0, NULL);
+		return;
+	}
+
 	/* Tell the BIOS if we want cold or warm reboot */
 	*((unsigned short *)__va(0x472)) = reboot_mode;
-       
+
 	for (;;) {
 		/* Could also try the reset bit in the Hammer NB */
 		switch (reboot_type) { 
diff -uprN -X linux-2.6.21rc7-git2-orig/Documentation/dontdiff linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/setup.c linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/setup.c
--- linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/setup.c	2007-04-19 12:39:39.000000000 -0700
+++ linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/setup.c	2007-04-19 13:01:02.000000000 -0700
@@ -44,6 +44,7 @@
 #include <linux/dmi.h>
 #include <linux/dma-mapping.h>
 #include <linux/ctype.h>
+#include <linux/efi.h>
 
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
@@ -69,6 +70,10 @@
  * Machine setup..
  */
 
+#ifdef CONFIG_EFI
+int efi_enabled = 0;
+EXPORT_SYMBOL(efi_enabled);
+#endif
 struct cpuinfo_x86 boot_cpu_data __read_mostly;
 EXPORT_SYMBOL(boot_cpu_data);
 
@@ -234,6 +239,10 @@ void __init setup_arch(char **cmdline_p)
 	rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
 	rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
+#ifdef CONFIG_EFI
+	if (!strncmp(EFI_LOADER_SIG, "EFIL", 4))
+		efi_enabled = 1;
+#endif
 	setup_memory_region();
 	copy_edd();
 
@@ -271,6 +280,8 @@ void __init setup_arch(char **cmdline_p)
 	discover_ebda();
 
 	init_memory_mapping(0, (end_pfn_map << PAGE_SHIFT));
+	if (efi_enabled)
+		efi_map_memmap();
 
 	dmi_scan_machine();
 
@@ -373,6 +384,8 @@ void __init setup_arch(char **cmdline_p)
 	}
 #endif
 
+	if (efi_enabled)
+		reserve_efi_runtime();
 	paging_init();
 
 #ifdef CONFIG_PCI
@@ -404,8 +417,12 @@ void __init setup_arch(char **cmdline_p)
 	/*
 	 * We trust e820 completely. No explicit ROM probing in memory.
  	 */
-	e820_reserve_resources(); 
-	e820_mark_nosave_regions();
+	if (efi_enabled)
+		efi_initialize_iomem_resources(&code_resource, &data_resource);
+	else {
+		e820_reserve_resources(); 
+		e820_mark_nosave_regions();
+	}
 
 	{
 	unsigned i;
@@ -418,7 +435,8 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
-	conswitchp = &vga_con;
+	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+		conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
 #endif
diff -uprN -X linux-2.6.21rc7-git2-orig/Documentation/dontdiff linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/time.c linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/time.c
--- linux-2.6.21rc7-git2-orig/arch/x86_64/kernel/time.c	2007-04-19 12:39:39.000000000 -0700
+++ linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/kernel/time.c	2007-04-19 13:01:02.000000000 -0700
@@ -27,6 +27,7 @@
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/kallsyms.h>
+#include <linux/efi.h>
 #include <linux/acpi.h>
 #ifdef CONFIG_ACPI
 #include <acpi/achware.h>	/* for PM timer frequency */
@@ -92,6 +93,11 @@ static void set_rtc_mmss(unsigned long n
  */
 
 	spin_lock(&rtc_lock);
+	if (efi_enabled) {
+		efi_set_rtc_mmss(nowtime);
+		spin_unlock(&rtc_lock);
+		return;
+	}
 
 /*
  * Tell the clock it's being set and stop it.
@@ -204,10 +210,15 @@ static irqreturn_t timer_interrupt(int i
 static unsigned long get_cmos_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
-	unsigned long flags;
+	unsigned long flags, retval;
 	unsigned century = 0;
 
 	spin_lock_irqsave(&rtc_lock, flags);
+	if (efi_enabled) {
+		retval = efi_get_time();
+		spin_unlock_irqrestore(&rtc_lock, flags);
+		return retval;
+	}
 
 	do {
 		sec = CMOS_READ(RTC_SECONDS);
diff -uprN -X linux-2.6.21rc7-git2-orig/Documentation/dontdiff linux-2.6.21rc7-git2-orig/arch/x86_64/mm/init.c linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/mm/init.c
--- linux-2.6.21rc7-git2-orig/arch/x86_64/mm/init.c	2007-04-19 12:39:39.000000000 -0700
+++ linux-2.6.21rc7-git2-uefi-finaltest/arch/x86_64/mm/init.c	2007-04-19 13:01:02.000000000 -0700
@@ -26,6 +26,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/memory_hotplug.h>
+#include <linux/efi.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -296,8 +297,8 @@ static void __meminit phys_pud_init(pud_
 
 		if (addr >= end)
 			break;
-
-		if (!after_bootmem && !e820_any_mapped(addr,addr+PUD_SIZE,0)) {
+		if (!after_bootmem && !efi_enabled && 
+			!e820_any_mapped(addr,addr+PUD_SIZE,0)) {
 			set_pud(pud, __pud(0)); 
 			continue;
 		} 
@@ -659,6 +660,8 @@ void __init reserve_bootmem_generic(unsi
 			return;
 		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
 				phys, len);
+		printk(KERN_ERR "reserve_bootmem: pfn (%lx) end_pfn_map (%u)\n",
+			pfn,end_pfn_map);
 		return;
 	}

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux