Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Extensible Firmware Interface | |
3 | * | |
4 | * Based on Extensible Firmware Interface Specification version 1.0 | |
5 | * | |
6 | * Copyright (C) 1999 VA Linux Systems | |
7 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | |
8 | * Copyright (C) 1999-2002 Hewlett-Packard Co. | |
9 | * David Mosberger-Tang <davidm@hpl.hp.com> | |
10 | * Stephane Eranian <eranian@hpl.hp.com> | |
11 | * | |
12 | * All EFI Runtime Services are not implemented yet as EFI only | |
13 | * supports physical mode addressing on SoftSDV. This is to be fixed | |
14 | * in a future version. --drummond 1999-07-20 | |
15 | * | |
16 | * Implemented EFI runtime services and virtual mode calls. --davidm | |
17 | * | |
18 | * Goutham Rao: <goutham.rao@intel.com> | |
19 | * Skip non-WB memory and ignore empty memory ranges. | |
20 | */ | |
21 | ||
1da177e4 | 22 | #include <linux/kernel.h> |
1da177e4 | 23 | #include <linux/types.h> |
1da177e4 | 24 | #include <linux/ioport.h> |
1da177e4 LT |
25 | #include <linux/efi.h> |
26 | ||
1da177e4 LT |
27 | #include <asm/io.h> |
28 | #include <asm/page.h> | |
29 | #include <asm/pgtable.h> | |
1da177e4 LT |
30 | #include <asm/tlbflush.h> |
31 | ||
1da177e4 LT |
32 | /* |
33 | * To make EFI call EFI runtime service in physical addressing mode we need | |
34 | * prelog/epilog before/after the invocation to disable interrupt, to | |
35 | * claim EFI runtime service handler exclusively and to duplicate a memory in | |
36 | * low memory space say 0 - 3G. | |
37 | */ | |
38 | ||
39 | static unsigned long efi_rt_eflags; | |
1da177e4 LT |
40 | static pgd_t efi_bak_pg_dir_pointer[2]; |
41 | ||
8b2cb7a8 | 42 | void efi_call_phys_prelog(void) |
1da177e4 LT |
43 | { |
44 | unsigned long cr4; | |
45 | unsigned long temp; | |
6b68f01b | 46 | struct desc_ptr gdt_descr; |
1da177e4 | 47 | |
1da177e4 LT |
48 | local_irq_save(efi_rt_eflags); |
49 | ||
50 | /* | |
51 | * If I don't have PSE, I should just duplicate two entries in page | |
52 | * directory. If I have PSE, I just need to duplicate one entry in | |
53 | * page directory. | |
54 | */ | |
4bb0d3ec | 55 | cr4 = read_cr4(); |
1da177e4 LT |
56 | |
57 | if (cr4 & X86_CR4_PSE) { | |
58 | efi_bak_pg_dir_pointer[0].pgd = | |
59 | swapper_pg_dir[pgd_index(0)].pgd; | |
60 | swapper_pg_dir[0].pgd = | |
61 | swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; | |
62 | } else { | |
63 | efi_bak_pg_dir_pointer[0].pgd = | |
64 | swapper_pg_dir[pgd_index(0)].pgd; | |
65 | efi_bak_pg_dir_pointer[1].pgd = | |
66 | swapper_pg_dir[pgd_index(0x400000)].pgd; | |
67 | swapper_pg_dir[pgd_index(0)].pgd = | |
68 | swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; | |
69 | temp = PAGE_OFFSET + 0x400000; | |
70 | swapper_pg_dir[pgd_index(0x400000)].pgd = | |
71 | swapper_pg_dir[pgd_index(temp)].pgd; | |
72 | } | |
73 | ||
74 | /* | |
75 | * After the lock is released, the original page table is restored. | |
76 | */ | |
8b2cb7a8 | 77 | __flush_tlb_all(); |
1da177e4 | 78 | |
4fbb5968 RR |
79 | gdt_descr.address = __pa(get_cpu_gdt_table(0)); |
80 | gdt_descr.size = GDT_SIZE - 1; | |
81 | load_gdt(&gdt_descr); | |
1da177e4 LT |
82 | } |
83 | ||
8b2cb7a8 | 84 | void efi_call_phys_epilog(void) |
1da177e4 LT |
85 | { |
86 | unsigned long cr4; | |
6b68f01b | 87 | struct desc_ptr gdt_descr; |
1da177e4 | 88 | |
4fbb5968 RR |
89 | gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); |
90 | gdt_descr.size = GDT_SIZE - 1; | |
91 | load_gdt(&gdt_descr); | |
2b932f6c | 92 | |
4bb0d3ec | 93 | cr4 = read_cr4(); |
1da177e4 LT |
94 | |
95 | if (cr4 & X86_CR4_PSE) { | |
96 | swapper_pg_dir[pgd_index(0)].pgd = | |
97 | efi_bak_pg_dir_pointer[0].pgd; | |
98 | } else { | |
99 | swapper_pg_dir[pgd_index(0)].pgd = | |
100 | efi_bak_pg_dir_pointer[0].pgd; | |
101 | swapper_pg_dir[pgd_index(0x400000)].pgd = | |
102 | efi_bak_pg_dir_pointer[1].pgd; | |
103 | } | |
104 | ||
105 | /* | |
106 | * After the lock is released, the original page table is restored. | |
107 | */ | |
8b2cb7a8 | 108 | __flush_tlb_all(); |
1da177e4 LT |
109 | |
110 | local_irq_restore(efi_rt_eflags); | |
1da177e4 LT |
111 | } |
112 | ||
1da177e4 LT |
113 | /* |
114 | * We need to map the EFI memory map again after paging_init(). | |
115 | */ | |
116 | void __init efi_map_memmap(void) | |
117 | { | |
118 | memmap.map = NULL; | |
119 | ||
7ae65fd3 MT |
120 | memmap.map = bt_ioremap((unsigned long) memmap.phys_map, |
121 | (memmap.nr_map * memmap.desc_size)); | |
1da177e4 | 122 | if (memmap.map == NULL) |
8b2cb7a8 | 123 | printk(KERN_ERR "Could not remap the EFI memmap!\n"); |
7ae65fd3 MT |
124 | |
125 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); | |
1da177e4 | 126 | } |