Commit 873ec746158403af82c57ce26780166aafc159e1
Committed by
Linus Torvalds
1 parent
f038f9a361
Exists in
master
and in
7 other branches
EFI: warn only for pre-1.00 system tables
We used to warn unless the EFI system table major revision was exactly 1. But EFI 2.00 firmware is starting to appear, and the 2.00 changes don't affect anything in Linux. Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com> Cc: Andi Kleen <ak@suse.de> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 4 changed files with 11 additions and 14 deletions Inline Diff
arch/i386/kernel/efi.c
1 | /* | 1 | /* |
2 | * Extensible Firmware Interface | 2 | * Extensible Firmware Interface |
3 | * | 3 | * |
4 | * Based on Extensible Firmware Interface Specification version 1.0 | 4 | * Based on Extensible Firmware Interface Specification version 1.0 |
5 | * | 5 | * |
6 | * Copyright (C) 1999 VA Linux Systems | 6 | * Copyright (C) 1999 VA Linux Systems |
7 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | 7 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> |
8 | * Copyright (C) 1999-2002 Hewlett-Packard Co. | 8 | * Copyright (C) 1999-2002 Hewlett-Packard Co. |
9 | * David Mosberger-Tang <davidm@hpl.hp.com> | 9 | * David Mosberger-Tang <davidm@hpl.hp.com> |
10 | * Stephane Eranian <eranian@hpl.hp.com> | 10 | * Stephane Eranian <eranian@hpl.hp.com> |
11 | * | 11 | * |
12 | * All EFI Runtime Services are not implemented yet as EFI only | 12 | * All EFI Runtime Services are not implemented yet as EFI only |
13 | * supports physical mode addressing on SoftSDV. This is to be fixed | 13 | * supports physical mode addressing on SoftSDV. This is to be fixed |
14 | * in a future version. --drummond 1999-07-20 | 14 | * in a future version. --drummond 1999-07-20 |
15 | * | 15 | * |
16 | * Implemented EFI runtime services and virtual mode calls. --davidm | 16 | * Implemented EFI runtime services and virtual mode calls. --davidm |
17 | * | 17 | * |
18 | * Goutham Rao: <goutham.rao@intel.com> | 18 | * Goutham Rao: <goutham.rao@intel.com> |
19 | * Skip non-WB memory and ignore empty memory ranges. | 19 | * Skip non-WB memory and ignore empty memory ranges. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | #include <linux/bootmem.h> | 28 | #include <linux/bootmem.h> |
29 | #include <linux/ioport.h> | 29 | #include <linux/ioport.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/efi.h> | 31 | #include <linux/efi.h> |
32 | #include <linux/kexec.h> | 32 | #include <linux/kexec.h> |
33 | 33 | ||
34 | #include <asm/setup.h> | 34 | #include <asm/setup.h> |
35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | #include <asm/page.h> | 36 | #include <asm/page.h> |
37 | #include <asm/pgtable.h> | 37 | #include <asm/pgtable.h> |
38 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
39 | #include <asm/desc.h> | 39 | #include <asm/desc.h> |
40 | #include <asm/tlbflush.h> | 40 | #include <asm/tlbflush.h> |
41 | 41 | ||
42 | #define EFI_DEBUG 0 | 42 | #define EFI_DEBUG 0 |
43 | #define PFX "EFI: " | 43 | #define PFX "EFI: " |
44 | 44 | ||
45 | extern efi_status_t asmlinkage efi_call_phys(void *, ...); | 45 | extern efi_status_t asmlinkage efi_call_phys(void *, ...); |
46 | 46 | ||
47 | struct efi efi; | 47 | struct efi efi; |
48 | EXPORT_SYMBOL(efi); | 48 | EXPORT_SYMBOL(efi); |
49 | static struct efi efi_phys; | 49 | static struct efi efi_phys; |
50 | struct efi_memory_map memmap; | 50 | struct efi_memory_map memmap; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * We require an early boot_ioremap mapping mechanism initially | 53 | * We require an early boot_ioremap mapping mechanism initially |
54 | */ | 54 | */ |
55 | extern void * boot_ioremap(unsigned long, unsigned long); | 55 | extern void * boot_ioremap(unsigned long, unsigned long); |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * To make EFI call EFI runtime service in physical addressing mode we need | 58 | * To make EFI call EFI runtime service in physical addressing mode we need |
59 | * prelog/epilog before/after the invocation to disable interrupt, to | 59 | * prelog/epilog before/after the invocation to disable interrupt, to |
60 | * claim EFI runtime service handler exclusively and to duplicate a memory in | 60 | * claim EFI runtime service handler exclusively and to duplicate a memory in |
61 | * low memory space say 0 - 3G. | 61 | * low memory space say 0 - 3G. |
62 | */ | 62 | */ |
63 | 63 | ||
64 | static unsigned long efi_rt_eflags; | 64 | static unsigned long efi_rt_eflags; |
65 | static DEFINE_SPINLOCK(efi_rt_lock); | 65 | static DEFINE_SPINLOCK(efi_rt_lock); |
66 | static pgd_t efi_bak_pg_dir_pointer[2]; | 66 | static pgd_t efi_bak_pg_dir_pointer[2]; |
67 | 67 | ||
68 | static void efi_call_phys_prelog(void) __acquires(efi_rt_lock) | 68 | static void efi_call_phys_prelog(void) __acquires(efi_rt_lock) |
69 | { | 69 | { |
70 | unsigned long cr4; | 70 | unsigned long cr4; |
71 | unsigned long temp; | 71 | unsigned long temp; |
72 | struct Xgt_desc_struct gdt_descr; | 72 | struct Xgt_desc_struct gdt_descr; |
73 | 73 | ||
74 | spin_lock(&efi_rt_lock); | 74 | spin_lock(&efi_rt_lock); |
75 | local_irq_save(efi_rt_eflags); | 75 | local_irq_save(efi_rt_eflags); |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * If I don't have PSE, I should just duplicate two entries in page | 78 | * If I don't have PSE, I should just duplicate two entries in page |
79 | * directory. If I have PSE, I just need to duplicate one entry in | 79 | * directory. If I have PSE, I just need to duplicate one entry in |
80 | * page directory. | 80 | * page directory. |
81 | */ | 81 | */ |
82 | cr4 = read_cr4(); | 82 | cr4 = read_cr4(); |
83 | 83 | ||
84 | if (cr4 & X86_CR4_PSE) { | 84 | if (cr4 & X86_CR4_PSE) { |
85 | efi_bak_pg_dir_pointer[0].pgd = | 85 | efi_bak_pg_dir_pointer[0].pgd = |
86 | swapper_pg_dir[pgd_index(0)].pgd; | 86 | swapper_pg_dir[pgd_index(0)].pgd; |
87 | swapper_pg_dir[0].pgd = | 87 | swapper_pg_dir[0].pgd = |
88 | swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; | 88 | swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; |
89 | } else { | 89 | } else { |
90 | efi_bak_pg_dir_pointer[0].pgd = | 90 | efi_bak_pg_dir_pointer[0].pgd = |
91 | swapper_pg_dir[pgd_index(0)].pgd; | 91 | swapper_pg_dir[pgd_index(0)].pgd; |
92 | efi_bak_pg_dir_pointer[1].pgd = | 92 | efi_bak_pg_dir_pointer[1].pgd = |
93 | swapper_pg_dir[pgd_index(0x400000)].pgd; | 93 | swapper_pg_dir[pgd_index(0x400000)].pgd; |
94 | swapper_pg_dir[pgd_index(0)].pgd = | 94 | swapper_pg_dir[pgd_index(0)].pgd = |
95 | swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; | 95 | swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; |
96 | temp = PAGE_OFFSET + 0x400000; | 96 | temp = PAGE_OFFSET + 0x400000; |
97 | swapper_pg_dir[pgd_index(0x400000)].pgd = | 97 | swapper_pg_dir[pgd_index(0x400000)].pgd = |
98 | swapper_pg_dir[pgd_index(temp)].pgd; | 98 | swapper_pg_dir[pgd_index(temp)].pgd; |
99 | } | 99 | } |
100 | 100 | ||
101 | /* | 101 | /* |
102 | * After the lock is released, the original page table is restored. | 102 | * After the lock is released, the original page table is restored. |
103 | */ | 103 | */ |
104 | local_flush_tlb(); | 104 | local_flush_tlb(); |
105 | 105 | ||
106 | gdt_descr.address = __pa(get_cpu_gdt_table(0)); | 106 | gdt_descr.address = __pa(get_cpu_gdt_table(0)); |
107 | gdt_descr.size = GDT_SIZE - 1; | 107 | gdt_descr.size = GDT_SIZE - 1; |
108 | load_gdt(&gdt_descr); | 108 | load_gdt(&gdt_descr); |
109 | } | 109 | } |
110 | 110 | ||
111 | static void efi_call_phys_epilog(void) __releases(efi_rt_lock) | 111 | static void efi_call_phys_epilog(void) __releases(efi_rt_lock) |
112 | { | 112 | { |
113 | unsigned long cr4; | 113 | unsigned long cr4; |
114 | struct Xgt_desc_struct gdt_descr; | 114 | struct Xgt_desc_struct gdt_descr; |
115 | 115 | ||
116 | gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); | 116 | gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); |
117 | gdt_descr.size = GDT_SIZE - 1; | 117 | gdt_descr.size = GDT_SIZE - 1; |
118 | load_gdt(&gdt_descr); | 118 | load_gdt(&gdt_descr); |
119 | 119 | ||
120 | cr4 = read_cr4(); | 120 | cr4 = read_cr4(); |
121 | 121 | ||
122 | if (cr4 & X86_CR4_PSE) { | 122 | if (cr4 & X86_CR4_PSE) { |
123 | swapper_pg_dir[pgd_index(0)].pgd = | 123 | swapper_pg_dir[pgd_index(0)].pgd = |
124 | efi_bak_pg_dir_pointer[0].pgd; | 124 | efi_bak_pg_dir_pointer[0].pgd; |
125 | } else { | 125 | } else { |
126 | swapper_pg_dir[pgd_index(0)].pgd = | 126 | swapper_pg_dir[pgd_index(0)].pgd = |
127 | efi_bak_pg_dir_pointer[0].pgd; | 127 | efi_bak_pg_dir_pointer[0].pgd; |
128 | swapper_pg_dir[pgd_index(0x400000)].pgd = | 128 | swapper_pg_dir[pgd_index(0x400000)].pgd = |
129 | efi_bak_pg_dir_pointer[1].pgd; | 129 | efi_bak_pg_dir_pointer[1].pgd; |
130 | } | 130 | } |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * After the lock is released, the original page table is restored. | 133 | * After the lock is released, the original page table is restored. |
134 | */ | 134 | */ |
135 | local_flush_tlb(); | 135 | local_flush_tlb(); |
136 | 136 | ||
137 | local_irq_restore(efi_rt_eflags); | 137 | local_irq_restore(efi_rt_eflags); |
138 | spin_unlock(&efi_rt_lock); | 138 | spin_unlock(&efi_rt_lock); |
139 | } | 139 | } |
140 | 140 | ||
141 | static efi_status_t | 141 | static efi_status_t |
142 | phys_efi_set_virtual_address_map(unsigned long memory_map_size, | 142 | phys_efi_set_virtual_address_map(unsigned long memory_map_size, |
143 | unsigned long descriptor_size, | 143 | unsigned long descriptor_size, |
144 | u32 descriptor_version, | 144 | u32 descriptor_version, |
145 | efi_memory_desc_t *virtual_map) | 145 | efi_memory_desc_t *virtual_map) |
146 | { | 146 | { |
147 | efi_status_t status; | 147 | efi_status_t status; |
148 | 148 | ||
149 | efi_call_phys_prelog(); | 149 | efi_call_phys_prelog(); |
150 | status = efi_call_phys(efi_phys.set_virtual_address_map, | 150 | status = efi_call_phys(efi_phys.set_virtual_address_map, |
151 | memory_map_size, descriptor_size, | 151 | memory_map_size, descriptor_size, |
152 | descriptor_version, virtual_map); | 152 | descriptor_version, virtual_map); |
153 | efi_call_phys_epilog(); | 153 | efi_call_phys_epilog(); |
154 | return status; | 154 | return status; |
155 | } | 155 | } |
156 | 156 | ||
157 | static efi_status_t | 157 | static efi_status_t |
158 | phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | 158 | phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) |
159 | { | 159 | { |
160 | efi_status_t status; | 160 | efi_status_t status; |
161 | 161 | ||
162 | efi_call_phys_prelog(); | 162 | efi_call_phys_prelog(); |
163 | status = efi_call_phys(efi_phys.get_time, tm, tc); | 163 | status = efi_call_phys(efi_phys.get_time, tm, tc); |
164 | efi_call_phys_epilog(); | 164 | efi_call_phys_epilog(); |
165 | return status; | 165 | return status; |
166 | } | 166 | } |
167 | 167 | ||
168 | inline int efi_set_rtc_mmss(unsigned long nowtime) | 168 | inline int efi_set_rtc_mmss(unsigned long nowtime) |
169 | { | 169 | { |
170 | int real_seconds, real_minutes; | 170 | int real_seconds, real_minutes; |
171 | efi_status_t status; | 171 | efi_status_t status; |
172 | efi_time_t eft; | 172 | efi_time_t eft; |
173 | efi_time_cap_t cap; | 173 | efi_time_cap_t cap; |
174 | 174 | ||
175 | spin_lock(&efi_rt_lock); | 175 | spin_lock(&efi_rt_lock); |
176 | status = efi.get_time(&eft, &cap); | 176 | status = efi.get_time(&eft, &cap); |
177 | spin_unlock(&efi_rt_lock); | 177 | spin_unlock(&efi_rt_lock); |
178 | if (status != EFI_SUCCESS) | 178 | if (status != EFI_SUCCESS) |
179 | panic("Ooops, efitime: can't read time!\n"); | 179 | panic("Ooops, efitime: can't read time!\n"); |
180 | real_seconds = nowtime % 60; | 180 | real_seconds = nowtime % 60; |
181 | real_minutes = nowtime / 60; | 181 | real_minutes = nowtime / 60; |
182 | 182 | ||
183 | if (((abs(real_minutes - eft.minute) + 15)/30) & 1) | 183 | if (((abs(real_minutes - eft.minute) + 15)/30) & 1) |
184 | real_minutes += 30; | 184 | real_minutes += 30; |
185 | real_minutes %= 60; | 185 | real_minutes %= 60; |
186 | 186 | ||
187 | eft.minute = real_minutes; | 187 | eft.minute = real_minutes; |
188 | eft.second = real_seconds; | 188 | eft.second = real_seconds; |
189 | 189 | ||
190 | if (status != EFI_SUCCESS) { | 190 | if (status != EFI_SUCCESS) { |
191 | printk("Ooops: efitime: can't read time!\n"); | 191 | printk("Ooops: efitime: can't read time!\n"); |
192 | return -1; | 192 | return -1; |
193 | } | 193 | } |
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | /* | 196 | /* |
197 | * This is used during kernel init before runtime | 197 | * This is used during kernel init before runtime |
198 | * services have been remapped and also during suspend, therefore, | 198 | * services have been remapped and also during suspend, therefore, |
199 | * we'll need to call both in physical and virtual modes. | 199 | * we'll need to call both in physical and virtual modes. |
200 | */ | 200 | */ |
201 | inline unsigned long efi_get_time(void) | 201 | inline unsigned long efi_get_time(void) |
202 | { | 202 | { |
203 | efi_status_t status; | 203 | efi_status_t status; |
204 | efi_time_t eft; | 204 | efi_time_t eft; |
205 | efi_time_cap_t cap; | 205 | efi_time_cap_t cap; |
206 | 206 | ||
207 | if (efi.get_time) { | 207 | if (efi.get_time) { |
208 | /* if we are in virtual mode use remapped function */ | 208 | /* if we are in virtual mode use remapped function */ |
209 | status = efi.get_time(&eft, &cap); | 209 | status = efi.get_time(&eft, &cap); |
210 | } else { | 210 | } else { |
211 | /* we are in physical mode */ | 211 | /* we are in physical mode */ |
212 | status = phys_efi_get_time(&eft, &cap); | 212 | status = phys_efi_get_time(&eft, &cap); |
213 | } | 213 | } |
214 | 214 | ||
215 | if (status != EFI_SUCCESS) | 215 | if (status != EFI_SUCCESS) |
216 | printk("Oops: efitime: can't read time status: 0x%lx\n",status); | 216 | printk("Oops: efitime: can't read time status: 0x%lx\n",status); |
217 | 217 | ||
218 | return mktime(eft.year, eft.month, eft.day, eft.hour, | 218 | return mktime(eft.year, eft.month, eft.day, eft.hour, |
219 | eft.minute, eft.second); | 219 | eft.minute, eft.second); |
220 | } | 220 | } |
221 | 221 | ||
222 | int is_available_memory(efi_memory_desc_t * md) | 222 | int is_available_memory(efi_memory_desc_t * md) |
223 | { | 223 | { |
224 | if (!(md->attribute & EFI_MEMORY_WB)) | 224 | if (!(md->attribute & EFI_MEMORY_WB)) |
225 | return 0; | 225 | return 0; |
226 | 226 | ||
227 | switch (md->type) { | 227 | switch (md->type) { |
228 | case EFI_LOADER_CODE: | 228 | case EFI_LOADER_CODE: |
229 | case EFI_LOADER_DATA: | 229 | case EFI_LOADER_DATA: |
230 | case EFI_BOOT_SERVICES_CODE: | 230 | case EFI_BOOT_SERVICES_CODE: |
231 | case EFI_BOOT_SERVICES_DATA: | 231 | case EFI_BOOT_SERVICES_DATA: |
232 | case EFI_CONVENTIONAL_MEMORY: | 232 | case EFI_CONVENTIONAL_MEMORY: |
233 | return 1; | 233 | return 1; |
234 | } | 234 | } |
235 | return 0; | 235 | return 0; |
236 | } | 236 | } |
237 | 237 | ||
238 | /* | 238 | /* |
239 | * We need to map the EFI memory map again after paging_init(). | 239 | * We need to map the EFI memory map again after paging_init(). |
240 | */ | 240 | */ |
241 | void __init efi_map_memmap(void) | 241 | void __init efi_map_memmap(void) |
242 | { | 242 | { |
243 | memmap.map = NULL; | 243 | memmap.map = NULL; |
244 | 244 | ||
245 | memmap.map = bt_ioremap((unsigned long) memmap.phys_map, | 245 | memmap.map = bt_ioremap((unsigned long) memmap.phys_map, |
246 | (memmap.nr_map * memmap.desc_size)); | 246 | (memmap.nr_map * memmap.desc_size)); |
247 | if (memmap.map == NULL) | 247 | if (memmap.map == NULL) |
248 | printk(KERN_ERR PFX "Could not remap the EFI memmap!\n"); | 248 | printk(KERN_ERR PFX "Could not remap the EFI memmap!\n"); |
249 | 249 | ||
250 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); | 250 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); |
251 | } | 251 | } |
252 | 252 | ||
253 | #if EFI_DEBUG | 253 | #if EFI_DEBUG |
254 | static void __init print_efi_memmap(void) | 254 | static void __init print_efi_memmap(void) |
255 | { | 255 | { |
256 | efi_memory_desc_t *md; | 256 | efi_memory_desc_t *md; |
257 | void *p; | 257 | void *p; |
258 | int i; | 258 | int i; |
259 | 259 | ||
260 | for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) { | 260 | for (p = memmap.map, i = 0; p < memmap.map_end; p += memmap.desc_size, i++) { |
261 | md = p; | 261 | md = p; |
262 | printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, " | 262 | printk(KERN_INFO "mem%02u: type=%u, attr=0x%llx, " |
263 | "range=[0x%016llx-0x%016llx) (%lluMB)\n", | 263 | "range=[0x%016llx-0x%016llx) (%lluMB)\n", |
264 | i, md->type, md->attribute, md->phys_addr, | 264 | i, md->type, md->attribute, md->phys_addr, |
265 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), | 265 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), |
266 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); | 266 | (md->num_pages >> (20 - EFI_PAGE_SHIFT))); |
267 | } | 267 | } |
268 | } | 268 | } |
269 | #endif /* EFI_DEBUG */ | 269 | #endif /* EFI_DEBUG */ |
270 | 270 | ||
271 | /* | 271 | /* |
272 | * Walks the EFI memory map and calls CALLBACK once for each EFI | 272 | * Walks the EFI memory map and calls CALLBACK once for each EFI |
273 | * memory descriptor that has memory that is available for kernel use. | 273 | * memory descriptor that has memory that is available for kernel use. |
274 | */ | 274 | */ |
275 | void efi_memmap_walk(efi_freemem_callback_t callback, void *arg) | 275 | void efi_memmap_walk(efi_freemem_callback_t callback, void *arg) |
276 | { | 276 | { |
277 | int prev_valid = 0; | 277 | int prev_valid = 0; |
278 | struct range { | 278 | struct range { |
279 | unsigned long start; | 279 | unsigned long start; |
280 | unsigned long end; | 280 | unsigned long end; |
281 | } prev, curr; | 281 | } prev, curr; |
282 | efi_memory_desc_t *md; | 282 | efi_memory_desc_t *md; |
283 | unsigned long start, end; | 283 | unsigned long start, end; |
284 | void *p; | 284 | void *p; |
285 | 285 | ||
286 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 286 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
287 | md = p; | 287 | md = p; |
288 | 288 | ||
289 | if ((md->num_pages == 0) || (!is_available_memory(md))) | 289 | if ((md->num_pages == 0) || (!is_available_memory(md))) |
290 | continue; | 290 | continue; |
291 | 291 | ||
292 | curr.start = md->phys_addr; | 292 | curr.start = md->phys_addr; |
293 | curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT); | 293 | curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT); |
294 | 294 | ||
295 | if (!prev_valid) { | 295 | if (!prev_valid) { |
296 | prev = curr; | 296 | prev = curr; |
297 | prev_valid = 1; | 297 | prev_valid = 1; |
298 | } else { | 298 | } else { |
299 | if (curr.start < prev.start) | 299 | if (curr.start < prev.start) |
300 | printk(KERN_INFO PFX "Unordered memory map\n"); | 300 | printk(KERN_INFO PFX "Unordered memory map\n"); |
301 | if (prev.end == curr.start) | 301 | if (prev.end == curr.start) |
302 | prev.end = curr.end; | 302 | prev.end = curr.end; |
303 | else { | 303 | else { |
304 | start = | 304 | start = |
305 | (unsigned long) (PAGE_ALIGN(prev.start)); | 305 | (unsigned long) (PAGE_ALIGN(prev.start)); |
306 | end = (unsigned long) (prev.end & PAGE_MASK); | 306 | end = (unsigned long) (prev.end & PAGE_MASK); |
307 | if ((end > start) | 307 | if ((end > start) |
308 | && (*callback) (start, end, arg) < 0) | 308 | && (*callback) (start, end, arg) < 0) |
309 | return; | 309 | return; |
310 | prev = curr; | 310 | prev = curr; |
311 | } | 311 | } |
312 | } | 312 | } |
313 | } | 313 | } |
314 | if (prev_valid) { | 314 | if (prev_valid) { |
315 | start = (unsigned long) PAGE_ALIGN(prev.start); | 315 | start = (unsigned long) PAGE_ALIGN(prev.start); |
316 | end = (unsigned long) (prev.end & PAGE_MASK); | 316 | end = (unsigned long) (prev.end & PAGE_MASK); |
317 | if (end > start) | 317 | if (end > start) |
318 | (*callback) (start, end, arg); | 318 | (*callback) (start, end, arg); |
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
322 | void __init efi_init(void) | 322 | void __init efi_init(void) |
323 | { | 323 | { |
324 | efi_config_table_t *config_tables; | 324 | efi_config_table_t *config_tables; |
325 | efi_runtime_services_t *runtime; | 325 | efi_runtime_services_t *runtime; |
326 | efi_char16_t *c16; | 326 | efi_char16_t *c16; |
327 | char vendor[100] = "unknown"; | 327 | char vendor[100] = "unknown"; |
328 | unsigned long num_config_tables; | 328 | unsigned long num_config_tables; |
329 | int i = 0; | 329 | int i = 0; |
330 | 330 | ||
331 | memset(&efi, 0, sizeof(efi) ); | 331 | memset(&efi, 0, sizeof(efi) ); |
332 | memset(&efi_phys, 0, sizeof(efi_phys)); | 332 | memset(&efi_phys, 0, sizeof(efi_phys)); |
333 | 333 | ||
334 | efi_phys.systab = EFI_SYSTAB; | 334 | efi_phys.systab = EFI_SYSTAB; |
335 | memmap.phys_map = EFI_MEMMAP; | 335 | memmap.phys_map = EFI_MEMMAP; |
336 | memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE; | 336 | memmap.nr_map = EFI_MEMMAP_SIZE/EFI_MEMDESC_SIZE; |
337 | memmap.desc_version = EFI_MEMDESC_VERSION; | 337 | memmap.desc_version = EFI_MEMDESC_VERSION; |
338 | memmap.desc_size = EFI_MEMDESC_SIZE; | 338 | memmap.desc_size = EFI_MEMDESC_SIZE; |
339 | 339 | ||
340 | efi.systab = (efi_system_table_t *) | 340 | efi.systab = (efi_system_table_t *) |
341 | boot_ioremap((unsigned long) efi_phys.systab, | 341 | boot_ioremap((unsigned long) efi_phys.systab, |
342 | sizeof(efi_system_table_t)); | 342 | sizeof(efi_system_table_t)); |
343 | /* | 343 | /* |
344 | * Verify the EFI Table | 344 | * Verify the EFI Table |
345 | */ | 345 | */ |
346 | if (efi.systab == NULL) | 346 | if (efi.systab == NULL) |
347 | printk(KERN_ERR PFX "Woah! Couldn't map the EFI system table.\n"); | 347 | printk(KERN_ERR PFX "Woah! Couldn't map the EFI system table.\n"); |
348 | if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | 348 | if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) |
349 | printk(KERN_ERR PFX "Woah! EFI system table signature incorrect\n"); | 349 | printk(KERN_ERR PFX "Woah! EFI system table signature incorrect\n"); |
350 | if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0) | 350 | if ((efi.systab->hdr.revision >> 16) == 0) |
351 | printk(KERN_ERR PFX | 351 | printk(KERN_ERR PFX "Warning: EFI system table version " |
352 | "Warning: EFI system table major version mismatch: " | 352 | "%d.%02d, expected 1.00 or greater\n", |
353 | "got %d.%02d, expected %d.%02d\n", | ||
354 | efi.systab->hdr.revision >> 16, | 353 | efi.systab->hdr.revision >> 16, |
355 | efi.systab->hdr.revision & 0xffff, | 354 | efi.systab->hdr.revision & 0xffff); |
356 | EFI_SYSTEM_TABLE_REVISION >> 16, | 355 | |
357 | EFI_SYSTEM_TABLE_REVISION & 0xffff); | ||
358 | /* | 356 | /* |
359 | * Grab some details from the system table | 357 | * Grab some details from the system table |
360 | */ | 358 | */ |
361 | num_config_tables = efi.systab->nr_tables; | 359 | num_config_tables = efi.systab->nr_tables; |
362 | config_tables = (efi_config_table_t *)efi.systab->tables; | 360 | config_tables = (efi_config_table_t *)efi.systab->tables; |
363 | runtime = efi.systab->runtime; | 361 | runtime = efi.systab->runtime; |
364 | 362 | ||
365 | /* | 363 | /* |
366 | * Show what we know for posterity | 364 | * Show what we know for posterity |
367 | */ | 365 | */ |
368 | c16 = (efi_char16_t *) boot_ioremap(efi.systab->fw_vendor, 2); | 366 | c16 = (efi_char16_t *) boot_ioremap(efi.systab->fw_vendor, 2); |
369 | if (c16) { | 367 | if (c16) { |
370 | for (i = 0; i < (sizeof(vendor) - 1) && *c16; ++i) | 368 | for (i = 0; i < (sizeof(vendor) - 1) && *c16; ++i) |
371 | vendor[i] = *c16++; | 369 | vendor[i] = *c16++; |
372 | vendor[i] = '\0'; | 370 | vendor[i] = '\0'; |
373 | } else | 371 | } else |
374 | printk(KERN_ERR PFX "Could not map the firmware vendor!\n"); | 372 | printk(KERN_ERR PFX "Could not map the firmware vendor!\n"); |
375 | 373 | ||
376 | printk(KERN_INFO PFX "EFI v%u.%.02u by %s \n", | 374 | printk(KERN_INFO PFX "EFI v%u.%.02u by %s \n", |
377 | efi.systab->hdr.revision >> 16, | 375 | efi.systab->hdr.revision >> 16, |
378 | efi.systab->hdr.revision & 0xffff, vendor); | 376 | efi.systab->hdr.revision & 0xffff, vendor); |
379 | 377 | ||
380 | /* | 378 | /* |
381 | * Let's see what config tables the firmware passed to us. | 379 | * Let's see what config tables the firmware passed to us. |
382 | */ | 380 | */ |
383 | config_tables = (efi_config_table_t *) | 381 | config_tables = (efi_config_table_t *) |
384 | boot_ioremap((unsigned long) config_tables, | 382 | boot_ioremap((unsigned long) config_tables, |
385 | num_config_tables * sizeof(efi_config_table_t)); | 383 | num_config_tables * sizeof(efi_config_table_t)); |
386 | 384 | ||
387 | if (config_tables == NULL) | 385 | if (config_tables == NULL) |
388 | printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n"); | 386 | printk(KERN_ERR PFX "Could not map EFI Configuration Table!\n"); |
389 | 387 | ||
390 | efi.mps = EFI_INVALID_TABLE_ADDR; | 388 | efi.mps = EFI_INVALID_TABLE_ADDR; |
391 | efi.acpi = EFI_INVALID_TABLE_ADDR; | 389 | efi.acpi = EFI_INVALID_TABLE_ADDR; |
392 | efi.acpi20 = EFI_INVALID_TABLE_ADDR; | 390 | efi.acpi20 = EFI_INVALID_TABLE_ADDR; |
393 | efi.smbios = EFI_INVALID_TABLE_ADDR; | 391 | efi.smbios = EFI_INVALID_TABLE_ADDR; |
394 | efi.sal_systab = EFI_INVALID_TABLE_ADDR; | 392 | efi.sal_systab = EFI_INVALID_TABLE_ADDR; |
395 | efi.boot_info = EFI_INVALID_TABLE_ADDR; | 393 | efi.boot_info = EFI_INVALID_TABLE_ADDR; |
396 | efi.hcdp = EFI_INVALID_TABLE_ADDR; | 394 | efi.hcdp = EFI_INVALID_TABLE_ADDR; |
397 | efi.uga = EFI_INVALID_TABLE_ADDR; | 395 | efi.uga = EFI_INVALID_TABLE_ADDR; |
398 | 396 | ||
399 | for (i = 0; i < num_config_tables; i++) { | 397 | for (i = 0; i < num_config_tables; i++) { |
400 | if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { | 398 | if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { |
401 | efi.mps = config_tables[i].table; | 399 | efi.mps = config_tables[i].table; |
402 | printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table); | 400 | printk(KERN_INFO " MPS=0x%lx ", config_tables[i].table); |
403 | } else | 401 | } else |
404 | if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { | 402 | if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { |
405 | efi.acpi20 = config_tables[i].table; | 403 | efi.acpi20 = config_tables[i].table; |
406 | printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table); | 404 | printk(KERN_INFO " ACPI 2.0=0x%lx ", config_tables[i].table); |
407 | } else | 405 | } else |
408 | if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { | 406 | if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { |
409 | efi.acpi = config_tables[i].table; | 407 | efi.acpi = config_tables[i].table; |
410 | printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table); | 408 | printk(KERN_INFO " ACPI=0x%lx ", config_tables[i].table); |
411 | } else | 409 | } else |
412 | if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { | 410 | if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { |
413 | efi.smbios = config_tables[i].table; | 411 | efi.smbios = config_tables[i].table; |
414 | printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table); | 412 | printk(KERN_INFO " SMBIOS=0x%lx ", config_tables[i].table); |
415 | } else | 413 | } else |
416 | if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { | 414 | if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { |
417 | efi.hcdp = config_tables[i].table; | 415 | efi.hcdp = config_tables[i].table; |
418 | printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table); | 416 | printk(KERN_INFO " HCDP=0x%lx ", config_tables[i].table); |
419 | } else | 417 | } else |
420 | if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) { | 418 | if (efi_guidcmp(config_tables[i].guid, UGA_IO_PROTOCOL_GUID) == 0) { |
421 | efi.uga = config_tables[i].table; | 419 | efi.uga = config_tables[i].table; |
422 | printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table); | 420 | printk(KERN_INFO " UGA=0x%lx ", config_tables[i].table); |
423 | } | 421 | } |
424 | } | 422 | } |
425 | printk("\n"); | 423 | printk("\n"); |
426 | 424 | ||
427 | /* | 425 | /* |
428 | * Check out the runtime services table. We need to map | 426 | * Check out the runtime services table. We need to map |
429 | * the runtime services table so that we can grab the physical | 427 | * the runtime services table so that we can grab the physical |
430 | * address of several of the EFI runtime functions, needed to | 428 | * address of several of the EFI runtime functions, needed to |
431 | * set the firmware into virtual mode. | 429 | * set the firmware into virtual mode. |
432 | */ | 430 | */ |
433 | 431 | ||
434 | runtime = (efi_runtime_services_t *) boot_ioremap((unsigned long) | 432 | runtime = (efi_runtime_services_t *) boot_ioremap((unsigned long) |
435 | runtime, | 433 | runtime, |
436 | sizeof(efi_runtime_services_t)); | 434 | sizeof(efi_runtime_services_t)); |
437 | if (runtime != NULL) { | 435 | if (runtime != NULL) { |
438 | /* | 436 | /* |
439 | * We will only need *early* access to the following | 437 | * We will only need *early* access to the following |
440 | * two EFI runtime services before set_virtual_address_map | 438 | * two EFI runtime services before set_virtual_address_map |
441 | * is invoked. | 439 | * is invoked. |
442 | */ | 440 | */ |
443 | efi_phys.get_time = (efi_get_time_t *) runtime->get_time; | 441 | efi_phys.get_time = (efi_get_time_t *) runtime->get_time; |
444 | efi_phys.set_virtual_address_map = | 442 | efi_phys.set_virtual_address_map = |
445 | (efi_set_virtual_address_map_t *) | 443 | (efi_set_virtual_address_map_t *) |
446 | runtime->set_virtual_address_map; | 444 | runtime->set_virtual_address_map; |
447 | } else | 445 | } else |
448 | printk(KERN_ERR PFX "Could not map the runtime service table!\n"); | 446 | printk(KERN_ERR PFX "Could not map the runtime service table!\n"); |
449 | 447 | ||
450 | /* Map the EFI memory map for use until paging_init() */ | 448 | /* Map the EFI memory map for use until paging_init() */ |
451 | memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE); | 449 | memmap.map = boot_ioremap((unsigned long) EFI_MEMMAP, EFI_MEMMAP_SIZE); |
452 | if (memmap.map == NULL) | 450 | if (memmap.map == NULL) |
453 | printk(KERN_ERR PFX "Could not map the EFI memory map!\n"); | 451 | printk(KERN_ERR PFX "Could not map the EFI memory map!\n"); |
454 | 452 | ||
455 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); | 453 | memmap.map_end = memmap.map + (memmap.nr_map * memmap.desc_size); |
456 | 454 | ||
457 | #if EFI_DEBUG | 455 | #if EFI_DEBUG |
458 | print_efi_memmap(); | 456 | print_efi_memmap(); |
459 | #endif | 457 | #endif |
460 | } | 458 | } |
461 | 459 | ||
462 | static inline void __init check_range_for_systab(efi_memory_desc_t *md) | 460 | static inline void __init check_range_for_systab(efi_memory_desc_t *md) |
463 | { | 461 | { |
464 | if (((unsigned long)md->phys_addr <= (unsigned long)efi_phys.systab) && | 462 | if (((unsigned long)md->phys_addr <= (unsigned long)efi_phys.systab) && |
465 | ((unsigned long)efi_phys.systab < md->phys_addr + | 463 | ((unsigned long)efi_phys.systab < md->phys_addr + |
466 | ((unsigned long)md->num_pages << EFI_PAGE_SHIFT))) { | 464 | ((unsigned long)md->num_pages << EFI_PAGE_SHIFT))) { |
467 | unsigned long addr; | 465 | unsigned long addr; |
468 | 466 | ||
469 | addr = md->virt_addr - md->phys_addr + | 467 | addr = md->virt_addr - md->phys_addr + |
470 | (unsigned long)efi_phys.systab; | 468 | (unsigned long)efi_phys.systab; |
471 | efi.systab = (efi_system_table_t *)addr; | 469 | efi.systab = (efi_system_table_t *)addr; |
472 | } | 470 | } |
473 | } | 471 | } |
474 | 472 | ||
475 | /* | 473 | /* |
476 | * Wrap all the virtual calls in a way that forces the parameters on the stack. | 474 | * Wrap all the virtual calls in a way that forces the parameters on the stack. |
477 | */ | 475 | */ |
478 | 476 | ||
479 | #define efi_call_virt(f, args...) \ | 477 | #define efi_call_virt(f, args...) \ |
480 | ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args) | 478 | ((efi_##f##_t __attribute__((regparm(0)))*)efi.systab->runtime->f)(args) |
481 | 479 | ||
482 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) | 480 | static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc) |
483 | { | 481 | { |
484 | return efi_call_virt(get_time, tm, tc); | 482 | return efi_call_virt(get_time, tm, tc); |
485 | } | 483 | } |
486 | 484 | ||
487 | static efi_status_t virt_efi_set_time (efi_time_t *tm) | 485 | static efi_status_t virt_efi_set_time (efi_time_t *tm) |
488 | { | 486 | { |
489 | return efi_call_virt(set_time, tm); | 487 | return efi_call_virt(set_time, tm); |
490 | } | 488 | } |
491 | 489 | ||
492 | static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled, | 490 | static efi_status_t virt_efi_get_wakeup_time (efi_bool_t *enabled, |
493 | efi_bool_t *pending, | 491 | efi_bool_t *pending, |
494 | efi_time_t *tm) | 492 | efi_time_t *tm) |
495 | { | 493 | { |
496 | return efi_call_virt(get_wakeup_time, enabled, pending, tm); | 494 | return efi_call_virt(get_wakeup_time, enabled, pending, tm); |
497 | } | 495 | } |
498 | 496 | ||
499 | static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled, | 497 | static efi_status_t virt_efi_set_wakeup_time (efi_bool_t enabled, |
500 | efi_time_t *tm) | 498 | efi_time_t *tm) |
501 | { | 499 | { |
502 | return efi_call_virt(set_wakeup_time, enabled, tm); | 500 | return efi_call_virt(set_wakeup_time, enabled, tm); |
503 | } | 501 | } |
504 | 502 | ||
505 | static efi_status_t virt_efi_get_variable (efi_char16_t *name, | 503 | static efi_status_t virt_efi_get_variable (efi_char16_t *name, |
506 | efi_guid_t *vendor, u32 *attr, | 504 | efi_guid_t *vendor, u32 *attr, |
507 | unsigned long *data_size, void *data) | 505 | unsigned long *data_size, void *data) |
508 | { | 506 | { |
509 | return efi_call_virt(get_variable, name, vendor, attr, data_size, data); | 507 | return efi_call_virt(get_variable, name, vendor, attr, data_size, data); |
510 | } | 508 | } |
511 | 509 | ||
512 | static efi_status_t virt_efi_get_next_variable (unsigned long *name_size, | 510 | static efi_status_t virt_efi_get_next_variable (unsigned long *name_size, |
513 | efi_char16_t *name, | 511 | efi_char16_t *name, |
514 | efi_guid_t *vendor) | 512 | efi_guid_t *vendor) |
515 | { | 513 | { |
516 | return efi_call_virt(get_next_variable, name_size, name, vendor); | 514 | return efi_call_virt(get_next_variable, name_size, name, vendor); |
517 | } | 515 | } |
518 | 516 | ||
519 | static efi_status_t virt_efi_set_variable (efi_char16_t *name, | 517 | static efi_status_t virt_efi_set_variable (efi_char16_t *name, |
520 | efi_guid_t *vendor, | 518 | efi_guid_t *vendor, |
521 | unsigned long attr, | 519 | unsigned long attr, |
522 | unsigned long data_size, void *data) | 520 | unsigned long data_size, void *data) |
523 | { | 521 | { |
524 | return efi_call_virt(set_variable, name, vendor, attr, data_size, data); | 522 | return efi_call_virt(set_variable, name, vendor, attr, data_size, data); |
525 | } | 523 | } |
526 | 524 | ||
527 | static efi_status_t virt_efi_get_next_high_mono_count (u32 *count) | 525 | static efi_status_t virt_efi_get_next_high_mono_count (u32 *count) |
528 | { | 526 | { |
529 | return efi_call_virt(get_next_high_mono_count, count); | 527 | return efi_call_virt(get_next_high_mono_count, count); |
530 | } | 528 | } |
531 | 529 | ||
532 | static void virt_efi_reset_system (int reset_type, efi_status_t status, | 530 | static void virt_efi_reset_system (int reset_type, efi_status_t status, |
533 | unsigned long data_size, | 531 | unsigned long data_size, |
534 | efi_char16_t *data) | 532 | efi_char16_t *data) |
535 | { | 533 | { |
536 | efi_call_virt(reset_system, reset_type, status, data_size, data); | 534 | efi_call_virt(reset_system, reset_type, status, data_size, data); |
537 | } | 535 | } |
538 | 536 | ||
539 | /* | 537 | /* |
540 | * This function will switch the EFI runtime services to virtual mode. | 538 | * This function will switch the EFI runtime services to virtual mode. |
541 | * Essentially, look through the EFI memmap and map every region that | 539 | * Essentially, look through the EFI memmap and map every region that |
542 | * has the runtime attribute bit set in its memory descriptor and update | 540 | * has the runtime attribute bit set in its memory descriptor and update |
543 | * that memory descriptor with the virtual address obtained from ioremap(). | 541 | * that memory descriptor with the virtual address obtained from ioremap(). |
544 | * This enables the runtime services to be called without having to | 542 | * This enables the runtime services to be called without having to |
545 | * thunk back into physical mode for every invocation. | 543 | * thunk back into physical mode for every invocation. |
546 | */ | 544 | */ |
547 | 545 | ||
548 | void __init efi_enter_virtual_mode(void) | 546 | void __init efi_enter_virtual_mode(void) |
549 | { | 547 | { |
550 | efi_memory_desc_t *md; | 548 | efi_memory_desc_t *md; |
551 | efi_status_t status; | 549 | efi_status_t status; |
552 | void *p; | 550 | void *p; |
553 | 551 | ||
554 | efi.systab = NULL; | 552 | efi.systab = NULL; |
555 | 553 | ||
556 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 554 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
557 | md = p; | 555 | md = p; |
558 | 556 | ||
559 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) | 557 | if (!(md->attribute & EFI_MEMORY_RUNTIME)) |
560 | continue; | 558 | continue; |
561 | 559 | ||
562 | md->virt_addr = (unsigned long)ioremap(md->phys_addr, | 560 | md->virt_addr = (unsigned long)ioremap(md->phys_addr, |
563 | md->num_pages << EFI_PAGE_SHIFT); | 561 | md->num_pages << EFI_PAGE_SHIFT); |
564 | if (!(unsigned long)md->virt_addr) { | 562 | if (!(unsigned long)md->virt_addr) { |
565 | printk(KERN_ERR PFX "ioremap of 0x%lX failed\n", | 563 | printk(KERN_ERR PFX "ioremap of 0x%lX failed\n", |
566 | (unsigned long)md->phys_addr); | 564 | (unsigned long)md->phys_addr); |
567 | } | 565 | } |
568 | /* update the virtual address of the EFI system table */ | 566 | /* update the virtual address of the EFI system table */ |
569 | check_range_for_systab(md); | 567 | check_range_for_systab(md); |
570 | } | 568 | } |
571 | 569 | ||
572 | BUG_ON(!efi.systab); | 570 | BUG_ON(!efi.systab); |
573 | 571 | ||
574 | status = phys_efi_set_virtual_address_map( | 572 | status = phys_efi_set_virtual_address_map( |
575 | memmap.desc_size * memmap.nr_map, | 573 | memmap.desc_size * memmap.nr_map, |
576 | memmap.desc_size, | 574 | memmap.desc_size, |
577 | memmap.desc_version, | 575 | memmap.desc_version, |
578 | memmap.phys_map); | 576 | memmap.phys_map); |
579 | 577 | ||
580 | if (status != EFI_SUCCESS) { | 578 | if (status != EFI_SUCCESS) { |
581 | printk (KERN_ALERT "You are screwed! " | 579 | printk (KERN_ALERT "You are screwed! " |
582 | "Unable to switch EFI into virtual mode " | 580 | "Unable to switch EFI into virtual mode " |
583 | "(status=%lx)\n", status); | 581 | "(status=%lx)\n", status); |
584 | panic("EFI call to SetVirtualAddressMap() failed!"); | 582 | panic("EFI call to SetVirtualAddressMap() failed!"); |
585 | } | 583 | } |
586 | 584 | ||
587 | /* | 585 | /* |
588 | * Now that EFI is in virtual mode, update the function | 586 | * Now that EFI is in virtual mode, update the function |
589 | * pointers in the runtime service table to the new virtual addresses. | 587 | * pointers in the runtime service table to the new virtual addresses. |
590 | */ | 588 | */ |
591 | 589 | ||
592 | efi.get_time = virt_efi_get_time; | 590 | efi.get_time = virt_efi_get_time; |
593 | efi.set_time = virt_efi_set_time; | 591 | efi.set_time = virt_efi_set_time; |
594 | efi.get_wakeup_time = virt_efi_get_wakeup_time; | 592 | efi.get_wakeup_time = virt_efi_get_wakeup_time; |
595 | efi.set_wakeup_time = virt_efi_set_wakeup_time; | 593 | efi.set_wakeup_time = virt_efi_set_wakeup_time; |
596 | efi.get_variable = virt_efi_get_variable; | 594 | efi.get_variable = virt_efi_get_variable; |
597 | efi.get_next_variable = virt_efi_get_next_variable; | 595 | efi.get_next_variable = virt_efi_get_next_variable; |
598 | efi.set_variable = virt_efi_set_variable; | 596 | efi.set_variable = virt_efi_set_variable; |
599 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; | 597 | efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count; |
600 | efi.reset_system = virt_efi_reset_system; | 598 | efi.reset_system = virt_efi_reset_system; |
601 | } | 599 | } |
602 | 600 | ||
603 | void __init | 601 | void __init |
604 | efi_initialize_iomem_resources(struct resource *code_resource, | 602 | efi_initialize_iomem_resources(struct resource *code_resource, |
605 | struct resource *data_resource) | 603 | struct resource *data_resource) |
606 | { | 604 | { |
607 | struct resource *res; | 605 | struct resource *res; |
608 | efi_memory_desc_t *md; | 606 | efi_memory_desc_t *md; |
609 | void *p; | 607 | void *p; |
610 | 608 | ||
611 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 609 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
612 | md = p; | 610 | md = p; |
613 | 611 | ||
614 | if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) > | 612 | if ((md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) > |
615 | 0x100000000ULL) | 613 | 0x100000000ULL) |
616 | continue; | 614 | continue; |
617 | res = kzalloc(sizeof(struct resource), GFP_ATOMIC); | 615 | res = kzalloc(sizeof(struct resource), GFP_ATOMIC); |
618 | switch (md->type) { | 616 | switch (md->type) { |
619 | case EFI_RESERVED_TYPE: | 617 | case EFI_RESERVED_TYPE: |
620 | res->name = "Reserved Memory"; | 618 | res->name = "Reserved Memory"; |
621 | break; | 619 | break; |
622 | case EFI_LOADER_CODE: | 620 | case EFI_LOADER_CODE: |
623 | res->name = "Loader Code"; | 621 | res->name = "Loader Code"; |
624 | break; | 622 | break; |
625 | case EFI_LOADER_DATA: | 623 | case EFI_LOADER_DATA: |
626 | res->name = "Loader Data"; | 624 | res->name = "Loader Data"; |
627 | break; | 625 | break; |
628 | case EFI_BOOT_SERVICES_DATA: | 626 | case EFI_BOOT_SERVICES_DATA: |
629 | res->name = "BootServices Data"; | 627 | res->name = "BootServices Data"; |
630 | break; | 628 | break; |
631 | case EFI_BOOT_SERVICES_CODE: | 629 | case EFI_BOOT_SERVICES_CODE: |
632 | res->name = "BootServices Code"; | 630 | res->name = "BootServices Code"; |
633 | break; | 631 | break; |
634 | case EFI_RUNTIME_SERVICES_CODE: | 632 | case EFI_RUNTIME_SERVICES_CODE: |
635 | res->name = "Runtime Service Code"; | 633 | res->name = "Runtime Service Code"; |
636 | break; | 634 | break; |
637 | case EFI_RUNTIME_SERVICES_DATA: | 635 | case EFI_RUNTIME_SERVICES_DATA: |
638 | res->name = "Runtime Service Data"; | 636 | res->name = "Runtime Service Data"; |
639 | break; | 637 | break; |
640 | case EFI_CONVENTIONAL_MEMORY: | 638 | case EFI_CONVENTIONAL_MEMORY: |
641 | res->name = "Conventional Memory"; | 639 | res->name = "Conventional Memory"; |
642 | break; | 640 | break; |
643 | case EFI_UNUSABLE_MEMORY: | 641 | case EFI_UNUSABLE_MEMORY: |
644 | res->name = "Unusable Memory"; | 642 | res->name = "Unusable Memory"; |
645 | break; | 643 | break; |
646 | case EFI_ACPI_RECLAIM_MEMORY: | 644 | case EFI_ACPI_RECLAIM_MEMORY: |
647 | res->name = "ACPI Reclaim"; | 645 | res->name = "ACPI Reclaim"; |
648 | break; | 646 | break; |
649 | case EFI_ACPI_MEMORY_NVS: | 647 | case EFI_ACPI_MEMORY_NVS: |
650 | res->name = "ACPI NVS"; | 648 | res->name = "ACPI NVS"; |
651 | break; | 649 | break; |
652 | case EFI_MEMORY_MAPPED_IO: | 650 | case EFI_MEMORY_MAPPED_IO: |
653 | res->name = "Memory Mapped IO"; | 651 | res->name = "Memory Mapped IO"; |
654 | break; | 652 | break; |
655 | case EFI_MEMORY_MAPPED_IO_PORT_SPACE: | 653 | case EFI_MEMORY_MAPPED_IO_PORT_SPACE: |
656 | res->name = "Memory Mapped IO Port Space"; | 654 | res->name = "Memory Mapped IO Port Space"; |
657 | break; | 655 | break; |
658 | default: | 656 | default: |
659 | res->name = "Reserved"; | 657 | res->name = "Reserved"; |
660 | break; | 658 | break; |
661 | } | 659 | } |
662 | res->start = md->phys_addr; | 660 | res->start = md->phys_addr; |
663 | res->end = res->start + ((md->num_pages << EFI_PAGE_SHIFT) - 1); | 661 | res->end = res->start + ((md->num_pages << EFI_PAGE_SHIFT) - 1); |
664 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; | 662 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
665 | if (request_resource(&iomem_resource, res) < 0) | 663 | if (request_resource(&iomem_resource, res) < 0) |
666 | printk(KERN_ERR PFX "Failed to allocate res %s : " | 664 | printk(KERN_ERR PFX "Failed to allocate res %s : " |
667 | "0x%llx-0x%llx\n", res->name, | 665 | "0x%llx-0x%llx\n", res->name, |
668 | (unsigned long long)res->start, | 666 | (unsigned long long)res->start, |
669 | (unsigned long long)res->end); | 667 | (unsigned long long)res->end); |
670 | /* | 668 | /* |
671 | * We don't know which region contains kernel data so we try | 669 | * We don't know which region contains kernel data so we try |
672 | * it repeatedly and let the resource manager test it. | 670 | * it repeatedly and let the resource manager test it. |
673 | */ | 671 | */ |
674 | if (md->type == EFI_CONVENTIONAL_MEMORY) { | 672 | if (md->type == EFI_CONVENTIONAL_MEMORY) { |
675 | request_resource(res, code_resource); | 673 | request_resource(res, code_resource); |
676 | request_resource(res, data_resource); | 674 | request_resource(res, data_resource); |
677 | #ifdef CONFIG_KEXEC | 675 | #ifdef CONFIG_KEXEC |
678 | request_resource(res, &crashk_res); | 676 | request_resource(res, &crashk_res); |
679 | #endif | 677 | #endif |
680 | } | 678 | } |
681 | } | 679 | } |
682 | } | 680 | } |
683 | 681 | ||
684 | /* | 682 | /* |
685 | * Convenience functions to obtain memory types and attributes | 683 | * Convenience functions to obtain memory types and attributes |
686 | */ | 684 | */ |
687 | 685 | ||
688 | u32 efi_mem_type(unsigned long phys_addr) | 686 | u32 efi_mem_type(unsigned long phys_addr) |
689 | { | 687 | { |
690 | efi_memory_desc_t *md; | 688 | efi_memory_desc_t *md; |
691 | void *p; | 689 | void *p; |
692 | 690 | ||
693 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 691 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
694 | md = p; | 692 | md = p; |
695 | if ((md->phys_addr <= phys_addr) && (phys_addr < | 693 | if ((md->phys_addr <= phys_addr) && (phys_addr < |
696 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) | 694 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) |
697 | return md->type; | 695 | return md->type; |
698 | } | 696 | } |
699 | return 0; | 697 | return 0; |
700 | } | 698 | } |
701 | 699 | ||
702 | u64 efi_mem_attributes(unsigned long phys_addr) | 700 | u64 efi_mem_attributes(unsigned long phys_addr) |
703 | { | 701 | { |
704 | efi_memory_desc_t *md; | 702 | efi_memory_desc_t *md; |
705 | void *p; | 703 | void *p; |
706 | 704 | ||
707 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { | 705 | for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
708 | md = p; | 706 | md = p; |
709 | if ((md->phys_addr <= phys_addr) && (phys_addr < | 707 | if ((md->phys_addr <= phys_addr) && (phys_addr < |
710 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) | 708 | (md->phys_addr + (md-> num_pages << EFI_PAGE_SHIFT)) )) |
711 | return md->attribute; | 709 | return md->attribute; |
712 | } | 710 | } |
713 | return 0; | 711 | return 0; |
714 | } | 712 | } |
715 | 713 |
arch/ia64/hp/sim/boot/fw-emu.c
1 | /* | 1 | /* |
2 | * PAL & SAL emulation. | 2 | * PAL & SAL emulation. |
3 | * | 3 | * |
4 | * Copyright (C) 1998-2001 Hewlett-Packard Co | 4 | * Copyright (C) 1998-2001 Hewlett-Packard Co |
5 | * David Mosberger-Tang <davidm@hpl.hp.com> | 5 | * David Mosberger-Tang <davidm@hpl.hp.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifdef CONFIG_PCI | 8 | #ifdef CONFIG_PCI |
9 | # include <linux/pci.h> | 9 | # include <linux/pci.h> |
10 | #endif | 10 | #endif |
11 | 11 | ||
12 | #include <linux/efi.h> | 12 | #include <linux/efi.h> |
13 | #include <asm/io.h> | 13 | #include <asm/io.h> |
14 | #include <asm/pal.h> | 14 | #include <asm/pal.h> |
15 | #include <asm/sal.h> | 15 | #include <asm/sal.h> |
16 | 16 | ||
17 | #include "ssc.h" | 17 | #include "ssc.h" |
18 | 18 | ||
19 | #define MB (1024*1024UL) | 19 | #define MB (1024*1024UL) |
20 | 20 | ||
21 | #define SIMPLE_MEMMAP 1 | 21 | #define SIMPLE_MEMMAP 1 |
22 | 22 | ||
23 | #if SIMPLE_MEMMAP | 23 | #if SIMPLE_MEMMAP |
24 | # define NUM_MEM_DESCS 4 | 24 | # define NUM_MEM_DESCS 4 |
25 | #else | 25 | #else |
26 | # define NUM_MEM_DESCS 16 | 26 | # define NUM_MEM_DESCS 16 |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | static char fw_mem[( sizeof(struct ia64_boot_param) | 29 | static char fw_mem[( sizeof(struct ia64_boot_param) |
30 | + sizeof(efi_system_table_t) | 30 | + sizeof(efi_system_table_t) |
31 | + sizeof(efi_runtime_services_t) | 31 | + sizeof(efi_runtime_services_t) |
32 | + 1*sizeof(efi_config_table_t) | 32 | + 1*sizeof(efi_config_table_t) |
33 | + sizeof(struct ia64_sal_systab) | 33 | + sizeof(struct ia64_sal_systab) |
34 | + sizeof(struct ia64_sal_desc_entry_point) | 34 | + sizeof(struct ia64_sal_desc_entry_point) |
35 | + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t)) | 35 | + NUM_MEM_DESCS*(sizeof(efi_memory_desc_t)) |
36 | + 1024)] __attribute__ ((aligned (8))); | 36 | + 1024)] __attribute__ ((aligned (8))); |
37 | 37 | ||
38 | #define SECS_PER_HOUR (60 * 60) | 38 | #define SECS_PER_HOUR (60 * 60) |
39 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) | 39 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) |
40 | 40 | ||
41 | /* Compute the `struct tm' representation of *T, | 41 | /* Compute the `struct tm' representation of *T, |
42 | offset OFFSET seconds east of UTC, | 42 | offset OFFSET seconds east of UTC, |
43 | and store year, yday, mon, mday, wday, hour, min, sec into *TP. | 43 | and store year, yday, mon, mday, wday, hour, min, sec into *TP. |
44 | Return nonzero if successful. */ | 44 | Return nonzero if successful. */ |
45 | int | 45 | int |
46 | offtime (unsigned long t, efi_time_t *tp) | 46 | offtime (unsigned long t, efi_time_t *tp) |
47 | { | 47 | { |
48 | const unsigned short int __mon_yday[2][13] = | 48 | const unsigned short int __mon_yday[2][13] = |
49 | { | 49 | { |
50 | /* Normal years. */ | 50 | /* Normal years. */ |
51 | { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, | 51 | { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, |
52 | /* Leap years. */ | 52 | /* Leap years. */ |
53 | { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } | 53 | { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } |
54 | }; | 54 | }; |
55 | long int days, rem, y; | 55 | long int days, rem, y; |
56 | const unsigned short int *ip; | 56 | const unsigned short int *ip; |
57 | 57 | ||
58 | days = t / SECS_PER_DAY; | 58 | days = t / SECS_PER_DAY; |
59 | rem = t % SECS_PER_DAY; | 59 | rem = t % SECS_PER_DAY; |
60 | while (rem < 0) { | 60 | while (rem < 0) { |
61 | rem += SECS_PER_DAY; | 61 | rem += SECS_PER_DAY; |
62 | --days; | 62 | --days; |
63 | } | 63 | } |
64 | while (rem >= SECS_PER_DAY) { | 64 | while (rem >= SECS_PER_DAY) { |
65 | rem -= SECS_PER_DAY; | 65 | rem -= SECS_PER_DAY; |
66 | ++days; | 66 | ++days; |
67 | } | 67 | } |
68 | tp->hour = rem / SECS_PER_HOUR; | 68 | tp->hour = rem / SECS_PER_HOUR; |
69 | rem %= SECS_PER_HOUR; | 69 | rem %= SECS_PER_HOUR; |
70 | tp->minute = rem / 60; | 70 | tp->minute = rem / 60; |
71 | tp->second = rem % 60; | 71 | tp->second = rem % 60; |
72 | /* January 1, 1970 was a Thursday. */ | 72 | /* January 1, 1970 was a Thursday. */ |
73 | y = 1970; | 73 | y = 1970; |
74 | 74 | ||
75 | # define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) | 75 | # define DIV(a, b) ((a) / (b) - ((a) % (b) < 0)) |
76 | # define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) | 76 | # define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400)) |
77 | # define __isleap(year) \ | 77 | # define __isleap(year) \ |
78 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) | 78 | ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) |
79 | 79 | ||
80 | while (days < 0 || days >= (__isleap (y) ? 366 : 365)) { | 80 | while (days < 0 || days >= (__isleap (y) ? 366 : 365)) { |
81 | /* Guess a corrected year, assuming 365 days per year. */ | 81 | /* Guess a corrected year, assuming 365 days per year. */ |
82 | long int yg = y + days / 365 - (days % 365 < 0); | 82 | long int yg = y + days / 365 - (days % 365 < 0); |
83 | 83 | ||
84 | /* Adjust DAYS and Y to match the guessed year. */ | 84 | /* Adjust DAYS and Y to match the guessed year. */ |
85 | days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1) | 85 | days -= ((yg - y) * 365 + LEAPS_THRU_END_OF (yg - 1) |
86 | - LEAPS_THRU_END_OF (y - 1)); | 86 | - LEAPS_THRU_END_OF (y - 1)); |
87 | y = yg; | 87 | y = yg; |
88 | } | 88 | } |
89 | tp->year = y; | 89 | tp->year = y; |
90 | ip = __mon_yday[__isleap(y)]; | 90 | ip = __mon_yday[__isleap(y)]; |
91 | for (y = 11; days < (long int) ip[y]; --y) | 91 | for (y = 11; days < (long int) ip[y]; --y) |
92 | continue; | 92 | continue; |
93 | days -= ip[y]; | 93 | days -= ip[y]; |
94 | tp->month = y + 1; | 94 | tp->month = y + 1; |
95 | tp->day = days + 1; | 95 | tp->day = days + 1; |
96 | return 1; | 96 | return 1; |
97 | } | 97 | } |
98 | 98 | ||
99 | extern void pal_emulator_static (void); | 99 | extern void pal_emulator_static (void); |
100 | 100 | ||
101 | /* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */ | 101 | /* Macro to emulate SAL call using legacy IN and OUT calls to CF8, CFC etc.. */ |
102 | 102 | ||
103 | #define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3) | 103 | #define BUILD_CMD(addr) ((0x80000000 | (addr)) & ~3) |
104 | 104 | ||
105 | #define REG_OFFSET(addr) (0x00000000000000FF & (addr)) | 105 | #define REG_OFFSET(addr) (0x00000000000000FF & (addr)) |
106 | #define DEVICE_FUNCTION(addr) (0x000000000000FF00 & (addr)) | 106 | #define DEVICE_FUNCTION(addr) (0x000000000000FF00 & (addr)) |
107 | #define BUS_NUMBER(addr) (0x0000000000FF0000 & (addr)) | 107 | #define BUS_NUMBER(addr) (0x0000000000FF0000 & (addr)) |
108 | 108 | ||
109 | static efi_status_t | 109 | static efi_status_t |
110 | fw_efi_get_time (efi_time_t *tm, efi_time_cap_t *tc) | 110 | fw_efi_get_time (efi_time_t *tm, efi_time_cap_t *tc) |
111 | { | 111 | { |
112 | #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC) | 112 | #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC) |
113 | struct { | 113 | struct { |
114 | int tv_sec; /* must be 32bits to work */ | 114 | int tv_sec; /* must be 32bits to work */ |
115 | int tv_usec; | 115 | int tv_usec; |
116 | } tv32bits; | 116 | } tv32bits; |
117 | 117 | ||
118 | ssc((unsigned long) &tv32bits, 0, 0, 0, SSC_GET_TOD); | 118 | ssc((unsigned long) &tv32bits, 0, 0, 0, SSC_GET_TOD); |
119 | 119 | ||
120 | memset(tm, 0, sizeof(*tm)); | 120 | memset(tm, 0, sizeof(*tm)); |
121 | offtime(tv32bits.tv_sec, tm); | 121 | offtime(tv32bits.tv_sec, tm); |
122 | 122 | ||
123 | if (tc) | 123 | if (tc) |
124 | memset(tc, 0, sizeof(*tc)); | 124 | memset(tc, 0, sizeof(*tc)); |
125 | #else | 125 | #else |
126 | # error Not implemented yet... | 126 | # error Not implemented yet... |
127 | #endif | 127 | #endif |
128 | return EFI_SUCCESS; | 128 | return EFI_SUCCESS; |
129 | } | 129 | } |
130 | 130 | ||
131 | static void | 131 | static void |
132 | efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data) | 132 | efi_reset_system (int reset_type, efi_status_t status, unsigned long data_size, efi_char16_t *data) |
133 | { | 133 | { |
134 | #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC) | 134 | #if defined(CONFIG_IA64_HP_SIM) || defined(CONFIG_IA64_GENERIC) |
135 | ssc(status, 0, 0, 0, SSC_EXIT); | 135 | ssc(status, 0, 0, 0, SSC_EXIT); |
136 | #else | 136 | #else |
137 | # error Not implemented yet... | 137 | # error Not implemented yet... |
138 | #endif | 138 | #endif |
139 | } | 139 | } |
140 | 140 | ||
141 | static efi_status_t | 141 | static efi_status_t |
142 | efi_unimplemented (void) | 142 | efi_unimplemented (void) |
143 | { | 143 | { |
144 | return EFI_UNSUPPORTED; | 144 | return EFI_UNSUPPORTED; |
145 | } | 145 | } |
146 | 146 | ||
147 | static struct sal_ret_values | 147 | static struct sal_ret_values |
148 | sal_emulator (long index, unsigned long in1, unsigned long in2, | 148 | sal_emulator (long index, unsigned long in1, unsigned long in2, |
149 | unsigned long in3, unsigned long in4, unsigned long in5, | 149 | unsigned long in3, unsigned long in4, unsigned long in5, |
150 | unsigned long in6, unsigned long in7) | 150 | unsigned long in6, unsigned long in7) |
151 | { | 151 | { |
152 | long r9 = 0; | 152 | long r9 = 0; |
153 | long r10 = 0; | 153 | long r10 = 0; |
154 | long r11 = 0; | 154 | long r11 = 0; |
155 | long status; | 155 | long status; |
156 | 156 | ||
157 | /* | 157 | /* |
158 | * Don't do a "switch" here since that gives us code that | 158 | * Don't do a "switch" here since that gives us code that |
159 | * isn't self-relocatable. | 159 | * isn't self-relocatable. |
160 | */ | 160 | */ |
161 | status = 0; | 161 | status = 0; |
162 | if (index == SAL_FREQ_BASE) { | 162 | if (index == SAL_FREQ_BASE) { |
163 | switch (in1) { | 163 | switch (in1) { |
164 | case SAL_FREQ_BASE_PLATFORM: | 164 | case SAL_FREQ_BASE_PLATFORM: |
165 | r9 = 200000000; | 165 | r9 = 200000000; |
166 | break; | 166 | break; |
167 | 167 | ||
168 | case SAL_FREQ_BASE_INTERVAL_TIMER: | 168 | case SAL_FREQ_BASE_INTERVAL_TIMER: |
169 | /* | 169 | /* |
170 | * Is this supposed to be the cr.itc frequency | 170 | * Is this supposed to be the cr.itc frequency |
171 | * or something platform specific? The SAL | 171 | * or something platform specific? The SAL |
172 | * doc ain't exactly clear on this... | 172 | * doc ain't exactly clear on this... |
173 | */ | 173 | */ |
174 | r9 = 700000000; | 174 | r9 = 700000000; |
175 | break; | 175 | break; |
176 | 176 | ||
177 | case SAL_FREQ_BASE_REALTIME_CLOCK: | 177 | case SAL_FREQ_BASE_REALTIME_CLOCK: |
178 | r9 = 1; | 178 | r9 = 1; |
179 | break; | 179 | break; |
180 | 180 | ||
181 | default: | 181 | default: |
182 | status = -1; | 182 | status = -1; |
183 | break; | 183 | break; |
184 | } | 184 | } |
185 | } else if (index == SAL_SET_VECTORS) { | 185 | } else if (index == SAL_SET_VECTORS) { |
186 | ; | 186 | ; |
187 | } else if (index == SAL_GET_STATE_INFO) { | 187 | } else if (index == SAL_GET_STATE_INFO) { |
188 | ; | 188 | ; |
189 | } else if (index == SAL_GET_STATE_INFO_SIZE) { | 189 | } else if (index == SAL_GET_STATE_INFO_SIZE) { |
190 | ; | 190 | ; |
191 | } else if (index == SAL_CLEAR_STATE_INFO) { | 191 | } else if (index == SAL_CLEAR_STATE_INFO) { |
192 | ; | 192 | ; |
193 | } else if (index == SAL_MC_RENDEZ) { | 193 | } else if (index == SAL_MC_RENDEZ) { |
194 | ; | 194 | ; |
195 | } else if (index == SAL_MC_SET_PARAMS) { | 195 | } else if (index == SAL_MC_SET_PARAMS) { |
196 | ; | 196 | ; |
197 | } else if (index == SAL_CACHE_FLUSH) { | 197 | } else if (index == SAL_CACHE_FLUSH) { |
198 | ; | 198 | ; |
199 | } else if (index == SAL_CACHE_INIT) { | 199 | } else if (index == SAL_CACHE_INIT) { |
200 | ; | 200 | ; |
201 | #ifdef CONFIG_PCI | 201 | #ifdef CONFIG_PCI |
202 | } else if (index == SAL_PCI_CONFIG_READ) { | 202 | } else if (index == SAL_PCI_CONFIG_READ) { |
203 | /* | 203 | /* |
204 | * in1 contains the PCI configuration address and in2 | 204 | * in1 contains the PCI configuration address and in2 |
205 | * the size of the read. The value that is read is | 205 | * the size of the read. The value that is read is |
206 | * returned via the general register r9. | 206 | * returned via the general register r9. |
207 | */ | 207 | */ |
208 | outl(BUILD_CMD(in1), 0xCF8); | 208 | outl(BUILD_CMD(in1), 0xCF8); |
209 | if (in2 == 1) /* Reading byte */ | 209 | if (in2 == 1) /* Reading byte */ |
210 | r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3))); | 210 | r9 = inb(0xCFC + ((REG_OFFSET(in1) & 3))); |
211 | else if (in2 == 2) /* Reading word */ | 211 | else if (in2 == 2) /* Reading word */ |
212 | r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2))); | 212 | r9 = inw(0xCFC + ((REG_OFFSET(in1) & 2))); |
213 | else /* Reading dword */ | 213 | else /* Reading dword */ |
214 | r9 = inl(0xCFC); | 214 | r9 = inl(0xCFC); |
215 | status = PCIBIOS_SUCCESSFUL; | 215 | status = PCIBIOS_SUCCESSFUL; |
216 | } else if (index == SAL_PCI_CONFIG_WRITE) { | 216 | } else if (index == SAL_PCI_CONFIG_WRITE) { |
217 | /* | 217 | /* |
218 | * in1 contains the PCI configuration address, in2 the | 218 | * in1 contains the PCI configuration address, in2 the |
219 | * size of the write, and in3 the actual value to be | 219 | * size of the write, and in3 the actual value to be |
220 | * written out. | 220 | * written out. |
221 | */ | 221 | */ |
222 | outl(BUILD_CMD(in1), 0xCF8); | 222 | outl(BUILD_CMD(in1), 0xCF8); |
223 | if (in2 == 1) /* Writing byte */ | 223 | if (in2 == 1) /* Writing byte */ |
224 | outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3))); | 224 | outb(in3, 0xCFC + ((REG_OFFSET(in1) & 3))); |
225 | else if (in2 == 2) /* Writing word */ | 225 | else if (in2 == 2) /* Writing word */ |
226 | outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2))); | 226 | outw(in3, 0xCFC + ((REG_OFFSET(in1) & 2))); |
227 | else /* Writing dword */ | 227 | else /* Writing dword */ |
228 | outl(in3, 0xCFC); | 228 | outl(in3, 0xCFC); |
229 | status = PCIBIOS_SUCCESSFUL; | 229 | status = PCIBIOS_SUCCESSFUL; |
230 | #endif /* CONFIG_PCI */ | 230 | #endif /* CONFIG_PCI */ |
231 | } else if (index == SAL_UPDATE_PAL) { | 231 | } else if (index == SAL_UPDATE_PAL) { |
232 | ; | 232 | ; |
233 | } else { | 233 | } else { |
234 | status = -1; | 234 | status = -1; |
235 | } | 235 | } |
236 | return ((struct sal_ret_values) {status, r9, r10, r11}); | 236 | return ((struct sal_ret_values) {status, r9, r10, r11}); |
237 | } | 237 | } |
238 | 238 | ||
239 | struct ia64_boot_param * | 239 | struct ia64_boot_param * |
240 | sys_fw_init (const char *args, int arglen) | 240 | sys_fw_init (const char *args, int arglen) |
241 | { | 241 | { |
242 | efi_system_table_t *efi_systab; | 242 | efi_system_table_t *efi_systab; |
243 | efi_runtime_services_t *efi_runtime; | 243 | efi_runtime_services_t *efi_runtime; |
244 | efi_config_table_t *efi_tables; | 244 | efi_config_table_t *efi_tables; |
245 | struct ia64_sal_systab *sal_systab; | 245 | struct ia64_sal_systab *sal_systab; |
246 | efi_memory_desc_t *efi_memmap, *md; | 246 | efi_memory_desc_t *efi_memmap, *md; |
247 | unsigned long *pal_desc, *sal_desc; | 247 | unsigned long *pal_desc, *sal_desc; |
248 | struct ia64_sal_desc_entry_point *sal_ed; | 248 | struct ia64_sal_desc_entry_point *sal_ed; |
249 | struct ia64_boot_param *bp; | 249 | struct ia64_boot_param *bp; |
250 | unsigned char checksum = 0; | 250 | unsigned char checksum = 0; |
251 | char *cp, *cmd_line; | 251 | char *cp, *cmd_line; |
252 | int i = 0; | 252 | int i = 0; |
253 | # define MAKE_MD(typ, attr, start, end) \ | 253 | # define MAKE_MD(typ, attr, start, end) \ |
254 | do { \ | 254 | do { \ |
255 | md = efi_memmap + i++; \ | 255 | md = efi_memmap + i++; \ |
256 | md->type = typ; \ | 256 | md->type = typ; \ |
257 | md->pad = 0; \ | 257 | md->pad = 0; \ |
258 | md->phys_addr = start; \ | 258 | md->phys_addr = start; \ |
259 | md->virt_addr = 0; \ | 259 | md->virt_addr = 0; \ |
260 | md->num_pages = (end - start) >> 12; \ | 260 | md->num_pages = (end - start) >> 12; \ |
261 | md->attribute = attr; \ | 261 | md->attribute = attr; \ |
262 | } while (0) | 262 | } while (0) |
263 | 263 | ||
264 | memset(fw_mem, 0, sizeof(fw_mem)); | 264 | memset(fw_mem, 0, sizeof(fw_mem)); |
265 | 265 | ||
266 | pal_desc = (unsigned long *) &pal_emulator_static; | 266 | pal_desc = (unsigned long *) &pal_emulator_static; |
267 | sal_desc = (unsigned long *) &sal_emulator; | 267 | sal_desc = (unsigned long *) &sal_emulator; |
268 | 268 | ||
269 | cp = fw_mem; | 269 | cp = fw_mem; |
270 | efi_systab = (void *) cp; cp += sizeof(*efi_systab); | 270 | efi_systab = (void *) cp; cp += sizeof(*efi_systab); |
271 | efi_runtime = (void *) cp; cp += sizeof(*efi_runtime); | 271 | efi_runtime = (void *) cp; cp += sizeof(*efi_runtime); |
272 | efi_tables = (void *) cp; cp += sizeof(*efi_tables); | 272 | efi_tables = (void *) cp; cp += sizeof(*efi_tables); |
273 | sal_systab = (void *) cp; cp += sizeof(*sal_systab); | 273 | sal_systab = (void *) cp; cp += sizeof(*sal_systab); |
274 | sal_ed = (void *) cp; cp += sizeof(*sal_ed); | 274 | sal_ed = (void *) cp; cp += sizeof(*sal_ed); |
275 | efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap); | 275 | efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap); |
276 | bp = (void *) cp; cp += sizeof(*bp); | 276 | bp = (void *) cp; cp += sizeof(*bp); |
277 | cmd_line = (void *) cp; | 277 | cmd_line = (void *) cp; |
278 | 278 | ||
279 | if (args) { | 279 | if (args) { |
280 | if (arglen >= 1024) | 280 | if (arglen >= 1024) |
281 | arglen = 1023; | 281 | arglen = 1023; |
282 | memcpy(cmd_line, args, arglen); | 282 | memcpy(cmd_line, args, arglen); |
283 | } else { | 283 | } else { |
284 | arglen = 0; | 284 | arglen = 0; |
285 | } | 285 | } |
286 | cmd_line[arglen] = '\0'; | 286 | cmd_line[arglen] = '\0'; |
287 | 287 | ||
288 | memset(efi_systab, 0, sizeof(efi_systab)); | 288 | memset(efi_systab, 0, sizeof(efi_systab)); |
289 | efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; | 289 | efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; |
290 | efi_systab->hdr.revision = EFI_SYSTEM_TABLE_REVISION; | 290 | efi_systab->hdr.revision = ((1 << 16) | 00); |
291 | efi_systab->hdr.headersize = sizeof(efi_systab->hdr); | 291 | efi_systab->hdr.headersize = sizeof(efi_systab->hdr); |
292 | efi_systab->fw_vendor = __pa("H\0e\0w\0l\0e\0t\0t\0-\0P\0a\0c\0k\0a\0r\0d\0\0"); | 292 | efi_systab->fw_vendor = __pa("H\0e\0w\0l\0e\0t\0t\0-\0P\0a\0c\0k\0a\0r\0d\0\0"); |
293 | efi_systab->fw_revision = 1; | 293 | efi_systab->fw_revision = 1; |
294 | efi_systab->runtime = (void *) __pa(efi_runtime); | 294 | efi_systab->runtime = (void *) __pa(efi_runtime); |
295 | efi_systab->nr_tables = 1; | 295 | efi_systab->nr_tables = 1; |
296 | efi_systab->tables = __pa(efi_tables); | 296 | efi_systab->tables = __pa(efi_tables); |
297 | 297 | ||
298 | efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; | 298 | efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; |
299 | efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION; | 299 | efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION; |
300 | efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr); | 300 | efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr); |
301 | efi_runtime->get_time = __pa(&fw_efi_get_time); | 301 | efi_runtime->get_time = __pa(&fw_efi_get_time); |
302 | efi_runtime->set_time = __pa(&efi_unimplemented); | 302 | efi_runtime->set_time = __pa(&efi_unimplemented); |
303 | efi_runtime->get_wakeup_time = __pa(&efi_unimplemented); | 303 | efi_runtime->get_wakeup_time = __pa(&efi_unimplemented); |
304 | efi_runtime->set_wakeup_time = __pa(&efi_unimplemented); | 304 | efi_runtime->set_wakeup_time = __pa(&efi_unimplemented); |
305 | efi_runtime->set_virtual_address_map = __pa(&efi_unimplemented); | 305 | efi_runtime->set_virtual_address_map = __pa(&efi_unimplemented); |
306 | efi_runtime->get_variable = __pa(&efi_unimplemented); | 306 | efi_runtime->get_variable = __pa(&efi_unimplemented); |
307 | efi_runtime->get_next_variable = __pa(&efi_unimplemented); | 307 | efi_runtime->get_next_variable = __pa(&efi_unimplemented); |
308 | efi_runtime->set_variable = __pa(&efi_unimplemented); | 308 | efi_runtime->set_variable = __pa(&efi_unimplemented); |
309 | efi_runtime->get_next_high_mono_count = __pa(&efi_unimplemented); | 309 | efi_runtime->get_next_high_mono_count = __pa(&efi_unimplemented); |
310 | efi_runtime->reset_system = __pa(&efi_reset_system); | 310 | efi_runtime->reset_system = __pa(&efi_reset_system); |
311 | 311 | ||
312 | efi_tables->guid = SAL_SYSTEM_TABLE_GUID; | 312 | efi_tables->guid = SAL_SYSTEM_TABLE_GUID; |
313 | efi_tables->table = __pa(sal_systab); | 313 | efi_tables->table = __pa(sal_systab); |
314 | 314 | ||
315 | /* fill in the SAL system table: */ | 315 | /* fill in the SAL system table: */ |
316 | memcpy(sal_systab->signature, "SST_", 4); | 316 | memcpy(sal_systab->signature, "SST_", 4); |
317 | sal_systab->size = sizeof(*sal_systab); | 317 | sal_systab->size = sizeof(*sal_systab); |
318 | sal_systab->sal_rev_minor = 1; | 318 | sal_systab->sal_rev_minor = 1; |
319 | sal_systab->sal_rev_major = 0; | 319 | sal_systab->sal_rev_major = 0; |
320 | sal_systab->entry_count = 1; | 320 | sal_systab->entry_count = 1; |
321 | 321 | ||
322 | #ifdef CONFIG_IA64_GENERIC | 322 | #ifdef CONFIG_IA64_GENERIC |
323 | strcpy(sal_systab->oem_id, "Generic"); | 323 | strcpy(sal_systab->oem_id, "Generic"); |
324 | strcpy(sal_systab->product_id, "IA-64 system"); | 324 | strcpy(sal_systab->product_id, "IA-64 system"); |
325 | #endif | 325 | #endif |
326 | 326 | ||
327 | #ifdef CONFIG_IA64_HP_SIM | 327 | #ifdef CONFIG_IA64_HP_SIM |
328 | strcpy(sal_systab->oem_id, "Hewlett-Packard"); | 328 | strcpy(sal_systab->oem_id, "Hewlett-Packard"); |
329 | strcpy(sal_systab->product_id, "HP-simulator"); | 329 | strcpy(sal_systab->product_id, "HP-simulator"); |
330 | #endif | 330 | #endif |
331 | 331 | ||
332 | #ifdef CONFIG_IA64_SDV | 332 | #ifdef CONFIG_IA64_SDV |
333 | strcpy(sal_systab->oem_id, "Intel"); | 333 | strcpy(sal_systab->oem_id, "Intel"); |
334 | strcpy(sal_systab->product_id, "SDV"); | 334 | strcpy(sal_systab->product_id, "SDV"); |
335 | #endif | 335 | #endif |
336 | 336 | ||
337 | /* fill in an entry point: */ | 337 | /* fill in an entry point: */ |
338 | sal_ed->type = SAL_DESC_ENTRY_POINT; | 338 | sal_ed->type = SAL_DESC_ENTRY_POINT; |
339 | sal_ed->pal_proc = __pa(pal_desc[0]); | 339 | sal_ed->pal_proc = __pa(pal_desc[0]); |
340 | sal_ed->sal_proc = __pa(sal_desc[0]); | 340 | sal_ed->sal_proc = __pa(sal_desc[0]); |
341 | sal_ed->gp = __pa(sal_desc[1]); | 341 | sal_ed->gp = __pa(sal_desc[1]); |
342 | 342 | ||
343 | for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp) | 343 | for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp) |
344 | checksum += *cp; | 344 | checksum += *cp; |
345 | 345 | ||
346 | sal_systab->checksum = -checksum; | 346 | sal_systab->checksum = -checksum; |
347 | 347 | ||
348 | #if SIMPLE_MEMMAP | 348 | #if SIMPLE_MEMMAP |
349 | /* simulate free memory at physical address zero */ | 349 | /* simulate free memory at physical address zero */ |
350 | MAKE_MD(EFI_BOOT_SERVICES_DATA, EFI_MEMORY_WB, 0*MB, 1*MB); | 350 | MAKE_MD(EFI_BOOT_SERVICES_DATA, EFI_MEMORY_WB, 0*MB, 1*MB); |
351 | MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB, 1*MB, 2*MB); | 351 | MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB, 1*MB, 2*MB); |
352 | MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 2*MB, 130*MB); | 352 | MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 2*MB, 130*MB); |
353 | MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 4096*MB, 4128*MB); | 353 | MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, 4096*MB, 4128*MB); |
354 | #else | 354 | #else |
355 | MAKE_MD( 4, 0x9, 0x0000000000000000, 0x0000000000001000); | 355 | MAKE_MD( 4, 0x9, 0x0000000000000000, 0x0000000000001000); |
356 | MAKE_MD( 7, 0x9, 0x0000000000001000, 0x000000000008a000); | 356 | MAKE_MD( 7, 0x9, 0x0000000000001000, 0x000000000008a000); |
357 | MAKE_MD( 4, 0x9, 0x000000000008a000, 0x00000000000a0000); | 357 | MAKE_MD( 4, 0x9, 0x000000000008a000, 0x00000000000a0000); |
358 | MAKE_MD( 5, 0x8000000000000009, 0x00000000000c0000, 0x0000000000100000); | 358 | MAKE_MD( 5, 0x8000000000000009, 0x00000000000c0000, 0x0000000000100000); |
359 | MAKE_MD( 7, 0x9, 0x0000000000100000, 0x0000000004400000); | 359 | MAKE_MD( 7, 0x9, 0x0000000000100000, 0x0000000004400000); |
360 | MAKE_MD( 2, 0x9, 0x0000000004400000, 0x0000000004be5000); | 360 | MAKE_MD( 2, 0x9, 0x0000000004400000, 0x0000000004be5000); |
361 | MAKE_MD( 7, 0x9, 0x0000000004be5000, 0x000000007f77e000); | 361 | MAKE_MD( 7, 0x9, 0x0000000004be5000, 0x000000007f77e000); |
362 | MAKE_MD( 6, 0x8000000000000009, 0x000000007f77e000, 0x000000007fb94000); | 362 | MAKE_MD( 6, 0x8000000000000009, 0x000000007f77e000, 0x000000007fb94000); |
363 | MAKE_MD( 6, 0x8000000000000009, 0x000000007fb94000, 0x000000007fb95000); | 363 | MAKE_MD( 6, 0x8000000000000009, 0x000000007fb94000, 0x000000007fb95000); |
364 | MAKE_MD( 6, 0x8000000000000009, 0x000000007fb95000, 0x000000007fc00000); | 364 | MAKE_MD( 6, 0x8000000000000009, 0x000000007fb95000, 0x000000007fc00000); |
365 | MAKE_MD(13, 0x8000000000000009, 0x000000007fc00000, 0x000000007fc3a000); | 365 | MAKE_MD(13, 0x8000000000000009, 0x000000007fc00000, 0x000000007fc3a000); |
366 | MAKE_MD( 7, 0x9, 0x000000007fc3a000, 0x000000007fea0000); | 366 | MAKE_MD( 7, 0x9, 0x000000007fc3a000, 0x000000007fea0000); |
367 | MAKE_MD( 5, 0x8000000000000009, 0x000000007fea0000, 0x000000007fea8000); | 367 | MAKE_MD( 5, 0x8000000000000009, 0x000000007fea0000, 0x000000007fea8000); |
368 | MAKE_MD( 7, 0x9, 0x000000007fea8000, 0x000000007feab000); | 368 | MAKE_MD( 7, 0x9, 0x000000007fea8000, 0x000000007feab000); |
369 | MAKE_MD( 5, 0x8000000000000009, 0x000000007feab000, 0x000000007ffff000); | 369 | MAKE_MD( 5, 0x8000000000000009, 0x000000007feab000, 0x000000007ffff000); |
370 | MAKE_MD( 7, 0x9, 0x00000000ff400000, 0x0000000104000000); | 370 | MAKE_MD( 7, 0x9, 0x00000000ff400000, 0x0000000104000000); |
371 | #endif | 371 | #endif |
372 | 372 | ||
373 | bp->efi_systab = __pa(&fw_mem); | 373 | bp->efi_systab = __pa(&fw_mem); |
374 | bp->efi_memmap = __pa(efi_memmap); | 374 | bp->efi_memmap = __pa(efi_memmap); |
375 | bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t); | 375 | bp->efi_memmap_size = NUM_MEM_DESCS*sizeof(efi_memory_desc_t); |
376 | bp->efi_memdesc_size = sizeof(efi_memory_desc_t); | 376 | bp->efi_memdesc_size = sizeof(efi_memory_desc_t); |
377 | bp->efi_memdesc_version = 1; | 377 | bp->efi_memdesc_version = 1; |
378 | bp->command_line = __pa(cmd_line); | 378 | bp->command_line = __pa(cmd_line); |
379 | bp->console_info.num_cols = 80; | 379 | bp->console_info.num_cols = 80; |
380 | bp->console_info.num_rows = 25; | 380 | bp->console_info.num_rows = 25; |
381 | bp->console_info.orig_x = 0; | 381 | bp->console_info.orig_x = 0; |
382 | bp->console_info.orig_y = 24; | 382 | bp->console_info.orig_y = 24; |
383 | bp->fpswa = 0; | 383 | bp->fpswa = 0; |
384 | 384 | ||
385 | return bp; | 385 | return bp; |
386 | } | 386 | } |
387 | 387 |
arch/ia64/kernel/efi.c
1 | /* | 1 | /* |
2 | * Extensible Firmware Interface | 2 | * Extensible Firmware Interface |
3 | * | 3 | * |
4 | * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999 | 4 | * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999 |
5 | * | 5 | * |
6 | * Copyright (C) 1999 VA Linux Systems | 6 | * Copyright (C) 1999 VA Linux Systems |
7 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | 7 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> |
8 | * Copyright (C) 1999-2003 Hewlett-Packard Co. | 8 | * Copyright (C) 1999-2003 Hewlett-Packard Co. |
9 | * David Mosberger-Tang <davidm@hpl.hp.com> | 9 | * David Mosberger-Tang <davidm@hpl.hp.com> |
10 | * Stephane Eranian <eranian@hpl.hp.com> | 10 | * Stephane Eranian <eranian@hpl.hp.com> |
11 | * (c) Copyright 2006 Hewlett-Packard Development Company, L.P. | 11 | * (c) Copyright 2006 Hewlett-Packard Development Company, L.P. |
12 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | 12 | * Bjorn Helgaas <bjorn.helgaas@hp.com> |
13 | * | 13 | * |
14 | * All EFI Runtime Services are not implemented yet as EFI only | 14 | * All EFI Runtime Services are not implemented yet as EFI only |
15 | * supports physical mode addressing on SoftSDV. This is to be fixed | 15 | * supports physical mode addressing on SoftSDV. This is to be fixed |
16 | * in a future version. --drummond 1999-07-20 | 16 | * in a future version. --drummond 1999-07-20 |
17 | * | 17 | * |
18 | * Implemented EFI runtime services and virtual mode calls. --davidm | 18 | * Implemented EFI runtime services and virtual mode calls. --davidm |
19 | * | 19 | * |
20 | * Goutham Rao: <goutham.rao@intel.com> | 20 | * Goutham Rao: <goutham.rao@intel.com> |
21 | * Skip non-WB memory and ignore empty memory ranges. | 21 | * Skip non-WB memory and ignore empty memory ranges. |
22 | */ | 22 | */ |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/bootmem.h> | 24 | #include <linux/bootmem.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/time.h> | 28 | #include <linux/time.h> |
29 | #include <linux/efi.h> | 29 | #include <linux/efi.h> |
30 | #include <linux/kexec.h> | 30 | #include <linux/kexec.h> |
31 | 31 | ||
32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
33 | #include <asm/kregs.h> | 33 | #include <asm/kregs.h> |
34 | #include <asm/meminit.h> | 34 | #include <asm/meminit.h> |
35 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
36 | #include <asm/processor.h> | 36 | #include <asm/processor.h> |
37 | #include <asm/mca.h> | 37 | #include <asm/mca.h> |
38 | 38 | ||
39 | #define EFI_DEBUG 0 | 39 | #define EFI_DEBUG 0 |
40 | 40 | ||
41 | extern efi_status_t efi_call_phys (void *, ...); | 41 | extern efi_status_t efi_call_phys (void *, ...); |
42 | 42 | ||
43 | struct efi efi; | 43 | struct efi efi; |
44 | EXPORT_SYMBOL(efi); | 44 | EXPORT_SYMBOL(efi); |
45 | static efi_runtime_services_t *runtime; | 45 | static efi_runtime_services_t *runtime; |
46 | static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; | 46 | static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; |
47 | 47 | ||
48 | #define efi_call_virt(f, args...) (*(f))(args) | 48 | #define efi_call_virt(f, args...) (*(f))(args) |
49 | 49 | ||
50 | #define STUB_GET_TIME(prefix, adjust_arg) \ | 50 | #define STUB_GET_TIME(prefix, adjust_arg) \ |
51 | static efi_status_t \ | 51 | static efi_status_t \ |
52 | prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ | 52 | prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ |
53 | { \ | 53 | { \ |
54 | struct ia64_fpreg fr[6]; \ | 54 | struct ia64_fpreg fr[6]; \ |
55 | efi_time_cap_t *atc = NULL; \ | 55 | efi_time_cap_t *atc = NULL; \ |
56 | efi_status_t ret; \ | 56 | efi_status_t ret; \ |
57 | \ | 57 | \ |
58 | if (tc) \ | 58 | if (tc) \ |
59 | atc = adjust_arg(tc); \ | 59 | atc = adjust_arg(tc); \ |
60 | ia64_save_scratch_fpregs(fr); \ | 60 | ia64_save_scratch_fpregs(fr); \ |
61 | ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \ | 61 | ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \ |
62 | ia64_load_scratch_fpregs(fr); \ | 62 | ia64_load_scratch_fpregs(fr); \ |
63 | return ret; \ | 63 | return ret; \ |
64 | } | 64 | } |
65 | 65 | ||
66 | #define STUB_SET_TIME(prefix, adjust_arg) \ | 66 | #define STUB_SET_TIME(prefix, adjust_arg) \ |
67 | static efi_status_t \ | 67 | static efi_status_t \ |
68 | prefix##_set_time (efi_time_t *tm) \ | 68 | prefix##_set_time (efi_time_t *tm) \ |
69 | { \ | 69 | { \ |
70 | struct ia64_fpreg fr[6]; \ | 70 | struct ia64_fpreg fr[6]; \ |
71 | efi_status_t ret; \ | 71 | efi_status_t ret; \ |
72 | \ | 72 | \ |
73 | ia64_save_scratch_fpregs(fr); \ | 73 | ia64_save_scratch_fpregs(fr); \ |
74 | ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \ | 74 | ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \ |
75 | ia64_load_scratch_fpregs(fr); \ | 75 | ia64_load_scratch_fpregs(fr); \ |
76 | return ret; \ | 76 | return ret; \ |
77 | } | 77 | } |
78 | 78 | ||
79 | #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \ | 79 | #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \ |
80 | static efi_status_t \ | 80 | static efi_status_t \ |
81 | prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \ | 81 | prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \ |
82 | { \ | 82 | { \ |
83 | struct ia64_fpreg fr[6]; \ | 83 | struct ia64_fpreg fr[6]; \ |
84 | efi_status_t ret; \ | 84 | efi_status_t ret; \ |
85 | \ | 85 | \ |
86 | ia64_save_scratch_fpregs(fr); \ | 86 | ia64_save_scratch_fpregs(fr); \ |
87 | ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \ | 87 | ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \ |
88 | adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \ | 88 | adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \ |
89 | ia64_load_scratch_fpregs(fr); \ | 89 | ia64_load_scratch_fpregs(fr); \ |
90 | return ret; \ | 90 | return ret; \ |
91 | } | 91 | } |
92 | 92 | ||
93 | #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \ | 93 | #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \ |
94 | static efi_status_t \ | 94 | static efi_status_t \ |
95 | prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ | 95 | prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ |
96 | { \ | 96 | { \ |
97 | struct ia64_fpreg fr[6]; \ | 97 | struct ia64_fpreg fr[6]; \ |
98 | efi_time_t *atm = NULL; \ | 98 | efi_time_t *atm = NULL; \ |
99 | efi_status_t ret; \ | 99 | efi_status_t ret; \ |
100 | \ | 100 | \ |
101 | if (tm) \ | 101 | if (tm) \ |
102 | atm = adjust_arg(tm); \ | 102 | atm = adjust_arg(tm); \ |
103 | ia64_save_scratch_fpregs(fr); \ | 103 | ia64_save_scratch_fpregs(fr); \ |
104 | ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ | 104 | ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ |
105 | enabled, atm); \ | 105 | enabled, atm); \ |
106 | ia64_load_scratch_fpregs(fr); \ | 106 | ia64_load_scratch_fpregs(fr); \ |
107 | return ret; \ | 107 | return ret; \ |
108 | } | 108 | } |
109 | 109 | ||
110 | #define STUB_GET_VARIABLE(prefix, adjust_arg) \ | 110 | #define STUB_GET_VARIABLE(prefix, adjust_arg) \ |
111 | static efi_status_t \ | 111 | static efi_status_t \ |
112 | prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ | 112 | prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ |
113 | unsigned long *data_size, void *data) \ | 113 | unsigned long *data_size, void *data) \ |
114 | { \ | 114 | { \ |
115 | struct ia64_fpreg fr[6]; \ | 115 | struct ia64_fpreg fr[6]; \ |
116 | u32 *aattr = NULL; \ | 116 | u32 *aattr = NULL; \ |
117 | efi_status_t ret; \ | 117 | efi_status_t ret; \ |
118 | \ | 118 | \ |
119 | if (attr) \ | 119 | if (attr) \ |
120 | aattr = adjust_arg(attr); \ | 120 | aattr = adjust_arg(attr); \ |
121 | ia64_save_scratch_fpregs(fr); \ | 121 | ia64_save_scratch_fpregs(fr); \ |
122 | ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \ | 122 | ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \ |
123 | adjust_arg(name), adjust_arg(vendor), aattr, \ | 123 | adjust_arg(name), adjust_arg(vendor), aattr, \ |
124 | adjust_arg(data_size), adjust_arg(data)); \ | 124 | adjust_arg(data_size), adjust_arg(data)); \ |
125 | ia64_load_scratch_fpregs(fr); \ | 125 | ia64_load_scratch_fpregs(fr); \ |
126 | return ret; \ | 126 | return ret; \ |
127 | } | 127 | } |
128 | 128 | ||
129 | #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \ | 129 | #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \ |
130 | static efi_status_t \ | 130 | static efi_status_t \ |
131 | prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \ | 131 | prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \ |
132 | { \ | 132 | { \ |
133 | struct ia64_fpreg fr[6]; \ | 133 | struct ia64_fpreg fr[6]; \ |
134 | efi_status_t ret; \ | 134 | efi_status_t ret; \ |
135 | \ | 135 | \ |
136 | ia64_save_scratch_fpregs(fr); \ | 136 | ia64_save_scratch_fpregs(fr); \ |
137 | ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \ | 137 | ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \ |
138 | adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \ | 138 | adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \ |
139 | ia64_load_scratch_fpregs(fr); \ | 139 | ia64_load_scratch_fpregs(fr); \ |
140 | return ret; \ | 140 | return ret; \ |
141 | } | 141 | } |
142 | 142 | ||
143 | #define STUB_SET_VARIABLE(prefix, adjust_arg) \ | 143 | #define STUB_SET_VARIABLE(prefix, adjust_arg) \ |
144 | static efi_status_t \ | 144 | static efi_status_t \ |
145 | prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long attr, \ | 145 | prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long attr, \ |
146 | unsigned long data_size, void *data) \ | 146 | unsigned long data_size, void *data) \ |
147 | { \ | 147 | { \ |
148 | struct ia64_fpreg fr[6]; \ | 148 | struct ia64_fpreg fr[6]; \ |
149 | efi_status_t ret; \ | 149 | efi_status_t ret; \ |
150 | \ | 150 | \ |
151 | ia64_save_scratch_fpregs(fr); \ | 151 | ia64_save_scratch_fpregs(fr); \ |
152 | ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \ | 152 | ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \ |
153 | adjust_arg(name), adjust_arg(vendor), attr, data_size, \ | 153 | adjust_arg(name), adjust_arg(vendor), attr, data_size, \ |
154 | adjust_arg(data)); \ | 154 | adjust_arg(data)); \ |
155 | ia64_load_scratch_fpregs(fr); \ | 155 | ia64_load_scratch_fpregs(fr); \ |
156 | return ret; \ | 156 | return ret; \ |
157 | } | 157 | } |
158 | 158 | ||
159 | #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \ | 159 | #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \ |
160 | static efi_status_t \ | 160 | static efi_status_t \ |
161 | prefix##_get_next_high_mono_count (u32 *count) \ | 161 | prefix##_get_next_high_mono_count (u32 *count) \ |
162 | { \ | 162 | { \ |
163 | struct ia64_fpreg fr[6]; \ | 163 | struct ia64_fpreg fr[6]; \ |
164 | efi_status_t ret; \ | 164 | efi_status_t ret; \ |
165 | \ | 165 | \ |
166 | ia64_save_scratch_fpregs(fr); \ | 166 | ia64_save_scratch_fpregs(fr); \ |
167 | ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \ | 167 | ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \ |
168 | __va(runtime->get_next_high_mono_count), adjust_arg(count)); \ | 168 | __va(runtime->get_next_high_mono_count), adjust_arg(count)); \ |
169 | ia64_load_scratch_fpregs(fr); \ | 169 | ia64_load_scratch_fpregs(fr); \ |
170 | return ret; \ | 170 | return ret; \ |
171 | } | 171 | } |
172 | 172 | ||
173 | #define STUB_RESET_SYSTEM(prefix, adjust_arg) \ | 173 | #define STUB_RESET_SYSTEM(prefix, adjust_arg) \ |
174 | static void \ | 174 | static void \ |
175 | prefix##_reset_system (int reset_type, efi_status_t status, \ | 175 | prefix##_reset_system (int reset_type, efi_status_t status, \ |
176 | unsigned long data_size, efi_char16_t *data) \ | 176 | unsigned long data_size, efi_char16_t *data) \ |
177 | { \ | 177 | { \ |
178 | struct ia64_fpreg fr[6]; \ | 178 | struct ia64_fpreg fr[6]; \ |
179 | efi_char16_t *adata = NULL; \ | 179 | efi_char16_t *adata = NULL; \ |
180 | \ | 180 | \ |
181 | if (data) \ | 181 | if (data) \ |
182 | adata = adjust_arg(data); \ | 182 | adata = adjust_arg(data); \ |
183 | \ | 183 | \ |
184 | ia64_save_scratch_fpregs(fr); \ | 184 | ia64_save_scratch_fpregs(fr); \ |
185 | efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \ | 185 | efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \ |
186 | reset_type, status, data_size, adata); \ | 186 | reset_type, status, data_size, adata); \ |
187 | /* should not return, but just in case... */ \ | 187 | /* should not return, but just in case... */ \ |
188 | ia64_load_scratch_fpregs(fr); \ | 188 | ia64_load_scratch_fpregs(fr); \ |
189 | } | 189 | } |
190 | 190 | ||
191 | #define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg)) | 191 | #define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg)) |
192 | 192 | ||
193 | STUB_GET_TIME(phys, phys_ptr) | 193 | STUB_GET_TIME(phys, phys_ptr) |
194 | STUB_SET_TIME(phys, phys_ptr) | 194 | STUB_SET_TIME(phys, phys_ptr) |
195 | STUB_GET_WAKEUP_TIME(phys, phys_ptr) | 195 | STUB_GET_WAKEUP_TIME(phys, phys_ptr) |
196 | STUB_SET_WAKEUP_TIME(phys, phys_ptr) | 196 | STUB_SET_WAKEUP_TIME(phys, phys_ptr) |
197 | STUB_GET_VARIABLE(phys, phys_ptr) | 197 | STUB_GET_VARIABLE(phys, phys_ptr) |
198 | STUB_GET_NEXT_VARIABLE(phys, phys_ptr) | 198 | STUB_GET_NEXT_VARIABLE(phys, phys_ptr) |
199 | STUB_SET_VARIABLE(phys, phys_ptr) | 199 | STUB_SET_VARIABLE(phys, phys_ptr) |
200 | STUB_GET_NEXT_HIGH_MONO_COUNT(phys, phys_ptr) | 200 | STUB_GET_NEXT_HIGH_MONO_COUNT(phys, phys_ptr) |
201 | STUB_RESET_SYSTEM(phys, phys_ptr) | 201 | STUB_RESET_SYSTEM(phys, phys_ptr) |
202 | 202 | ||
203 | #define id(arg) arg | 203 | #define id(arg) arg |
204 | 204 | ||
205 | STUB_GET_TIME(virt, id) | 205 | STUB_GET_TIME(virt, id) |
206 | STUB_SET_TIME(virt, id) | 206 | STUB_SET_TIME(virt, id) |
207 | STUB_GET_WAKEUP_TIME(virt, id) | 207 | STUB_GET_WAKEUP_TIME(virt, id) |
208 | STUB_SET_WAKEUP_TIME(virt, id) | 208 | STUB_SET_WAKEUP_TIME(virt, id) |
209 | STUB_GET_VARIABLE(virt, id) | 209 | STUB_GET_VARIABLE(virt, id) |
210 | STUB_GET_NEXT_VARIABLE(virt, id) | 210 | STUB_GET_NEXT_VARIABLE(virt, id) |
211 | STUB_SET_VARIABLE(virt, id) | 211 | STUB_SET_VARIABLE(virt, id) |
212 | STUB_GET_NEXT_HIGH_MONO_COUNT(virt, id) | 212 | STUB_GET_NEXT_HIGH_MONO_COUNT(virt, id) |
213 | STUB_RESET_SYSTEM(virt, id) | 213 | STUB_RESET_SYSTEM(virt, id) |
214 | 214 | ||
215 | void | 215 | void |
216 | efi_gettimeofday (struct timespec *ts) | 216 | efi_gettimeofday (struct timespec *ts) |
217 | { | 217 | { |
218 | efi_time_t tm; | 218 | efi_time_t tm; |
219 | 219 | ||
220 | memset(ts, 0, sizeof(ts)); | 220 | memset(ts, 0, sizeof(ts)); |
221 | if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS) | 221 | if ((*efi.get_time)(&tm, NULL) != EFI_SUCCESS) |
222 | return; | 222 | return; |
223 | 223 | ||
224 | ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); | 224 | ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); |
225 | ts->tv_nsec = tm.nanosecond; | 225 | ts->tv_nsec = tm.nanosecond; |
226 | } | 226 | } |
227 | 227 | ||
228 | static int | 228 | static int |
229 | is_memory_available (efi_memory_desc_t *md) | 229 | is_memory_available (efi_memory_desc_t *md) |
230 | { | 230 | { |
231 | if (!(md->attribute & EFI_MEMORY_WB)) | 231 | if (!(md->attribute & EFI_MEMORY_WB)) |
232 | return 0; | 232 | return 0; |
233 | 233 | ||
234 | switch (md->type) { | 234 | switch (md->type) { |
235 | case EFI_LOADER_CODE: | 235 | case EFI_LOADER_CODE: |
236 | case EFI_LOADER_DATA: | 236 | case EFI_LOADER_DATA: |
237 | case EFI_BOOT_SERVICES_CODE: | 237 | case EFI_BOOT_SERVICES_CODE: |
238 | case EFI_BOOT_SERVICES_DATA: | 238 | case EFI_BOOT_SERVICES_DATA: |
239 | case EFI_CONVENTIONAL_MEMORY: | 239 | case EFI_CONVENTIONAL_MEMORY: |
240 | return 1; | 240 | return 1; |
241 | } | 241 | } |
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | typedef struct kern_memdesc { | 245 | typedef struct kern_memdesc { |
246 | u64 attribute; | 246 | u64 attribute; |
247 | u64 start; | 247 | u64 start; |
248 | u64 num_pages; | 248 | u64 num_pages; |
249 | } kern_memdesc_t; | 249 | } kern_memdesc_t; |
250 | 250 | ||
251 | static kern_memdesc_t *kern_memmap; | 251 | static kern_memdesc_t *kern_memmap; |
252 | 252 | ||
253 | #define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT) | 253 | #define efi_md_size(md) (md->num_pages << EFI_PAGE_SHIFT) |
254 | 254 | ||
255 | static inline u64 | 255 | static inline u64 |
256 | kmd_end(kern_memdesc_t *kmd) | 256 | kmd_end(kern_memdesc_t *kmd) |
257 | { | 257 | { |
258 | return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT)); | 258 | return (kmd->start + (kmd->num_pages << EFI_PAGE_SHIFT)); |
259 | } | 259 | } |
260 | 260 | ||
261 | static inline u64 | 261 | static inline u64 |
262 | efi_md_end(efi_memory_desc_t *md) | 262 | efi_md_end(efi_memory_desc_t *md) |
263 | { | 263 | { |
264 | return (md->phys_addr + efi_md_size(md)); | 264 | return (md->phys_addr + efi_md_size(md)); |
265 | } | 265 | } |
266 | 266 | ||
267 | static inline int | 267 | static inline int |
268 | efi_wb(efi_memory_desc_t *md) | 268 | efi_wb(efi_memory_desc_t *md) |
269 | { | 269 | { |
270 | return (md->attribute & EFI_MEMORY_WB); | 270 | return (md->attribute & EFI_MEMORY_WB); |
271 | } | 271 | } |
272 | 272 | ||
273 | static inline int | 273 | static inline int |
274 | efi_uc(efi_memory_desc_t *md) | 274 | efi_uc(efi_memory_desc_t *md) |
275 | { | 275 | { |
276 | return (md->attribute & EFI_MEMORY_UC); | 276 | return (md->attribute & EFI_MEMORY_UC); |
277 | } | 277 | } |
278 | 278 | ||
279 | static void | 279 | static void |
280 | walk (efi_freemem_callback_t callback, void *arg, u64 attr) | 280 | walk (efi_freemem_callback_t callback, void *arg, u64 attr) |
281 | { | 281 | { |
282 | kern_memdesc_t *k; | 282 | kern_memdesc_t *k; |
283 | u64 start, end, voff; | 283 | u64 start, end, voff; |
284 | 284 | ||
285 | voff = (attr == EFI_MEMORY_WB) ? PAGE_OFFSET : __IA64_UNCACHED_OFFSET; | 285 | voff = (attr == EFI_MEMORY_WB) ? PAGE_OFFSET : __IA64_UNCACHED_OFFSET; |
286 | for (k = kern_memmap; k->start != ~0UL; k++) { | 286 | for (k = kern_memmap; k->start != ~0UL; k++) { |
287 | if (k->attribute != attr) | 287 | if (k->attribute != attr) |
288 | continue; | 288 | continue; |
289 | start = PAGE_ALIGN(k->start); | 289 | start = PAGE_ALIGN(k->start); |
290 | end = (k->start + (k->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK; | 290 | end = (k->start + (k->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK; |
291 | if (start < end) | 291 | if (start < end) |
292 | if ((*callback)(start + voff, end + voff, arg) < 0) | 292 | if ((*callback)(start + voff, end + voff, arg) < 0) |
293 | return; | 293 | return; |
294 | } | 294 | } |
295 | } | 295 | } |
296 | 296 | ||
297 | /* | 297 | /* |
298 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that | 298 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that |
299 | * has memory that is available for OS use. | 299 | * has memory that is available for OS use. |
300 | */ | 300 | */ |
301 | void | 301 | void |
302 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) | 302 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) |
303 | { | 303 | { |
304 | walk(callback, arg, EFI_MEMORY_WB); | 304 | walk(callback, arg, EFI_MEMORY_WB); |
305 | } | 305 | } |
306 | 306 | ||
307 | /* | 307 | /* |
308 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that | 308 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that |
309 | * has memory that is available for uncached allocator. | 309 | * has memory that is available for uncached allocator. |
310 | */ | 310 | */ |
311 | void | 311 | void |
312 | efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) | 312 | efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) |
313 | { | 313 | { |
314 | walk(callback, arg, EFI_MEMORY_UC); | 314 | walk(callback, arg, EFI_MEMORY_UC); |
315 | } | 315 | } |
316 | 316 | ||
317 | /* | 317 | /* |
318 | * Look for the PAL_CODE region reported by EFI and maps it using an | 318 | * Look for the PAL_CODE region reported by EFI and maps it using an |
319 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor | 319 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor |
320 | * Abstraction Layer chapter 11 in ADAG | 320 | * Abstraction Layer chapter 11 in ADAG |
321 | */ | 321 | */ |
322 | 322 | ||
323 | void * | 323 | void * |
324 | efi_get_pal_addr (void) | 324 | efi_get_pal_addr (void) |
325 | { | 325 | { |
326 | void *efi_map_start, *efi_map_end, *p; | 326 | void *efi_map_start, *efi_map_end, *p; |
327 | efi_memory_desc_t *md; | 327 | efi_memory_desc_t *md; |
328 | u64 efi_desc_size; | 328 | u64 efi_desc_size; |
329 | int pal_code_count = 0; | 329 | int pal_code_count = 0; |
330 | u64 vaddr, mask; | 330 | u64 vaddr, mask; |
331 | 331 | ||
332 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 332 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
333 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 333 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
334 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 334 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
335 | 335 | ||
336 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 336 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
337 | md = p; | 337 | md = p; |
338 | if (md->type != EFI_PAL_CODE) | 338 | if (md->type != EFI_PAL_CODE) |
339 | continue; | 339 | continue; |
340 | 340 | ||
341 | if (++pal_code_count > 1) { | 341 | if (++pal_code_count > 1) { |
342 | printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n", | 342 | printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n", |
343 | md->phys_addr); | 343 | md->phys_addr); |
344 | continue; | 344 | continue; |
345 | } | 345 | } |
346 | /* | 346 | /* |
347 | * The only ITLB entry in region 7 that is used is the one installed by | 347 | * The only ITLB entry in region 7 that is used is the one installed by |
348 | * __start(). That entry covers a 64MB range. | 348 | * __start(). That entry covers a 64MB range. |
349 | */ | 349 | */ |
350 | mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1); | 350 | mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1); |
351 | vaddr = PAGE_OFFSET + md->phys_addr; | 351 | vaddr = PAGE_OFFSET + md->phys_addr; |
352 | 352 | ||
353 | /* | 353 | /* |
354 | * We must check that the PAL mapping won't overlap with the kernel | 354 | * We must check that the PAL mapping won't overlap with the kernel |
355 | * mapping. | 355 | * mapping. |
356 | * | 356 | * |
357 | * PAL code is guaranteed to be aligned on a power of 2 between 4k and | 357 | * PAL code is guaranteed to be aligned on a power of 2 between 4k and |
358 | * 256KB and that only one ITR is needed to map it. This implies that the | 358 | * 256KB and that only one ITR is needed to map it. This implies that the |
359 | * PAL code is always aligned on its size, i.e., the closest matching page | 359 | * PAL code is always aligned on its size, i.e., the closest matching page |
360 | * size supported by the TLB. Therefore PAL code is guaranteed never to | 360 | * size supported by the TLB. Therefore PAL code is guaranteed never to |
361 | * cross a 64MB unless it is bigger than 64MB (very unlikely!). So for | 361 | * cross a 64MB unless it is bigger than 64MB (very unlikely!). So for |
362 | * now the following test is enough to determine whether or not we need a | 362 | * now the following test is enough to determine whether or not we need a |
363 | * dedicated ITR for the PAL code. | 363 | * dedicated ITR for the PAL code. |
364 | */ | 364 | */ |
365 | if ((vaddr & mask) == (KERNEL_START & mask)) { | 365 | if ((vaddr & mask) == (KERNEL_START & mask)) { |
366 | printk(KERN_INFO "%s: no need to install ITR for PAL code\n", | 366 | printk(KERN_INFO "%s: no need to install ITR for PAL code\n", |
367 | __FUNCTION__); | 367 | __FUNCTION__); |
368 | continue; | 368 | continue; |
369 | } | 369 | } |
370 | 370 | ||
371 | if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE) | 371 | if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE) |
372 | panic("Woah! PAL code size bigger than a granule!"); | 372 | panic("Woah! PAL code size bigger than a granule!"); |
373 | 373 | ||
374 | #if EFI_DEBUG | 374 | #if EFI_DEBUG |
375 | mask = ~((1 << IA64_GRANULE_SHIFT) - 1); | 375 | mask = ~((1 << IA64_GRANULE_SHIFT) - 1); |
376 | 376 | ||
377 | printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n", | 377 | printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n", |
378 | smp_processor_id(), md->phys_addr, | 378 | smp_processor_id(), md->phys_addr, |
379 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), | 379 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), |
380 | vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); | 380 | vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); |
381 | #endif | 381 | #endif |
382 | return __va(md->phys_addr); | 382 | return __va(md->phys_addr); |
383 | } | 383 | } |
384 | printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n", | 384 | printk(KERN_WARNING "%s: no PAL-code memory-descriptor found\n", |
385 | __FUNCTION__); | 385 | __FUNCTION__); |
386 | return NULL; | 386 | return NULL; |
387 | } | 387 | } |
388 | 388 | ||
389 | void | 389 | void |
390 | efi_map_pal_code (void) | 390 | efi_map_pal_code (void) |
391 | { | 391 | { |
392 | void *pal_vaddr = efi_get_pal_addr (); | 392 | void *pal_vaddr = efi_get_pal_addr (); |
393 | u64 psr; | 393 | u64 psr; |
394 | 394 | ||
395 | if (!pal_vaddr) | 395 | if (!pal_vaddr) |
396 | return; | 396 | return; |
397 | 397 | ||
398 | /* | 398 | /* |
399 | * Cannot write to CRx with PSR.ic=1 | 399 | * Cannot write to CRx with PSR.ic=1 |
400 | */ | 400 | */ |
401 | psr = ia64_clear_ic(); | 401 | psr = ia64_clear_ic(); |
402 | ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) pal_vaddr), | 402 | ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) pal_vaddr), |
403 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), | 403 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), |
404 | IA64_GRANULE_SHIFT); | 404 | IA64_GRANULE_SHIFT); |
405 | ia64_set_psr(psr); /* restore psr */ | 405 | ia64_set_psr(psr); /* restore psr */ |
406 | ia64_srlz_i(); | 406 | ia64_srlz_i(); |
407 | } | 407 | } |
408 | 408 | ||
409 | void __init | 409 | void __init |
410 | efi_init (void) | 410 | efi_init (void) |
411 | { | 411 | { |
412 | void *efi_map_start, *efi_map_end; | 412 | void *efi_map_start, *efi_map_end; |
413 | efi_config_table_t *config_tables; | 413 | efi_config_table_t *config_tables; |
414 | efi_char16_t *c16; | 414 | efi_char16_t *c16; |
415 | u64 efi_desc_size; | 415 | u64 efi_desc_size; |
416 | char *cp, vendor[100] = "unknown"; | 416 | char *cp, vendor[100] = "unknown"; |
417 | int i; | 417 | int i; |
418 | 418 | ||
419 | /* it's too early to be able to use the standard kernel command line support... */ | 419 | /* it's too early to be able to use the standard kernel command line support... */ |
420 | for (cp = boot_command_line; *cp; ) { | 420 | for (cp = boot_command_line; *cp; ) { |
421 | if (memcmp(cp, "mem=", 4) == 0) { | 421 | if (memcmp(cp, "mem=", 4) == 0) { |
422 | mem_limit = memparse(cp + 4, &cp); | 422 | mem_limit = memparse(cp + 4, &cp); |
423 | } else if (memcmp(cp, "max_addr=", 9) == 0) { | 423 | } else if (memcmp(cp, "max_addr=", 9) == 0) { |
424 | max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); | 424 | max_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); |
425 | } else if (memcmp(cp, "min_addr=", 9) == 0) { | 425 | } else if (memcmp(cp, "min_addr=", 9) == 0) { |
426 | min_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); | 426 | min_addr = GRANULEROUNDDOWN(memparse(cp + 9, &cp)); |
427 | } else { | 427 | } else { |
428 | while (*cp != ' ' && *cp) | 428 | while (*cp != ' ' && *cp) |
429 | ++cp; | 429 | ++cp; |
430 | while (*cp == ' ') | 430 | while (*cp == ' ') |
431 | ++cp; | 431 | ++cp; |
432 | } | 432 | } |
433 | } | 433 | } |
434 | if (min_addr != 0UL) | 434 | if (min_addr != 0UL) |
435 | printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20); | 435 | printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20); |
436 | if (max_addr != ~0UL) | 436 | if (max_addr != ~0UL) |
437 | printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); | 437 | printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); |
438 | 438 | ||
439 | efi.systab = __va(ia64_boot_param->efi_systab); | 439 | efi.systab = __va(ia64_boot_param->efi_systab); |
440 | 440 | ||
441 | /* | 441 | /* |
442 | * Verify the EFI Table | 442 | * Verify the EFI Table |
443 | */ | 443 | */ |
444 | if (efi.systab == NULL) | 444 | if (efi.systab == NULL) |
445 | panic("Woah! Can't find EFI system table.\n"); | 445 | panic("Woah! Can't find EFI system table.\n"); |
446 | if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | 446 | if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) |
447 | panic("Woah! EFI system table signature incorrect\n"); | 447 | panic("Woah! EFI system table signature incorrect\n"); |
448 | if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0) | 448 | if ((efi.systab->hdr.revision >> 16) == 0) |
449 | printk(KERN_WARNING "Warning: EFI system table major version mismatch: " | 449 | printk(KERN_WARNING "Warning: EFI system table version " |
450 | "got %d.%02d, expected %d.%02d\n", | 450 | "%d.%02d, expected 1.00 or greater\n", |
451 | efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, | 451 | efi.systab->hdr.revision >> 16, |
452 | EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff); | 452 | efi.systab->hdr.revision & 0xffff); |
453 | 453 | ||
454 | config_tables = __va(efi.systab->tables); | 454 | config_tables = __va(efi.systab->tables); |
455 | 455 | ||
456 | /* Show what we know for posterity */ | 456 | /* Show what we know for posterity */ |
457 | c16 = __va(efi.systab->fw_vendor); | 457 | c16 = __va(efi.systab->fw_vendor); |
458 | if (c16) { | 458 | if (c16) { |
459 | for (i = 0;i < (int) sizeof(vendor) - 1 && *c16; ++i) | 459 | for (i = 0;i < (int) sizeof(vendor) - 1 && *c16; ++i) |
460 | vendor[i] = *c16++; | 460 | vendor[i] = *c16++; |
461 | vendor[i] = '\0'; | 461 | vendor[i] = '\0'; |
462 | } | 462 | } |
463 | 463 | ||
464 | printk(KERN_INFO "EFI v%u.%.02u by %s:", | 464 | printk(KERN_INFO "EFI v%u.%.02u by %s:", |
465 | efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); | 465 | efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); |
466 | 466 | ||
467 | efi.mps = EFI_INVALID_TABLE_ADDR; | 467 | efi.mps = EFI_INVALID_TABLE_ADDR; |
468 | efi.acpi = EFI_INVALID_TABLE_ADDR; | 468 | efi.acpi = EFI_INVALID_TABLE_ADDR; |
469 | efi.acpi20 = EFI_INVALID_TABLE_ADDR; | 469 | efi.acpi20 = EFI_INVALID_TABLE_ADDR; |
470 | efi.smbios = EFI_INVALID_TABLE_ADDR; | 470 | efi.smbios = EFI_INVALID_TABLE_ADDR; |
471 | efi.sal_systab = EFI_INVALID_TABLE_ADDR; | 471 | efi.sal_systab = EFI_INVALID_TABLE_ADDR; |
472 | efi.boot_info = EFI_INVALID_TABLE_ADDR; | 472 | efi.boot_info = EFI_INVALID_TABLE_ADDR; |
473 | efi.hcdp = EFI_INVALID_TABLE_ADDR; | 473 | efi.hcdp = EFI_INVALID_TABLE_ADDR; |
474 | efi.uga = EFI_INVALID_TABLE_ADDR; | 474 | efi.uga = EFI_INVALID_TABLE_ADDR; |
475 | 475 | ||
476 | for (i = 0; i < (int) efi.systab->nr_tables; i++) { | 476 | for (i = 0; i < (int) efi.systab->nr_tables; i++) { |
477 | if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { | 477 | if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { |
478 | efi.mps = config_tables[i].table; | 478 | efi.mps = config_tables[i].table; |
479 | printk(" MPS=0x%lx", config_tables[i].table); | 479 | printk(" MPS=0x%lx", config_tables[i].table); |
480 | } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { | 480 | } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) { |
481 | efi.acpi20 = config_tables[i].table; | 481 | efi.acpi20 = config_tables[i].table; |
482 | printk(" ACPI 2.0=0x%lx", config_tables[i].table); | 482 | printk(" ACPI 2.0=0x%lx", config_tables[i].table); |
483 | } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { | 483 | } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) { |
484 | efi.acpi = config_tables[i].table; | 484 | efi.acpi = config_tables[i].table; |
485 | printk(" ACPI=0x%lx", config_tables[i].table); | 485 | printk(" ACPI=0x%lx", config_tables[i].table); |
486 | } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { | 486 | } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) { |
487 | efi.smbios = config_tables[i].table; | 487 | efi.smbios = config_tables[i].table; |
488 | printk(" SMBIOS=0x%lx", config_tables[i].table); | 488 | printk(" SMBIOS=0x%lx", config_tables[i].table); |
489 | } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { | 489 | } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) { |
490 | efi.sal_systab = config_tables[i].table; | 490 | efi.sal_systab = config_tables[i].table; |
491 | printk(" SALsystab=0x%lx", config_tables[i].table); | 491 | printk(" SALsystab=0x%lx", config_tables[i].table); |
492 | } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { | 492 | } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) { |
493 | efi.hcdp = config_tables[i].table; | 493 | efi.hcdp = config_tables[i].table; |
494 | printk(" HCDP=0x%lx", config_tables[i].table); | 494 | printk(" HCDP=0x%lx", config_tables[i].table); |
495 | } | 495 | } |
496 | } | 496 | } |
497 | printk("\n"); | 497 | printk("\n"); |
498 | 498 | ||
499 | runtime = __va(efi.systab->runtime); | 499 | runtime = __va(efi.systab->runtime); |
500 | efi.get_time = phys_get_time; | 500 | efi.get_time = phys_get_time; |
501 | efi.set_time = phys_set_time; | 501 | efi.set_time = phys_set_time; |
502 | efi.get_wakeup_time = phys_get_wakeup_time; | 502 | efi.get_wakeup_time = phys_get_wakeup_time; |
503 | efi.set_wakeup_time = phys_set_wakeup_time; | 503 | efi.set_wakeup_time = phys_set_wakeup_time; |
504 | efi.get_variable = phys_get_variable; | 504 | efi.get_variable = phys_get_variable; |
505 | efi.get_next_variable = phys_get_next_variable; | 505 | efi.get_next_variable = phys_get_next_variable; |
506 | efi.set_variable = phys_set_variable; | 506 | efi.set_variable = phys_set_variable; |
507 | efi.get_next_high_mono_count = phys_get_next_high_mono_count; | 507 | efi.get_next_high_mono_count = phys_get_next_high_mono_count; |
508 | efi.reset_system = phys_reset_system; | 508 | efi.reset_system = phys_reset_system; |
509 | 509 | ||
510 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 510 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
511 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 511 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
512 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 512 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
513 | 513 | ||
514 | #if EFI_DEBUG | 514 | #if EFI_DEBUG |
515 | /* print EFI memory map: */ | 515 | /* print EFI memory map: */ |
516 | { | 516 | { |
517 | efi_memory_desc_t *md; | 517 | efi_memory_desc_t *md; |
518 | void *p; | 518 | void *p; |
519 | 519 | ||
520 | for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { | 520 | for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { |
521 | md = p; | 521 | md = p; |
522 | printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", | 522 | printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", |
523 | i, md->type, md->attribute, md->phys_addr, | 523 | i, md->type, md->attribute, md->phys_addr, |
524 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), | 524 | md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), |
525 | md->num_pages >> (20 - EFI_PAGE_SHIFT)); | 525 | md->num_pages >> (20 - EFI_PAGE_SHIFT)); |
526 | } | 526 | } |
527 | } | 527 | } |
528 | #endif | 528 | #endif |
529 | 529 | ||
530 | efi_map_pal_code(); | 530 | efi_map_pal_code(); |
531 | efi_enter_virtual_mode(); | 531 | efi_enter_virtual_mode(); |
532 | } | 532 | } |
533 | 533 | ||
534 | void | 534 | void |
535 | efi_enter_virtual_mode (void) | 535 | efi_enter_virtual_mode (void) |
536 | { | 536 | { |
537 | void *efi_map_start, *efi_map_end, *p; | 537 | void *efi_map_start, *efi_map_end, *p; |
538 | efi_memory_desc_t *md; | 538 | efi_memory_desc_t *md; |
539 | efi_status_t status; | 539 | efi_status_t status; |
540 | u64 efi_desc_size; | 540 | u64 efi_desc_size; |
541 | 541 | ||
542 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 542 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
543 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 543 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
544 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 544 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
545 | 545 | ||
546 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 546 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
547 | md = p; | 547 | md = p; |
548 | if (md->attribute & EFI_MEMORY_RUNTIME) { | 548 | if (md->attribute & EFI_MEMORY_RUNTIME) { |
549 | /* | 549 | /* |
550 | * Some descriptors have multiple bits set, so the order of | 550 | * Some descriptors have multiple bits set, so the order of |
551 | * the tests is relevant. | 551 | * the tests is relevant. |
552 | */ | 552 | */ |
553 | if (md->attribute & EFI_MEMORY_WB) { | 553 | if (md->attribute & EFI_MEMORY_WB) { |
554 | md->virt_addr = (u64) __va(md->phys_addr); | 554 | md->virt_addr = (u64) __va(md->phys_addr); |
555 | } else if (md->attribute & EFI_MEMORY_UC) { | 555 | } else if (md->attribute & EFI_MEMORY_UC) { |
556 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 556 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
557 | } else if (md->attribute & EFI_MEMORY_WC) { | 557 | } else if (md->attribute & EFI_MEMORY_WC) { |
558 | #if 0 | 558 | #if 0 |
559 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P | 559 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P |
560 | | _PAGE_D | 560 | | _PAGE_D |
561 | | _PAGE_MA_WC | 561 | | _PAGE_MA_WC |
562 | | _PAGE_PL_0 | 562 | | _PAGE_PL_0 |
563 | | _PAGE_AR_RW)); | 563 | | _PAGE_AR_RW)); |
564 | #else | 564 | #else |
565 | printk(KERN_INFO "EFI_MEMORY_WC mapping\n"); | 565 | printk(KERN_INFO "EFI_MEMORY_WC mapping\n"); |
566 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 566 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
567 | #endif | 567 | #endif |
568 | } else if (md->attribute & EFI_MEMORY_WT) { | 568 | } else if (md->attribute & EFI_MEMORY_WT) { |
569 | #if 0 | 569 | #if 0 |
570 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P | 570 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P |
571 | | _PAGE_D | _PAGE_MA_WT | 571 | | _PAGE_D | _PAGE_MA_WT |
572 | | _PAGE_PL_0 | 572 | | _PAGE_PL_0 |
573 | | _PAGE_AR_RW)); | 573 | | _PAGE_AR_RW)); |
574 | #else | 574 | #else |
575 | printk(KERN_INFO "EFI_MEMORY_WT mapping\n"); | 575 | printk(KERN_INFO "EFI_MEMORY_WT mapping\n"); |
576 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 576 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
577 | #endif | 577 | #endif |
578 | } | 578 | } |
579 | } | 579 | } |
580 | } | 580 | } |
581 | 581 | ||
582 | status = efi_call_phys(__va(runtime->set_virtual_address_map), | 582 | status = efi_call_phys(__va(runtime->set_virtual_address_map), |
583 | ia64_boot_param->efi_memmap_size, | 583 | ia64_boot_param->efi_memmap_size, |
584 | efi_desc_size, ia64_boot_param->efi_memdesc_version, | 584 | efi_desc_size, ia64_boot_param->efi_memdesc_version, |
585 | ia64_boot_param->efi_memmap); | 585 | ia64_boot_param->efi_memmap); |
586 | if (status != EFI_SUCCESS) { | 586 | if (status != EFI_SUCCESS) { |
587 | printk(KERN_WARNING "warning: unable to switch EFI into virtual mode " | 587 | printk(KERN_WARNING "warning: unable to switch EFI into virtual mode " |
588 | "(status=%lu)\n", status); | 588 | "(status=%lu)\n", status); |
589 | return; | 589 | return; |
590 | } | 590 | } |
591 | 591 | ||
592 | /* | 592 | /* |
593 | * Now that EFI is in virtual mode, we call the EFI functions more efficiently: | 593 | * Now that EFI is in virtual mode, we call the EFI functions more efficiently: |
594 | */ | 594 | */ |
595 | efi.get_time = virt_get_time; | 595 | efi.get_time = virt_get_time; |
596 | efi.set_time = virt_set_time; | 596 | efi.set_time = virt_set_time; |
597 | efi.get_wakeup_time = virt_get_wakeup_time; | 597 | efi.get_wakeup_time = virt_get_wakeup_time; |
598 | efi.set_wakeup_time = virt_set_wakeup_time; | 598 | efi.set_wakeup_time = virt_set_wakeup_time; |
599 | efi.get_variable = virt_get_variable; | 599 | efi.get_variable = virt_get_variable; |
600 | efi.get_next_variable = virt_get_next_variable; | 600 | efi.get_next_variable = virt_get_next_variable; |
601 | efi.set_variable = virt_set_variable; | 601 | efi.set_variable = virt_set_variable; |
602 | efi.get_next_high_mono_count = virt_get_next_high_mono_count; | 602 | efi.get_next_high_mono_count = virt_get_next_high_mono_count; |
603 | efi.reset_system = virt_reset_system; | 603 | efi.reset_system = virt_reset_system; |
604 | } | 604 | } |
605 | 605 | ||
606 | /* | 606 | /* |
607 | * Walk the EFI memory map looking for the I/O port range. There can only be one entry of | 607 | * Walk the EFI memory map looking for the I/O port range. There can only be one entry of |
608 | * this type, other I/O port ranges should be described via ACPI. | 608 | * this type, other I/O port ranges should be described via ACPI. |
609 | */ | 609 | */ |
610 | u64 | 610 | u64 |
611 | efi_get_iobase (void) | 611 | efi_get_iobase (void) |
612 | { | 612 | { |
613 | void *efi_map_start, *efi_map_end, *p; | 613 | void *efi_map_start, *efi_map_end, *p; |
614 | efi_memory_desc_t *md; | 614 | efi_memory_desc_t *md; |
615 | u64 efi_desc_size; | 615 | u64 efi_desc_size; |
616 | 616 | ||
617 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 617 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
618 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 618 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
619 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 619 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
620 | 620 | ||
621 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 621 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
622 | md = p; | 622 | md = p; |
623 | if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) { | 623 | if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) { |
624 | if (md->attribute & EFI_MEMORY_UC) | 624 | if (md->attribute & EFI_MEMORY_UC) |
625 | return md->phys_addr; | 625 | return md->phys_addr; |
626 | } | 626 | } |
627 | } | 627 | } |
628 | return 0; | 628 | return 0; |
629 | } | 629 | } |
630 | 630 | ||
631 | static struct kern_memdesc * | 631 | static struct kern_memdesc * |
632 | kern_memory_descriptor (unsigned long phys_addr) | 632 | kern_memory_descriptor (unsigned long phys_addr) |
633 | { | 633 | { |
634 | struct kern_memdesc *md; | 634 | struct kern_memdesc *md; |
635 | 635 | ||
636 | for (md = kern_memmap; md->start != ~0UL; md++) { | 636 | for (md = kern_memmap; md->start != ~0UL; md++) { |
637 | if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT)) | 637 | if (phys_addr - md->start < (md->num_pages << EFI_PAGE_SHIFT)) |
638 | return md; | 638 | return md; |
639 | } | 639 | } |
640 | return NULL; | 640 | return NULL; |
641 | } | 641 | } |
642 | 642 | ||
643 | static efi_memory_desc_t * | 643 | static efi_memory_desc_t * |
644 | efi_memory_descriptor (unsigned long phys_addr) | 644 | efi_memory_descriptor (unsigned long phys_addr) |
645 | { | 645 | { |
646 | void *efi_map_start, *efi_map_end, *p; | 646 | void *efi_map_start, *efi_map_end, *p; |
647 | efi_memory_desc_t *md; | 647 | efi_memory_desc_t *md; |
648 | u64 efi_desc_size; | 648 | u64 efi_desc_size; |
649 | 649 | ||
650 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 650 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
651 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 651 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
652 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 652 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
653 | 653 | ||
654 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 654 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
655 | md = p; | 655 | md = p; |
656 | 656 | ||
657 | if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) | 657 | if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) |
658 | return md; | 658 | return md; |
659 | } | 659 | } |
660 | return NULL; | 660 | return NULL; |
661 | } | 661 | } |
662 | 662 | ||
663 | static int | 663 | static int |
664 | efi_memmap_intersects (unsigned long phys_addr, unsigned long size) | 664 | efi_memmap_intersects (unsigned long phys_addr, unsigned long size) |
665 | { | 665 | { |
666 | void *efi_map_start, *efi_map_end, *p; | 666 | void *efi_map_start, *efi_map_end, *p; |
667 | efi_memory_desc_t *md; | 667 | efi_memory_desc_t *md; |
668 | u64 efi_desc_size; | 668 | u64 efi_desc_size; |
669 | unsigned long end; | 669 | unsigned long end; |
670 | 670 | ||
671 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 671 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
672 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 672 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
673 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 673 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
674 | 674 | ||
675 | end = phys_addr + size; | 675 | end = phys_addr + size; |
676 | 676 | ||
677 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 677 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
678 | md = p; | 678 | md = p; |
679 | 679 | ||
680 | if (md->phys_addr < end && efi_md_end(md) > phys_addr) | 680 | if (md->phys_addr < end && efi_md_end(md) > phys_addr) |
681 | return 1; | 681 | return 1; |
682 | } | 682 | } |
683 | return 0; | 683 | return 0; |
684 | } | 684 | } |
685 | 685 | ||
686 | u32 | 686 | u32 |
687 | efi_mem_type (unsigned long phys_addr) | 687 | efi_mem_type (unsigned long phys_addr) |
688 | { | 688 | { |
689 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); | 689 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); |
690 | 690 | ||
691 | if (md) | 691 | if (md) |
692 | return md->type; | 692 | return md->type; |
693 | return 0; | 693 | return 0; |
694 | } | 694 | } |
695 | 695 | ||
696 | u64 | 696 | u64 |
697 | efi_mem_attributes (unsigned long phys_addr) | 697 | efi_mem_attributes (unsigned long phys_addr) |
698 | { | 698 | { |
699 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); | 699 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); |
700 | 700 | ||
701 | if (md) | 701 | if (md) |
702 | return md->attribute; | 702 | return md->attribute; |
703 | return 0; | 703 | return 0; |
704 | } | 704 | } |
705 | EXPORT_SYMBOL(efi_mem_attributes); | 705 | EXPORT_SYMBOL(efi_mem_attributes); |
706 | 706 | ||
707 | u64 | 707 | u64 |
708 | efi_mem_attribute (unsigned long phys_addr, unsigned long size) | 708 | efi_mem_attribute (unsigned long phys_addr, unsigned long size) |
709 | { | 709 | { |
710 | unsigned long end = phys_addr + size; | 710 | unsigned long end = phys_addr + size; |
711 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); | 711 | efi_memory_desc_t *md = efi_memory_descriptor(phys_addr); |
712 | u64 attr; | 712 | u64 attr; |
713 | 713 | ||
714 | if (!md) | 714 | if (!md) |
715 | return 0; | 715 | return 0; |
716 | 716 | ||
717 | /* | 717 | /* |
718 | * EFI_MEMORY_RUNTIME is not a memory attribute; it just tells | 718 | * EFI_MEMORY_RUNTIME is not a memory attribute; it just tells |
719 | * the kernel that firmware needs this region mapped. | 719 | * the kernel that firmware needs this region mapped. |
720 | */ | 720 | */ |
721 | attr = md->attribute & ~EFI_MEMORY_RUNTIME; | 721 | attr = md->attribute & ~EFI_MEMORY_RUNTIME; |
722 | do { | 722 | do { |
723 | unsigned long md_end = efi_md_end(md); | 723 | unsigned long md_end = efi_md_end(md); |
724 | 724 | ||
725 | if (end <= md_end) | 725 | if (end <= md_end) |
726 | return attr; | 726 | return attr; |
727 | 727 | ||
728 | md = efi_memory_descriptor(md_end); | 728 | md = efi_memory_descriptor(md_end); |
729 | if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr) | 729 | if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr) |
730 | return 0; | 730 | return 0; |
731 | } while (md); | 731 | } while (md); |
732 | return 0; | 732 | return 0; |
733 | } | 733 | } |
734 | 734 | ||
735 | u64 | 735 | u64 |
736 | kern_mem_attribute (unsigned long phys_addr, unsigned long size) | 736 | kern_mem_attribute (unsigned long phys_addr, unsigned long size) |
737 | { | 737 | { |
738 | unsigned long end = phys_addr + size; | 738 | unsigned long end = phys_addr + size; |
739 | struct kern_memdesc *md; | 739 | struct kern_memdesc *md; |
740 | u64 attr; | 740 | u64 attr; |
741 | 741 | ||
742 | /* | 742 | /* |
743 | * This is a hack for ioremap calls before we set up kern_memmap. | 743 | * This is a hack for ioremap calls before we set up kern_memmap. |
744 | * Maybe we should do efi_memmap_init() earlier instead. | 744 | * Maybe we should do efi_memmap_init() earlier instead. |
745 | */ | 745 | */ |
746 | if (!kern_memmap) { | 746 | if (!kern_memmap) { |
747 | attr = efi_mem_attribute(phys_addr, size); | 747 | attr = efi_mem_attribute(phys_addr, size); |
748 | if (attr & EFI_MEMORY_WB) | 748 | if (attr & EFI_MEMORY_WB) |
749 | return EFI_MEMORY_WB; | 749 | return EFI_MEMORY_WB; |
750 | return 0; | 750 | return 0; |
751 | } | 751 | } |
752 | 752 | ||
753 | md = kern_memory_descriptor(phys_addr); | 753 | md = kern_memory_descriptor(phys_addr); |
754 | if (!md) | 754 | if (!md) |
755 | return 0; | 755 | return 0; |
756 | 756 | ||
757 | attr = md->attribute; | 757 | attr = md->attribute; |
758 | do { | 758 | do { |
759 | unsigned long md_end = kmd_end(md); | 759 | unsigned long md_end = kmd_end(md); |
760 | 760 | ||
761 | if (end <= md_end) | 761 | if (end <= md_end) |
762 | return attr; | 762 | return attr; |
763 | 763 | ||
764 | md = kern_memory_descriptor(md_end); | 764 | md = kern_memory_descriptor(md_end); |
765 | if (!md || md->attribute != attr) | 765 | if (!md || md->attribute != attr) |
766 | return 0; | 766 | return 0; |
767 | } while (md); | 767 | } while (md); |
768 | return 0; | 768 | return 0; |
769 | } | 769 | } |
770 | EXPORT_SYMBOL(kern_mem_attribute); | 770 | EXPORT_SYMBOL(kern_mem_attribute); |
771 | 771 | ||
772 | int | 772 | int |
773 | valid_phys_addr_range (unsigned long phys_addr, unsigned long size) | 773 | valid_phys_addr_range (unsigned long phys_addr, unsigned long size) |
774 | { | 774 | { |
775 | u64 attr; | 775 | u64 attr; |
776 | 776 | ||
777 | /* | 777 | /* |
778 | * /dev/mem reads and writes use copy_to_user(), which implicitly | 778 | * /dev/mem reads and writes use copy_to_user(), which implicitly |
779 | * uses a granule-sized kernel identity mapping. It's really | 779 | * uses a granule-sized kernel identity mapping. It's really |
780 | * only safe to do this for regions in kern_memmap. For more | 780 | * only safe to do this for regions in kern_memmap. For more |
781 | * details, see Documentation/ia64/aliasing.txt. | 781 | * details, see Documentation/ia64/aliasing.txt. |
782 | */ | 782 | */ |
783 | attr = kern_mem_attribute(phys_addr, size); | 783 | attr = kern_mem_attribute(phys_addr, size); |
784 | if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC) | 784 | if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC) |
785 | return 1; | 785 | return 1; |
786 | return 0; | 786 | return 0; |
787 | } | 787 | } |
788 | 788 | ||
789 | int | 789 | int |
790 | valid_mmap_phys_addr_range (unsigned long pfn, unsigned long size) | 790 | valid_mmap_phys_addr_range (unsigned long pfn, unsigned long size) |
791 | { | 791 | { |
792 | unsigned long phys_addr = pfn << PAGE_SHIFT; | 792 | unsigned long phys_addr = pfn << PAGE_SHIFT; |
793 | u64 attr; | 793 | u64 attr; |
794 | 794 | ||
795 | attr = efi_mem_attribute(phys_addr, size); | 795 | attr = efi_mem_attribute(phys_addr, size); |
796 | 796 | ||
797 | /* | 797 | /* |
798 | * /dev/mem mmap uses normal user pages, so we don't need the entire | 798 | * /dev/mem mmap uses normal user pages, so we don't need the entire |
799 | * granule, but the entire region we're mapping must support the same | 799 | * granule, but the entire region we're mapping must support the same |
800 | * attribute. | 800 | * attribute. |
801 | */ | 801 | */ |
802 | if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC) | 802 | if (attr & EFI_MEMORY_WB || attr & EFI_MEMORY_UC) |
803 | return 1; | 803 | return 1; |
804 | 804 | ||
805 | /* | 805 | /* |
806 | * Intel firmware doesn't tell us about all the MMIO regions, so | 806 | * Intel firmware doesn't tell us about all the MMIO regions, so |
807 | * in general we have to allow mmap requests. But if EFI *does* | 807 | * in general we have to allow mmap requests. But if EFI *does* |
808 | * tell us about anything inside this region, we should deny it. | 808 | * tell us about anything inside this region, we should deny it. |
809 | * The user can always map a smaller region to avoid the overlap. | 809 | * The user can always map a smaller region to avoid the overlap. |
810 | */ | 810 | */ |
811 | if (efi_memmap_intersects(phys_addr, size)) | 811 | if (efi_memmap_intersects(phys_addr, size)) |
812 | return 0; | 812 | return 0; |
813 | 813 | ||
814 | return 1; | 814 | return 1; |
815 | } | 815 | } |
816 | 816 | ||
817 | pgprot_t | 817 | pgprot_t |
818 | phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, | 818 | phys_mem_access_prot(struct file *file, unsigned long pfn, unsigned long size, |
819 | pgprot_t vma_prot) | 819 | pgprot_t vma_prot) |
820 | { | 820 | { |
821 | unsigned long phys_addr = pfn << PAGE_SHIFT; | 821 | unsigned long phys_addr = pfn << PAGE_SHIFT; |
822 | u64 attr; | 822 | u64 attr; |
823 | 823 | ||
824 | /* | 824 | /* |
825 | * For /dev/mem mmap, we use user mappings, but if the region is | 825 | * For /dev/mem mmap, we use user mappings, but if the region is |
826 | * in kern_memmap (and hence may be covered by a kernel mapping), | 826 | * in kern_memmap (and hence may be covered by a kernel mapping), |
827 | * we must use the same attribute as the kernel mapping. | 827 | * we must use the same attribute as the kernel mapping. |
828 | */ | 828 | */ |
829 | attr = kern_mem_attribute(phys_addr, size); | 829 | attr = kern_mem_attribute(phys_addr, size); |
830 | if (attr & EFI_MEMORY_WB) | 830 | if (attr & EFI_MEMORY_WB) |
831 | return pgprot_cacheable(vma_prot); | 831 | return pgprot_cacheable(vma_prot); |
832 | else if (attr & EFI_MEMORY_UC) | 832 | else if (attr & EFI_MEMORY_UC) |
833 | return pgprot_noncached(vma_prot); | 833 | return pgprot_noncached(vma_prot); |
834 | 834 | ||
835 | /* | 835 | /* |
836 | * Some chipsets don't support UC access to memory. If | 836 | * Some chipsets don't support UC access to memory. If |
837 | * WB is supported, we prefer that. | 837 | * WB is supported, we prefer that. |
838 | */ | 838 | */ |
839 | if (efi_mem_attribute(phys_addr, size) & EFI_MEMORY_WB) | 839 | if (efi_mem_attribute(phys_addr, size) & EFI_MEMORY_WB) |
840 | return pgprot_cacheable(vma_prot); | 840 | return pgprot_cacheable(vma_prot); |
841 | 841 | ||
842 | return pgprot_noncached(vma_prot); | 842 | return pgprot_noncached(vma_prot); |
843 | } | 843 | } |
844 | 844 | ||
845 | int __init | 845 | int __init |
846 | efi_uart_console_only(void) | 846 | efi_uart_console_only(void) |
847 | { | 847 | { |
848 | efi_status_t status; | 848 | efi_status_t status; |
849 | char *s, name[] = "ConOut"; | 849 | char *s, name[] = "ConOut"; |
850 | efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID; | 850 | efi_guid_t guid = EFI_GLOBAL_VARIABLE_GUID; |
851 | efi_char16_t *utf16, name_utf16[32]; | 851 | efi_char16_t *utf16, name_utf16[32]; |
852 | unsigned char data[1024]; | 852 | unsigned char data[1024]; |
853 | unsigned long size = sizeof(data); | 853 | unsigned long size = sizeof(data); |
854 | struct efi_generic_dev_path *hdr, *end_addr; | 854 | struct efi_generic_dev_path *hdr, *end_addr; |
855 | int uart = 0; | 855 | int uart = 0; |
856 | 856 | ||
857 | /* Convert to UTF-16 */ | 857 | /* Convert to UTF-16 */ |
858 | utf16 = name_utf16; | 858 | utf16 = name_utf16; |
859 | s = name; | 859 | s = name; |
860 | while (*s) | 860 | while (*s) |
861 | *utf16++ = *s++ & 0x7f; | 861 | *utf16++ = *s++ & 0x7f; |
862 | *utf16 = 0; | 862 | *utf16 = 0; |
863 | 863 | ||
864 | status = efi.get_variable(name_utf16, &guid, NULL, &size, data); | 864 | status = efi.get_variable(name_utf16, &guid, NULL, &size, data); |
865 | if (status != EFI_SUCCESS) { | 865 | if (status != EFI_SUCCESS) { |
866 | printk(KERN_ERR "No EFI %s variable?\n", name); | 866 | printk(KERN_ERR "No EFI %s variable?\n", name); |
867 | return 0; | 867 | return 0; |
868 | } | 868 | } |
869 | 869 | ||
870 | hdr = (struct efi_generic_dev_path *) data; | 870 | hdr = (struct efi_generic_dev_path *) data; |
871 | end_addr = (struct efi_generic_dev_path *) ((u8 *) data + size); | 871 | end_addr = (struct efi_generic_dev_path *) ((u8 *) data + size); |
872 | while (hdr < end_addr) { | 872 | while (hdr < end_addr) { |
873 | if (hdr->type == EFI_DEV_MSG && | 873 | if (hdr->type == EFI_DEV_MSG && |
874 | hdr->sub_type == EFI_DEV_MSG_UART) | 874 | hdr->sub_type == EFI_DEV_MSG_UART) |
875 | uart = 1; | 875 | uart = 1; |
876 | else if (hdr->type == EFI_DEV_END_PATH || | 876 | else if (hdr->type == EFI_DEV_END_PATH || |
877 | hdr->type == EFI_DEV_END_PATH2) { | 877 | hdr->type == EFI_DEV_END_PATH2) { |
878 | if (!uart) | 878 | if (!uart) |
879 | return 0; | 879 | return 0; |
880 | if (hdr->sub_type == EFI_DEV_END_ENTIRE) | 880 | if (hdr->sub_type == EFI_DEV_END_ENTIRE) |
881 | return 1; | 881 | return 1; |
882 | uart = 0; | 882 | uart = 0; |
883 | } | 883 | } |
884 | hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length); | 884 | hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length); |
885 | } | 885 | } |
886 | printk(KERN_ERR "Malformed %s value\n", name); | 886 | printk(KERN_ERR "Malformed %s value\n", name); |
887 | return 0; | 887 | return 0; |
888 | } | 888 | } |
889 | 889 | ||
890 | /* | 890 | /* |
891 | * Look for the first granule aligned memory descriptor memory | 891 | * Look for the first granule aligned memory descriptor memory |
892 | * that is big enough to hold EFI memory map. Make sure this | 892 | * that is big enough to hold EFI memory map. Make sure this |
893 | * descriptor is atleast granule sized so it does not get trimmed | 893 | * descriptor is atleast granule sized so it does not get trimmed |
894 | */ | 894 | */ |
895 | struct kern_memdesc * | 895 | struct kern_memdesc * |
896 | find_memmap_space (void) | 896 | find_memmap_space (void) |
897 | { | 897 | { |
898 | u64 contig_low=0, contig_high=0; | 898 | u64 contig_low=0, contig_high=0; |
899 | u64 as = 0, ae; | 899 | u64 as = 0, ae; |
900 | void *efi_map_start, *efi_map_end, *p, *q; | 900 | void *efi_map_start, *efi_map_end, *p, *q; |
901 | efi_memory_desc_t *md, *pmd = NULL, *check_md; | 901 | efi_memory_desc_t *md, *pmd = NULL, *check_md; |
902 | u64 space_needed, efi_desc_size; | 902 | u64 space_needed, efi_desc_size; |
903 | unsigned long total_mem = 0; | 903 | unsigned long total_mem = 0; |
904 | 904 | ||
905 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 905 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
906 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 906 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
907 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 907 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
908 | 908 | ||
909 | /* | 909 | /* |
910 | * Worst case: we need 3 kernel descriptors for each efi descriptor | 910 | * Worst case: we need 3 kernel descriptors for each efi descriptor |
911 | * (if every entry has a WB part in the middle, and UC head and tail), | 911 | * (if every entry has a WB part in the middle, and UC head and tail), |
912 | * plus one for the end marker. | 912 | * plus one for the end marker. |
913 | */ | 913 | */ |
914 | space_needed = sizeof(kern_memdesc_t) * | 914 | space_needed = sizeof(kern_memdesc_t) * |
915 | (3 * (ia64_boot_param->efi_memmap_size/efi_desc_size) + 1); | 915 | (3 * (ia64_boot_param->efi_memmap_size/efi_desc_size) + 1); |
916 | 916 | ||
917 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { | 917 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { |
918 | md = p; | 918 | md = p; |
919 | if (!efi_wb(md)) { | 919 | if (!efi_wb(md)) { |
920 | continue; | 920 | continue; |
921 | } | 921 | } |
922 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | 922 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { |
923 | contig_low = GRANULEROUNDUP(md->phys_addr); | 923 | contig_low = GRANULEROUNDUP(md->phys_addr); |
924 | contig_high = efi_md_end(md); | 924 | contig_high = efi_md_end(md); |
925 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | 925 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { |
926 | check_md = q; | 926 | check_md = q; |
927 | if (!efi_wb(check_md)) | 927 | if (!efi_wb(check_md)) |
928 | break; | 928 | break; |
929 | if (contig_high != check_md->phys_addr) | 929 | if (contig_high != check_md->phys_addr) |
930 | break; | 930 | break; |
931 | contig_high = efi_md_end(check_md); | 931 | contig_high = efi_md_end(check_md); |
932 | } | 932 | } |
933 | contig_high = GRANULEROUNDDOWN(contig_high); | 933 | contig_high = GRANULEROUNDDOWN(contig_high); |
934 | } | 934 | } |
935 | if (!is_memory_available(md) || md->type == EFI_LOADER_DATA) | 935 | if (!is_memory_available(md) || md->type == EFI_LOADER_DATA) |
936 | continue; | 936 | continue; |
937 | 937 | ||
938 | /* Round ends inward to granule boundaries */ | 938 | /* Round ends inward to granule boundaries */ |
939 | as = max(contig_low, md->phys_addr); | 939 | as = max(contig_low, md->phys_addr); |
940 | ae = min(contig_high, efi_md_end(md)); | 940 | ae = min(contig_high, efi_md_end(md)); |
941 | 941 | ||
942 | /* keep within max_addr= and min_addr= command line arg */ | 942 | /* keep within max_addr= and min_addr= command line arg */ |
943 | as = max(as, min_addr); | 943 | as = max(as, min_addr); |
944 | ae = min(ae, max_addr); | 944 | ae = min(ae, max_addr); |
945 | if (ae <= as) | 945 | if (ae <= as) |
946 | continue; | 946 | continue; |
947 | 947 | ||
948 | /* avoid going over mem= command line arg */ | 948 | /* avoid going over mem= command line arg */ |
949 | if (total_mem + (ae - as) > mem_limit) | 949 | if (total_mem + (ae - as) > mem_limit) |
950 | ae -= total_mem + (ae - as) - mem_limit; | 950 | ae -= total_mem + (ae - as) - mem_limit; |
951 | 951 | ||
952 | if (ae <= as) | 952 | if (ae <= as) |
953 | continue; | 953 | continue; |
954 | 954 | ||
955 | if (ae - as > space_needed) | 955 | if (ae - as > space_needed) |
956 | break; | 956 | break; |
957 | } | 957 | } |
958 | if (p >= efi_map_end) | 958 | if (p >= efi_map_end) |
959 | panic("Can't allocate space for kernel memory descriptors"); | 959 | panic("Can't allocate space for kernel memory descriptors"); |
960 | 960 | ||
961 | return __va(as); | 961 | return __va(as); |
962 | } | 962 | } |
963 | 963 | ||
964 | /* | 964 | /* |
965 | * Walk the EFI memory map and gather all memory available for kernel | 965 | * Walk the EFI memory map and gather all memory available for kernel |
966 | * to use. We can allocate partial granules only if the unavailable | 966 | * to use. We can allocate partial granules only if the unavailable |
967 | * parts exist, and are WB. | 967 | * parts exist, and are WB. |
968 | */ | 968 | */ |
969 | void | 969 | void |
970 | efi_memmap_init(unsigned long *s, unsigned long *e) | 970 | efi_memmap_init(unsigned long *s, unsigned long *e) |
971 | { | 971 | { |
972 | struct kern_memdesc *k, *prev = NULL; | 972 | struct kern_memdesc *k, *prev = NULL; |
973 | u64 contig_low=0, contig_high=0; | 973 | u64 contig_low=0, contig_high=0; |
974 | u64 as, ae, lim; | 974 | u64 as, ae, lim; |
975 | void *efi_map_start, *efi_map_end, *p, *q; | 975 | void *efi_map_start, *efi_map_end, *p, *q; |
976 | efi_memory_desc_t *md, *pmd = NULL, *check_md; | 976 | efi_memory_desc_t *md, *pmd = NULL, *check_md; |
977 | u64 efi_desc_size; | 977 | u64 efi_desc_size; |
978 | unsigned long total_mem = 0; | 978 | unsigned long total_mem = 0; |
979 | 979 | ||
980 | k = kern_memmap = find_memmap_space(); | 980 | k = kern_memmap = find_memmap_space(); |
981 | 981 | ||
982 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 982 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
983 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 983 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
984 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 984 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
985 | 985 | ||
986 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { | 986 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { |
987 | md = p; | 987 | md = p; |
988 | if (!efi_wb(md)) { | 988 | if (!efi_wb(md)) { |
989 | if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY || | 989 | if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY || |
990 | md->type == EFI_BOOT_SERVICES_DATA)) { | 990 | md->type == EFI_BOOT_SERVICES_DATA)) { |
991 | k->attribute = EFI_MEMORY_UC; | 991 | k->attribute = EFI_MEMORY_UC; |
992 | k->start = md->phys_addr; | 992 | k->start = md->phys_addr; |
993 | k->num_pages = md->num_pages; | 993 | k->num_pages = md->num_pages; |
994 | k++; | 994 | k++; |
995 | } | 995 | } |
996 | continue; | 996 | continue; |
997 | } | 997 | } |
998 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | 998 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { |
999 | contig_low = GRANULEROUNDUP(md->phys_addr); | 999 | contig_low = GRANULEROUNDUP(md->phys_addr); |
1000 | contig_high = efi_md_end(md); | 1000 | contig_high = efi_md_end(md); |
1001 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | 1001 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { |
1002 | check_md = q; | 1002 | check_md = q; |
1003 | if (!efi_wb(check_md)) | 1003 | if (!efi_wb(check_md)) |
1004 | break; | 1004 | break; |
1005 | if (contig_high != check_md->phys_addr) | 1005 | if (contig_high != check_md->phys_addr) |
1006 | break; | 1006 | break; |
1007 | contig_high = efi_md_end(check_md); | 1007 | contig_high = efi_md_end(check_md); |
1008 | } | 1008 | } |
1009 | contig_high = GRANULEROUNDDOWN(contig_high); | 1009 | contig_high = GRANULEROUNDDOWN(contig_high); |
1010 | } | 1010 | } |
1011 | if (!is_memory_available(md)) | 1011 | if (!is_memory_available(md)) |
1012 | continue; | 1012 | continue; |
1013 | 1013 | ||
1014 | #ifdef CONFIG_CRASH_DUMP | 1014 | #ifdef CONFIG_CRASH_DUMP |
1015 | /* saved_max_pfn should ignore max_addr= command line arg */ | 1015 | /* saved_max_pfn should ignore max_addr= command line arg */ |
1016 | if (saved_max_pfn < (efi_md_end(md) >> PAGE_SHIFT)) | 1016 | if (saved_max_pfn < (efi_md_end(md) >> PAGE_SHIFT)) |
1017 | saved_max_pfn = (efi_md_end(md) >> PAGE_SHIFT); | 1017 | saved_max_pfn = (efi_md_end(md) >> PAGE_SHIFT); |
1018 | #endif | 1018 | #endif |
1019 | /* | 1019 | /* |
1020 | * Round ends inward to granule boundaries | 1020 | * Round ends inward to granule boundaries |
1021 | * Give trimmings to uncached allocator | 1021 | * Give trimmings to uncached allocator |
1022 | */ | 1022 | */ |
1023 | if (md->phys_addr < contig_low) { | 1023 | if (md->phys_addr < contig_low) { |
1024 | lim = min(efi_md_end(md), contig_low); | 1024 | lim = min(efi_md_end(md), contig_low); |
1025 | if (efi_uc(md)) { | 1025 | if (efi_uc(md)) { |
1026 | if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC && | 1026 | if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC && |
1027 | kmd_end(k-1) == md->phys_addr) { | 1027 | kmd_end(k-1) == md->phys_addr) { |
1028 | (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | 1028 | (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT; |
1029 | } else { | 1029 | } else { |
1030 | k->attribute = EFI_MEMORY_UC; | 1030 | k->attribute = EFI_MEMORY_UC; |
1031 | k->start = md->phys_addr; | 1031 | k->start = md->phys_addr; |
1032 | k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | 1032 | k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT; |
1033 | k++; | 1033 | k++; |
1034 | } | 1034 | } |
1035 | } | 1035 | } |
1036 | as = contig_low; | 1036 | as = contig_low; |
1037 | } else | 1037 | } else |
1038 | as = md->phys_addr; | 1038 | as = md->phys_addr; |
1039 | 1039 | ||
1040 | if (efi_md_end(md) > contig_high) { | 1040 | if (efi_md_end(md) > contig_high) { |
1041 | lim = max(md->phys_addr, contig_high); | 1041 | lim = max(md->phys_addr, contig_high); |
1042 | if (efi_uc(md)) { | 1042 | if (efi_uc(md)) { |
1043 | if (lim == md->phys_addr && k > kern_memmap && | 1043 | if (lim == md->phys_addr && k > kern_memmap && |
1044 | (k-1)->attribute == EFI_MEMORY_UC && | 1044 | (k-1)->attribute == EFI_MEMORY_UC && |
1045 | kmd_end(k-1) == md->phys_addr) { | 1045 | kmd_end(k-1) == md->phys_addr) { |
1046 | (k-1)->num_pages += md->num_pages; | 1046 | (k-1)->num_pages += md->num_pages; |
1047 | } else { | 1047 | } else { |
1048 | k->attribute = EFI_MEMORY_UC; | 1048 | k->attribute = EFI_MEMORY_UC; |
1049 | k->start = lim; | 1049 | k->start = lim; |
1050 | k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT; | 1050 | k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT; |
1051 | k++; | 1051 | k++; |
1052 | } | 1052 | } |
1053 | } | 1053 | } |
1054 | ae = contig_high; | 1054 | ae = contig_high; |
1055 | } else | 1055 | } else |
1056 | ae = efi_md_end(md); | 1056 | ae = efi_md_end(md); |
1057 | 1057 | ||
1058 | /* keep within max_addr= and min_addr= command line arg */ | 1058 | /* keep within max_addr= and min_addr= command line arg */ |
1059 | as = max(as, min_addr); | 1059 | as = max(as, min_addr); |
1060 | ae = min(ae, max_addr); | 1060 | ae = min(ae, max_addr); |
1061 | if (ae <= as) | 1061 | if (ae <= as) |
1062 | continue; | 1062 | continue; |
1063 | 1063 | ||
1064 | /* avoid going over mem= command line arg */ | 1064 | /* avoid going over mem= command line arg */ |
1065 | if (total_mem + (ae - as) > mem_limit) | 1065 | if (total_mem + (ae - as) > mem_limit) |
1066 | ae -= total_mem + (ae - as) - mem_limit; | 1066 | ae -= total_mem + (ae - as) - mem_limit; |
1067 | 1067 | ||
1068 | if (ae <= as) | 1068 | if (ae <= as) |
1069 | continue; | 1069 | continue; |
1070 | if (prev && kmd_end(prev) == md->phys_addr) { | 1070 | if (prev && kmd_end(prev) == md->phys_addr) { |
1071 | prev->num_pages += (ae - as) >> EFI_PAGE_SHIFT; | 1071 | prev->num_pages += (ae - as) >> EFI_PAGE_SHIFT; |
1072 | total_mem += ae - as; | 1072 | total_mem += ae - as; |
1073 | continue; | 1073 | continue; |
1074 | } | 1074 | } |
1075 | k->attribute = EFI_MEMORY_WB; | 1075 | k->attribute = EFI_MEMORY_WB; |
1076 | k->start = as; | 1076 | k->start = as; |
1077 | k->num_pages = (ae - as) >> EFI_PAGE_SHIFT; | 1077 | k->num_pages = (ae - as) >> EFI_PAGE_SHIFT; |
1078 | total_mem += ae - as; | 1078 | total_mem += ae - as; |
1079 | prev = k++; | 1079 | prev = k++; |
1080 | } | 1080 | } |
1081 | k->start = ~0L; /* end-marker */ | 1081 | k->start = ~0L; /* end-marker */ |
1082 | 1082 | ||
1083 | /* reserve the memory we are using for kern_memmap */ | 1083 | /* reserve the memory we are using for kern_memmap */ |
1084 | *s = (u64)kern_memmap; | 1084 | *s = (u64)kern_memmap; |
1085 | *e = (u64)++k; | 1085 | *e = (u64)++k; |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | void | 1088 | void |
1089 | efi_initialize_iomem_resources(struct resource *code_resource, | 1089 | efi_initialize_iomem_resources(struct resource *code_resource, |
1090 | struct resource *data_resource) | 1090 | struct resource *data_resource) |
1091 | { | 1091 | { |
1092 | struct resource *res; | 1092 | struct resource *res; |
1093 | void *efi_map_start, *efi_map_end, *p; | 1093 | void *efi_map_start, *efi_map_end, *p; |
1094 | efi_memory_desc_t *md; | 1094 | efi_memory_desc_t *md; |
1095 | u64 efi_desc_size; | 1095 | u64 efi_desc_size; |
1096 | char *name; | 1096 | char *name; |
1097 | unsigned long flags; | 1097 | unsigned long flags; |
1098 | 1098 | ||
1099 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 1099 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
1100 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 1100 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
1101 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 1101 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
1102 | 1102 | ||
1103 | res = NULL; | 1103 | res = NULL; |
1104 | 1104 | ||
1105 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 1105 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
1106 | md = p; | 1106 | md = p; |
1107 | 1107 | ||
1108 | if (md->num_pages == 0) /* should not happen */ | 1108 | if (md->num_pages == 0) /* should not happen */ |
1109 | continue; | 1109 | continue; |
1110 | 1110 | ||
1111 | flags = IORESOURCE_MEM; | 1111 | flags = IORESOURCE_MEM; |
1112 | switch (md->type) { | 1112 | switch (md->type) { |
1113 | 1113 | ||
1114 | case EFI_MEMORY_MAPPED_IO: | 1114 | case EFI_MEMORY_MAPPED_IO: |
1115 | case EFI_MEMORY_MAPPED_IO_PORT_SPACE: | 1115 | case EFI_MEMORY_MAPPED_IO_PORT_SPACE: |
1116 | continue; | 1116 | continue; |
1117 | 1117 | ||
1118 | case EFI_LOADER_CODE: | 1118 | case EFI_LOADER_CODE: |
1119 | case EFI_LOADER_DATA: | 1119 | case EFI_LOADER_DATA: |
1120 | case EFI_BOOT_SERVICES_DATA: | 1120 | case EFI_BOOT_SERVICES_DATA: |
1121 | case EFI_BOOT_SERVICES_CODE: | 1121 | case EFI_BOOT_SERVICES_CODE: |
1122 | case EFI_CONVENTIONAL_MEMORY: | 1122 | case EFI_CONVENTIONAL_MEMORY: |
1123 | if (md->attribute & EFI_MEMORY_WP) { | 1123 | if (md->attribute & EFI_MEMORY_WP) { |
1124 | name = "System ROM"; | 1124 | name = "System ROM"; |
1125 | flags |= IORESOURCE_READONLY; | 1125 | flags |= IORESOURCE_READONLY; |
1126 | } else { | 1126 | } else { |
1127 | name = "System RAM"; | 1127 | name = "System RAM"; |
1128 | } | 1128 | } |
1129 | break; | 1129 | break; |
1130 | 1130 | ||
1131 | case EFI_ACPI_MEMORY_NVS: | 1131 | case EFI_ACPI_MEMORY_NVS: |
1132 | name = "ACPI Non-volatile Storage"; | 1132 | name = "ACPI Non-volatile Storage"; |
1133 | flags |= IORESOURCE_BUSY; | 1133 | flags |= IORESOURCE_BUSY; |
1134 | break; | 1134 | break; |
1135 | 1135 | ||
1136 | case EFI_UNUSABLE_MEMORY: | 1136 | case EFI_UNUSABLE_MEMORY: |
1137 | name = "reserved"; | 1137 | name = "reserved"; |
1138 | flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED; | 1138 | flags |= IORESOURCE_BUSY | IORESOURCE_DISABLED; |
1139 | break; | 1139 | break; |
1140 | 1140 | ||
1141 | case EFI_RESERVED_TYPE: | 1141 | case EFI_RESERVED_TYPE: |
1142 | case EFI_RUNTIME_SERVICES_CODE: | 1142 | case EFI_RUNTIME_SERVICES_CODE: |
1143 | case EFI_RUNTIME_SERVICES_DATA: | 1143 | case EFI_RUNTIME_SERVICES_DATA: |
1144 | case EFI_ACPI_RECLAIM_MEMORY: | 1144 | case EFI_ACPI_RECLAIM_MEMORY: |
1145 | default: | 1145 | default: |
1146 | name = "reserved"; | 1146 | name = "reserved"; |
1147 | flags |= IORESOURCE_BUSY; | 1147 | flags |= IORESOURCE_BUSY; |
1148 | break; | 1148 | break; |
1149 | } | 1149 | } |
1150 | 1150 | ||
1151 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { | 1151 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { |
1152 | printk(KERN_ERR "failed to alocate resource for iomem\n"); | 1152 | printk(KERN_ERR "failed to alocate resource for iomem\n"); |
1153 | return; | 1153 | return; |
1154 | } | 1154 | } |
1155 | 1155 | ||
1156 | res->name = name; | 1156 | res->name = name; |
1157 | res->start = md->phys_addr; | 1157 | res->start = md->phys_addr; |
1158 | res->end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; | 1158 | res->end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; |
1159 | res->flags = flags; | 1159 | res->flags = flags; |
1160 | 1160 | ||
1161 | if (insert_resource(&iomem_resource, res) < 0) | 1161 | if (insert_resource(&iomem_resource, res) < 0) |
1162 | kfree(res); | 1162 | kfree(res); |
1163 | else { | 1163 | else { |
1164 | /* | 1164 | /* |
1165 | * We don't know which region contains | 1165 | * We don't know which region contains |
1166 | * kernel data so we try it repeatedly and | 1166 | * kernel data so we try it repeatedly and |
1167 | * let the resource manager test it. | 1167 | * let the resource manager test it. |
1168 | */ | 1168 | */ |
1169 | insert_resource(res, code_resource); | 1169 | insert_resource(res, code_resource); |
1170 | insert_resource(res, data_resource); | 1170 | insert_resource(res, data_resource); |
1171 | #ifdef CONFIG_KEXEC | 1171 | #ifdef CONFIG_KEXEC |
1172 | insert_resource(res, &efi_memmap_res); | 1172 | insert_resource(res, &efi_memmap_res); |
1173 | insert_resource(res, &boot_param_res); | 1173 | insert_resource(res, &boot_param_res); |
1174 | if (crashk_res.end > crashk_res.start) | 1174 | if (crashk_res.end > crashk_res.start) |
1175 | insert_resource(res, &crashk_res); | 1175 | insert_resource(res, &crashk_res); |
1176 | #endif | 1176 | #endif |
1177 | } | 1177 | } |
1178 | } | 1178 | } |
1179 | } | 1179 | } |
1180 | 1180 | ||
1181 | #ifdef CONFIG_KEXEC | 1181 | #ifdef CONFIG_KEXEC |
1182 | /* find a block of memory aligned to 64M exclude reserved regions | 1182 | /* find a block of memory aligned to 64M exclude reserved regions |
1183 | rsvd_regions are sorted | 1183 | rsvd_regions are sorted |
1184 | */ | 1184 | */ |
1185 | unsigned long __init | 1185 | unsigned long __init |
1186 | kdump_find_rsvd_region (unsigned long size, | 1186 | kdump_find_rsvd_region (unsigned long size, |
1187 | struct rsvd_region *r, int n) | 1187 | struct rsvd_region *r, int n) |
1188 | { | 1188 | { |
1189 | int i; | 1189 | int i; |
1190 | u64 start, end; | 1190 | u64 start, end; |
1191 | u64 alignment = 1UL << _PAGE_SIZE_64M; | 1191 | u64 alignment = 1UL << _PAGE_SIZE_64M; |
1192 | void *efi_map_start, *efi_map_end, *p; | 1192 | void *efi_map_start, *efi_map_end, *p; |
1193 | efi_memory_desc_t *md; | 1193 | efi_memory_desc_t *md; |
1194 | u64 efi_desc_size; | 1194 | u64 efi_desc_size; |
1195 | 1195 | ||
1196 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 1196 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
1197 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 1197 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
1198 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 1198 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
1199 | 1199 | ||
1200 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 1200 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
1201 | md = p; | 1201 | md = p; |
1202 | if (!efi_wb(md)) | 1202 | if (!efi_wb(md)) |
1203 | continue; | 1203 | continue; |
1204 | start = ALIGN(md->phys_addr, alignment); | 1204 | start = ALIGN(md->phys_addr, alignment); |
1205 | end = efi_md_end(md); | 1205 | end = efi_md_end(md); |
1206 | for (i = 0; i < n; i++) { | 1206 | for (i = 0; i < n; i++) { |
1207 | if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { | 1207 | if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { |
1208 | if (__pa(r[i].start) > start + size) | 1208 | if (__pa(r[i].start) > start + size) |
1209 | return start; | 1209 | return start; |
1210 | start = ALIGN(__pa(r[i].end), alignment); | 1210 | start = ALIGN(__pa(r[i].end), alignment); |
1211 | if (i < n-1 && __pa(r[i+1].start) < start + size) | 1211 | if (i < n-1 && __pa(r[i+1].start) < start + size) |
1212 | continue; | 1212 | continue; |
1213 | else | 1213 | else |
1214 | break; | 1214 | break; |
1215 | } | 1215 | } |
1216 | } | 1216 | } |
1217 | if (end > start + size) | 1217 | if (end > start + size) |
1218 | return start; | 1218 | return start; |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n", | 1221 | printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n", |
1222 | size); | 1222 | size); |
1223 | return ~0UL; | 1223 | return ~0UL; |
1224 | } | 1224 | } |
1225 | #endif | 1225 | #endif |
1226 | 1226 | ||
1227 | #ifdef CONFIG_PROC_VMCORE | 1227 | #ifdef CONFIG_PROC_VMCORE |
1228 | /* locate the size find a the descriptor at a certain address */ | 1228 | /* locate the size find a the descriptor at a certain address */ |
1229 | unsigned long | 1229 | unsigned long |
1230 | vmcore_find_descriptor_size (unsigned long address) | 1230 | vmcore_find_descriptor_size (unsigned long address) |
1231 | { | 1231 | { |
1232 | void *efi_map_start, *efi_map_end, *p; | 1232 | void *efi_map_start, *efi_map_end, *p; |
1233 | efi_memory_desc_t *md; | 1233 | efi_memory_desc_t *md; |
1234 | u64 efi_desc_size; | 1234 | u64 efi_desc_size; |
1235 | unsigned long ret = 0; | 1235 | unsigned long ret = 0; |
1236 | 1236 | ||
1237 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 1237 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
1238 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 1238 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
1239 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 1239 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
1240 | 1240 | ||
1241 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 1241 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
1242 | md = p; | 1242 | md = p; |
1243 | if (efi_wb(md) && md->type == EFI_LOADER_DATA | 1243 | if (efi_wb(md) && md->type == EFI_LOADER_DATA |
1244 | && md->phys_addr == address) { | 1244 | && md->phys_addr == address) { |
1245 | ret = efi_md_size(md); | 1245 | ret = efi_md_size(md); |
1246 | break; | 1246 | break; |
1247 | } | 1247 | } |
1248 | } | 1248 | } |
1249 | 1249 | ||
1250 | if (ret == 0) | 1250 | if (ret == 0) |
1251 | printk(KERN_WARNING "Cannot locate EFI vmcore descriptor\n"); | 1251 | printk(KERN_WARNING "Cannot locate EFI vmcore descriptor\n"); |
1252 | 1252 | ||
1253 | return ret; | 1253 | return ret; |
1254 | } | 1254 | } |
1255 | #endif | 1255 | #endif |
1256 | 1256 |
include/linux/efi.h
1 | #ifndef _LINUX_EFI_H | 1 | #ifndef _LINUX_EFI_H |
2 | #define _LINUX_EFI_H | 2 | #define _LINUX_EFI_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * Extensible Firmware Interface | 5 | * Extensible Firmware Interface |
6 | * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999 | 6 | * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999 |
7 | * | 7 | * |
8 | * Copyright (C) 1999 VA Linux Systems | 8 | * Copyright (C) 1999 VA Linux Systems |
9 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | 9 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> |
10 | * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. | 10 | * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. |
11 | * David Mosberger-Tang <davidm@hpl.hp.com> | 11 | * David Mosberger-Tang <davidm@hpl.hp.com> |
12 | * Stephane Eranian <eranian@hpl.hp.com> | 12 | * Stephane Eranian <eranian@hpl.hp.com> |
13 | */ | 13 | */ |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/string.h> | 15 | #include <linux/string.h> |
16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
17 | #include <linux/types.h> | 17 | #include <linux/types.h> |
18 | #include <linux/proc_fs.h> | 18 | #include <linux/proc_fs.h> |
19 | #include <linux/rtc.h> | 19 | #include <linux/rtc.h> |
20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
21 | 21 | ||
22 | #include <asm/page.h> | 22 | #include <asm/page.h> |
23 | #include <asm/system.h> | 23 | #include <asm/system.h> |
24 | 24 | ||
25 | #define EFI_SUCCESS 0 | 25 | #define EFI_SUCCESS 0 |
26 | #define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1))) | 26 | #define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1))) |
27 | #define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1))) | 27 | #define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1))) |
28 | #define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) | 28 | #define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) |
29 | #define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) | 29 | #define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) |
30 | #define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) | 30 | #define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) |
31 | #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) | 31 | #define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) |
32 | 32 | ||
33 | typedef unsigned long efi_status_t; | 33 | typedef unsigned long efi_status_t; |
34 | typedef u8 efi_bool_t; | 34 | typedef u8 efi_bool_t; |
35 | typedef u16 efi_char16_t; /* UNICODE character */ | 35 | typedef u16 efi_char16_t; /* UNICODE character */ |
36 | 36 | ||
37 | 37 | ||
38 | typedef struct { | 38 | typedef struct { |
39 | u8 b[16]; | 39 | u8 b[16]; |
40 | } efi_guid_t; | 40 | } efi_guid_t; |
41 | 41 | ||
42 | #define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ | 42 | #define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ |
43 | ((efi_guid_t) \ | 43 | ((efi_guid_t) \ |
44 | {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ | 44 | {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ |
45 | (b) & 0xff, ((b) >> 8) & 0xff, \ | 45 | (b) & 0xff, ((b) >> 8) & 0xff, \ |
46 | (c) & 0xff, ((c) >> 8) & 0xff, \ | 46 | (c) & 0xff, ((c) >> 8) & 0xff, \ |
47 | (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) | 47 | (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) |
48 | 48 | ||
49 | /* | 49 | /* |
50 | * Generic EFI table header | 50 | * Generic EFI table header |
51 | */ | 51 | */ |
52 | typedef struct { | 52 | typedef struct { |
53 | u64 signature; | 53 | u64 signature; |
54 | u32 revision; | 54 | u32 revision; |
55 | u32 headersize; | 55 | u32 headersize; |
56 | u32 crc32; | 56 | u32 crc32; |
57 | u32 reserved; | 57 | u32 reserved; |
58 | } efi_table_hdr_t; | 58 | } efi_table_hdr_t; |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * Memory map descriptor: | 61 | * Memory map descriptor: |
62 | */ | 62 | */ |
63 | 63 | ||
64 | /* Memory types: */ | 64 | /* Memory types: */ |
65 | #define EFI_RESERVED_TYPE 0 | 65 | #define EFI_RESERVED_TYPE 0 |
66 | #define EFI_LOADER_CODE 1 | 66 | #define EFI_LOADER_CODE 1 |
67 | #define EFI_LOADER_DATA 2 | 67 | #define EFI_LOADER_DATA 2 |
68 | #define EFI_BOOT_SERVICES_CODE 3 | 68 | #define EFI_BOOT_SERVICES_CODE 3 |
69 | #define EFI_BOOT_SERVICES_DATA 4 | 69 | #define EFI_BOOT_SERVICES_DATA 4 |
70 | #define EFI_RUNTIME_SERVICES_CODE 5 | 70 | #define EFI_RUNTIME_SERVICES_CODE 5 |
71 | #define EFI_RUNTIME_SERVICES_DATA 6 | 71 | #define EFI_RUNTIME_SERVICES_DATA 6 |
72 | #define EFI_CONVENTIONAL_MEMORY 7 | 72 | #define EFI_CONVENTIONAL_MEMORY 7 |
73 | #define EFI_UNUSABLE_MEMORY 8 | 73 | #define EFI_UNUSABLE_MEMORY 8 |
74 | #define EFI_ACPI_RECLAIM_MEMORY 9 | 74 | #define EFI_ACPI_RECLAIM_MEMORY 9 |
75 | #define EFI_ACPI_MEMORY_NVS 10 | 75 | #define EFI_ACPI_MEMORY_NVS 10 |
76 | #define EFI_MEMORY_MAPPED_IO 11 | 76 | #define EFI_MEMORY_MAPPED_IO 11 |
77 | #define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 | 77 | #define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 |
78 | #define EFI_PAL_CODE 13 | 78 | #define EFI_PAL_CODE 13 |
79 | #define EFI_MAX_MEMORY_TYPE 14 | 79 | #define EFI_MAX_MEMORY_TYPE 14 |
80 | 80 | ||
81 | /* Attribute values: */ | 81 | /* Attribute values: */ |
82 | #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ | 82 | #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ |
83 | #define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ | 83 | #define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ |
84 | #define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ | 84 | #define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ |
85 | #define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ | 85 | #define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ |
86 | #define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ | 86 | #define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ |
87 | #define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ | 87 | #define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ |
88 | #define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ | 88 | #define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ |
89 | #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ | 89 | #define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ |
90 | #define EFI_MEMORY_DESCRIPTOR_VERSION 1 | 90 | #define EFI_MEMORY_DESCRIPTOR_VERSION 1 |
91 | 91 | ||
92 | #define EFI_PAGE_SHIFT 12 | 92 | #define EFI_PAGE_SHIFT 12 |
93 | 93 | ||
94 | typedef struct { | 94 | typedef struct { |
95 | u32 type; | 95 | u32 type; |
96 | u32 pad; | 96 | u32 pad; |
97 | u64 phys_addr; | 97 | u64 phys_addr; |
98 | u64 virt_addr; | 98 | u64 virt_addr; |
99 | u64 num_pages; | 99 | u64 num_pages; |
100 | u64 attribute; | 100 | u64 attribute; |
101 | } efi_memory_desc_t; | 101 | } efi_memory_desc_t; |
102 | 102 | ||
103 | typedef int (*efi_freemem_callback_t) (unsigned long start, unsigned long end, void *arg); | 103 | typedef int (*efi_freemem_callback_t) (unsigned long start, unsigned long end, void *arg); |
104 | 104 | ||
105 | /* | 105 | /* |
106 | * Types and defines for Time Services | 106 | * Types and defines for Time Services |
107 | */ | 107 | */ |
108 | #define EFI_TIME_ADJUST_DAYLIGHT 0x1 | 108 | #define EFI_TIME_ADJUST_DAYLIGHT 0x1 |
109 | #define EFI_TIME_IN_DAYLIGHT 0x2 | 109 | #define EFI_TIME_IN_DAYLIGHT 0x2 |
110 | #define EFI_UNSPECIFIED_TIMEZONE 0x07ff | 110 | #define EFI_UNSPECIFIED_TIMEZONE 0x07ff |
111 | 111 | ||
112 | typedef struct { | 112 | typedef struct { |
113 | u16 year; | 113 | u16 year; |
114 | u8 month; | 114 | u8 month; |
115 | u8 day; | 115 | u8 day; |
116 | u8 hour; | 116 | u8 hour; |
117 | u8 minute; | 117 | u8 minute; |
118 | u8 second; | 118 | u8 second; |
119 | u8 pad1; | 119 | u8 pad1; |
120 | u32 nanosecond; | 120 | u32 nanosecond; |
121 | s16 timezone; | 121 | s16 timezone; |
122 | u8 daylight; | 122 | u8 daylight; |
123 | u8 pad2; | 123 | u8 pad2; |
124 | } efi_time_t; | 124 | } efi_time_t; |
125 | 125 | ||
126 | typedef struct { | 126 | typedef struct { |
127 | u32 resolution; | 127 | u32 resolution; |
128 | u32 accuracy; | 128 | u32 accuracy; |
129 | u8 sets_to_zero; | 129 | u8 sets_to_zero; |
130 | } efi_time_cap_t; | 130 | } efi_time_cap_t; |
131 | 131 | ||
132 | /* | 132 | /* |
133 | * Types and defines for EFI ResetSystem | 133 | * Types and defines for EFI ResetSystem |
134 | */ | 134 | */ |
135 | #define EFI_RESET_COLD 0 | 135 | #define EFI_RESET_COLD 0 |
136 | #define EFI_RESET_WARM 1 | 136 | #define EFI_RESET_WARM 1 |
137 | #define EFI_RESET_SHUTDOWN 2 | 137 | #define EFI_RESET_SHUTDOWN 2 |
138 | 138 | ||
139 | /* | 139 | /* |
140 | * EFI Runtime Services table | 140 | * EFI Runtime Services table |
141 | */ | 141 | */ |
142 | #define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL) | 142 | #define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL) |
143 | #define EFI_RUNTIME_SERVICES_REVISION 0x00010000 | 143 | #define EFI_RUNTIME_SERVICES_REVISION 0x00010000 |
144 | 144 | ||
145 | typedef struct { | 145 | typedef struct { |
146 | efi_table_hdr_t hdr; | 146 | efi_table_hdr_t hdr; |
147 | unsigned long get_time; | 147 | unsigned long get_time; |
148 | unsigned long set_time; | 148 | unsigned long set_time; |
149 | unsigned long get_wakeup_time; | 149 | unsigned long get_wakeup_time; |
150 | unsigned long set_wakeup_time; | 150 | unsigned long set_wakeup_time; |
151 | unsigned long set_virtual_address_map; | 151 | unsigned long set_virtual_address_map; |
152 | unsigned long convert_pointer; | 152 | unsigned long convert_pointer; |
153 | unsigned long get_variable; | 153 | unsigned long get_variable; |
154 | unsigned long get_next_variable; | 154 | unsigned long get_next_variable; |
155 | unsigned long set_variable; | 155 | unsigned long set_variable; |
156 | unsigned long get_next_high_mono_count; | 156 | unsigned long get_next_high_mono_count; |
157 | unsigned long reset_system; | 157 | unsigned long reset_system; |
158 | } efi_runtime_services_t; | 158 | } efi_runtime_services_t; |
159 | 159 | ||
160 | typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); | 160 | typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); |
161 | typedef efi_status_t efi_set_time_t (efi_time_t *tm); | 161 | typedef efi_status_t efi_set_time_t (efi_time_t *tm); |
162 | typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending, | 162 | typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending, |
163 | efi_time_t *tm); | 163 | efi_time_t *tm); |
164 | typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm); | 164 | typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm); |
165 | typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, | 165 | typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, |
166 | unsigned long *data_size, void *data); | 166 | unsigned long *data_size, void *data); |
167 | typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name, | 167 | typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name, |
168 | efi_guid_t *vendor); | 168 | efi_guid_t *vendor); |
169 | typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, | 169 | typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, |
170 | unsigned long attr, unsigned long data_size, | 170 | unsigned long attr, unsigned long data_size, |
171 | void *data); | 171 | void *data); |
172 | typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count); | 172 | typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count); |
173 | typedef void efi_reset_system_t (int reset_type, efi_status_t status, | 173 | typedef void efi_reset_system_t (int reset_type, efi_status_t status, |
174 | unsigned long data_size, efi_char16_t *data); | 174 | unsigned long data_size, efi_char16_t *data); |
175 | typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size, | 175 | typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size, |
176 | unsigned long descriptor_size, | 176 | unsigned long descriptor_size, |
177 | u32 descriptor_version, | 177 | u32 descriptor_version, |
178 | efi_memory_desc_t *virtual_map); | 178 | efi_memory_desc_t *virtual_map); |
179 | 179 | ||
180 | /* | 180 | /* |
181 | * EFI Configuration Table and GUID definitions | 181 | * EFI Configuration Table and GUID definitions |
182 | */ | 182 | */ |
183 | #define NULL_GUID \ | 183 | #define NULL_GUID \ |
184 | EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) | 184 | EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) |
185 | 185 | ||
186 | #define MPS_TABLE_GUID \ | 186 | #define MPS_TABLE_GUID \ |
187 | EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) | 187 | EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) |
188 | 188 | ||
189 | #define ACPI_TABLE_GUID \ | 189 | #define ACPI_TABLE_GUID \ |
190 | EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) | 190 | EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) |
191 | 191 | ||
192 | #define ACPI_20_TABLE_GUID \ | 192 | #define ACPI_20_TABLE_GUID \ |
193 | EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 ) | 193 | EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 ) |
194 | 194 | ||
195 | #define SMBIOS_TABLE_GUID \ | 195 | #define SMBIOS_TABLE_GUID \ |
196 | EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) | 196 | EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) |
197 | 197 | ||
198 | #define SAL_SYSTEM_TABLE_GUID \ | 198 | #define SAL_SYSTEM_TABLE_GUID \ |
199 | EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) | 199 | EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) |
200 | 200 | ||
201 | #define HCDP_TABLE_GUID \ | 201 | #define HCDP_TABLE_GUID \ |
202 | EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 ) | 202 | EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 ) |
203 | 203 | ||
204 | #define UGA_IO_PROTOCOL_GUID \ | 204 | #define UGA_IO_PROTOCOL_GUID \ |
205 | EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 ) | 205 | EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 ) |
206 | 206 | ||
207 | #define EFI_GLOBAL_VARIABLE_GUID \ | 207 | #define EFI_GLOBAL_VARIABLE_GUID \ |
208 | EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c ) | 208 | EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c ) |
209 | 209 | ||
210 | typedef struct { | 210 | typedef struct { |
211 | efi_guid_t guid; | 211 | efi_guid_t guid; |
212 | unsigned long table; | 212 | unsigned long table; |
213 | } efi_config_table_t; | 213 | } efi_config_table_t; |
214 | 214 | ||
215 | #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) | 215 | #define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) |
216 | #define EFI_SYSTEM_TABLE_REVISION ((1 << 16) | 00) | ||
217 | 216 | ||
218 | typedef struct { | 217 | typedef struct { |
219 | efi_table_hdr_t hdr; | 218 | efi_table_hdr_t hdr; |
220 | unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ | 219 | unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ |
221 | u32 fw_revision; | 220 | u32 fw_revision; |
222 | unsigned long con_in_handle; | 221 | unsigned long con_in_handle; |
223 | unsigned long con_in; | 222 | unsigned long con_in; |
224 | unsigned long con_out_handle; | 223 | unsigned long con_out_handle; |
225 | unsigned long con_out; | 224 | unsigned long con_out; |
226 | unsigned long stderr_handle; | 225 | unsigned long stderr_handle; |
227 | unsigned long stderr; | 226 | unsigned long stderr; |
228 | efi_runtime_services_t *runtime; | 227 | efi_runtime_services_t *runtime; |
229 | unsigned long boottime; | 228 | unsigned long boottime; |
230 | unsigned long nr_tables; | 229 | unsigned long nr_tables; |
231 | unsigned long tables; | 230 | unsigned long tables; |
232 | } efi_system_table_t; | 231 | } efi_system_table_t; |
233 | 232 | ||
234 | struct efi_memory_map { | 233 | struct efi_memory_map { |
235 | void *phys_map; | 234 | void *phys_map; |
236 | void *map; | 235 | void *map; |
237 | void *map_end; | 236 | void *map_end; |
238 | int nr_map; | 237 | int nr_map; |
239 | unsigned long desc_version; | 238 | unsigned long desc_version; |
240 | unsigned long desc_size; | 239 | unsigned long desc_size; |
241 | }; | 240 | }; |
242 | 241 | ||
243 | #define EFI_INVALID_TABLE_ADDR (~0UL) | 242 | #define EFI_INVALID_TABLE_ADDR (~0UL) |
244 | 243 | ||
245 | /* | 244 | /* |
246 | * All runtime access to EFI goes through this structure: | 245 | * All runtime access to EFI goes through this structure: |
247 | */ | 246 | */ |
248 | extern struct efi { | 247 | extern struct efi { |
249 | efi_system_table_t *systab; /* EFI system table */ | 248 | efi_system_table_t *systab; /* EFI system table */ |
250 | unsigned long mps; /* MPS table */ | 249 | unsigned long mps; /* MPS table */ |
251 | unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ | 250 | unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ |
252 | unsigned long acpi20; /* ACPI table (ACPI 2.0) */ | 251 | unsigned long acpi20; /* ACPI table (ACPI 2.0) */ |
253 | unsigned long smbios; /* SM BIOS table */ | 252 | unsigned long smbios; /* SM BIOS table */ |
254 | unsigned long sal_systab; /* SAL system table */ | 253 | unsigned long sal_systab; /* SAL system table */ |
255 | unsigned long boot_info; /* boot info table */ | 254 | unsigned long boot_info; /* boot info table */ |
256 | unsigned long hcdp; /* HCDP table */ | 255 | unsigned long hcdp; /* HCDP table */ |
257 | unsigned long uga; /* UGA table */ | 256 | unsigned long uga; /* UGA table */ |
258 | efi_get_time_t *get_time; | 257 | efi_get_time_t *get_time; |
259 | efi_set_time_t *set_time; | 258 | efi_set_time_t *set_time; |
260 | efi_get_wakeup_time_t *get_wakeup_time; | 259 | efi_get_wakeup_time_t *get_wakeup_time; |
261 | efi_set_wakeup_time_t *set_wakeup_time; | 260 | efi_set_wakeup_time_t *set_wakeup_time; |
262 | efi_get_variable_t *get_variable; | 261 | efi_get_variable_t *get_variable; |
263 | efi_get_next_variable_t *get_next_variable; | 262 | efi_get_next_variable_t *get_next_variable; |
264 | efi_set_variable_t *set_variable; | 263 | efi_set_variable_t *set_variable; |
265 | efi_get_next_high_mono_count_t *get_next_high_mono_count; | 264 | efi_get_next_high_mono_count_t *get_next_high_mono_count; |
266 | efi_reset_system_t *reset_system; | 265 | efi_reset_system_t *reset_system; |
267 | efi_set_virtual_address_map_t *set_virtual_address_map; | 266 | efi_set_virtual_address_map_t *set_virtual_address_map; |
268 | } efi; | 267 | } efi; |
269 | 268 | ||
270 | static inline int | 269 | static inline int |
271 | efi_guidcmp (efi_guid_t left, efi_guid_t right) | 270 | efi_guidcmp (efi_guid_t left, efi_guid_t right) |
272 | { | 271 | { |
273 | return memcmp(&left, &right, sizeof (efi_guid_t)); | 272 | return memcmp(&left, &right, sizeof (efi_guid_t)); |
274 | } | 273 | } |
275 | 274 | ||
276 | static inline char * | 275 | static inline char * |
277 | efi_guid_unparse(efi_guid_t *guid, char *out) | 276 | efi_guid_unparse(efi_guid_t *guid, char *out) |
278 | { | 277 | { |
279 | sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", | 278 | sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
280 | guid->b[3], guid->b[2], guid->b[1], guid->b[0], | 279 | guid->b[3], guid->b[2], guid->b[1], guid->b[0], |
281 | guid->b[5], guid->b[4], guid->b[7], guid->b[6], | 280 | guid->b[5], guid->b[4], guid->b[7], guid->b[6], |
282 | guid->b[8], guid->b[9], guid->b[10], guid->b[11], | 281 | guid->b[8], guid->b[9], guid->b[10], guid->b[11], |
283 | guid->b[12], guid->b[13], guid->b[14], guid->b[15]); | 282 | guid->b[12], guid->b[13], guid->b[14], guid->b[15]); |
284 | return out; | 283 | return out; |
285 | } | 284 | } |
286 | 285 | ||
287 | extern void efi_init (void); | 286 | extern void efi_init (void); |
288 | extern void *efi_get_pal_addr (void); | 287 | extern void *efi_get_pal_addr (void); |
289 | extern void efi_map_pal_code (void); | 288 | extern void efi_map_pal_code (void); |
290 | extern void efi_map_memmap(void); | 289 | extern void efi_map_memmap(void); |
291 | extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); | 290 | extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); |
292 | extern void efi_gettimeofday (struct timespec *ts); | 291 | extern void efi_gettimeofday (struct timespec *ts); |
293 | extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ | 292 | extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ |
294 | extern u64 efi_get_iobase (void); | 293 | extern u64 efi_get_iobase (void); |
295 | extern u32 efi_mem_type (unsigned long phys_addr); | 294 | extern u32 efi_mem_type (unsigned long phys_addr); |
296 | extern u64 efi_mem_attributes (unsigned long phys_addr); | 295 | extern u64 efi_mem_attributes (unsigned long phys_addr); |
297 | extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); | 296 | extern u64 efi_mem_attribute (unsigned long phys_addr, unsigned long size); |
298 | extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, | 297 | extern int efi_mem_attribute_range (unsigned long phys_addr, unsigned long size, |
299 | u64 attr); | 298 | u64 attr); |
300 | extern int __init efi_uart_console_only (void); | 299 | extern int __init efi_uart_console_only (void); |
301 | extern void efi_initialize_iomem_resources(struct resource *code_resource, | 300 | extern void efi_initialize_iomem_resources(struct resource *code_resource, |
302 | struct resource *data_resource); | 301 | struct resource *data_resource); |
303 | extern unsigned long efi_get_time(void); | 302 | extern unsigned long efi_get_time(void); |
304 | extern int efi_set_rtc_mmss(unsigned long nowtime); | 303 | extern int efi_set_rtc_mmss(unsigned long nowtime); |
305 | extern int is_available_memory(efi_memory_desc_t * md); | 304 | extern int is_available_memory(efi_memory_desc_t * md); |
306 | extern struct efi_memory_map memmap; | 305 | extern struct efi_memory_map memmap; |
307 | 306 | ||
308 | /** | 307 | /** |
309 | * efi_range_is_wc - check the WC bit on an address range | 308 | * efi_range_is_wc - check the WC bit on an address range |
310 | * @start: starting kvirt address | 309 | * @start: starting kvirt address |
311 | * @len: length of range | 310 | * @len: length of range |
312 | * | 311 | * |
313 | * Consult the EFI memory map and make sure it's ok to set this range WC. | 312 | * Consult the EFI memory map and make sure it's ok to set this range WC. |
314 | * Returns true or false. | 313 | * Returns true or false. |
315 | */ | 314 | */ |
316 | static inline int efi_range_is_wc(unsigned long start, unsigned long len) | 315 | static inline int efi_range_is_wc(unsigned long start, unsigned long len) |
317 | { | 316 | { |
318 | unsigned long i; | 317 | unsigned long i; |
319 | 318 | ||
320 | for (i = 0; i < len; i += (1UL << EFI_PAGE_SHIFT)) { | 319 | for (i = 0; i < len; i += (1UL << EFI_PAGE_SHIFT)) { |
321 | unsigned long paddr = __pa(start + i); | 320 | unsigned long paddr = __pa(start + i); |
322 | if (!(efi_mem_attributes(paddr) & EFI_MEMORY_WC)) | 321 | if (!(efi_mem_attributes(paddr) & EFI_MEMORY_WC)) |
323 | return 0; | 322 | return 0; |
324 | } | 323 | } |
325 | /* The range checked out */ | 324 | /* The range checked out */ |
326 | return 1; | 325 | return 1; |
327 | } | 326 | } |
328 | 327 | ||
329 | #ifdef CONFIG_EFI_PCDP | 328 | #ifdef CONFIG_EFI_PCDP |
330 | extern int __init efi_setup_pcdp_console(char *); | 329 | extern int __init efi_setup_pcdp_console(char *); |
331 | #endif | 330 | #endif |
332 | 331 | ||
333 | /* | 332 | /* |
334 | * We play games with efi_enabled so that the compiler will, if possible, remove | 333 | * We play games with efi_enabled so that the compiler will, if possible, remove |
335 | * EFI-related code altogether. | 334 | * EFI-related code altogether. |
336 | */ | 335 | */ |
337 | #ifdef CONFIG_EFI | 336 | #ifdef CONFIG_EFI |
338 | # ifdef CONFIG_X86 | 337 | # ifdef CONFIG_X86 |
339 | extern int efi_enabled; | 338 | extern int efi_enabled; |
340 | # else | 339 | # else |
341 | # define efi_enabled 1 | 340 | # define efi_enabled 1 |
342 | # endif | 341 | # endif |
343 | #else | 342 | #else |
344 | # define efi_enabled 0 | 343 | # define efi_enabled 0 |
345 | #endif | 344 | #endif |
346 | 345 | ||
347 | /* | 346 | /* |
348 | * Variable Attributes | 347 | * Variable Attributes |
349 | */ | 348 | */ |
350 | #define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 | 349 | #define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 |
351 | #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 | 350 | #define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 |
352 | #define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 | 351 | #define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 |
353 | 352 | ||
354 | /* | 353 | /* |
355 | * EFI Device Path information | 354 | * EFI Device Path information |
356 | */ | 355 | */ |
357 | #define EFI_DEV_HW 0x01 | 356 | #define EFI_DEV_HW 0x01 |
358 | #define EFI_DEV_PCI 1 | 357 | #define EFI_DEV_PCI 1 |
359 | #define EFI_DEV_PCCARD 2 | 358 | #define EFI_DEV_PCCARD 2 |
360 | #define EFI_DEV_MEM_MAPPED 3 | 359 | #define EFI_DEV_MEM_MAPPED 3 |
361 | #define EFI_DEV_VENDOR 4 | 360 | #define EFI_DEV_VENDOR 4 |
362 | #define EFI_DEV_CONTROLLER 5 | 361 | #define EFI_DEV_CONTROLLER 5 |
363 | #define EFI_DEV_ACPI 0x02 | 362 | #define EFI_DEV_ACPI 0x02 |
364 | #define EFI_DEV_BASIC_ACPI 1 | 363 | #define EFI_DEV_BASIC_ACPI 1 |
365 | #define EFI_DEV_EXPANDED_ACPI 2 | 364 | #define EFI_DEV_EXPANDED_ACPI 2 |
366 | #define EFI_DEV_MSG 0x03 | 365 | #define EFI_DEV_MSG 0x03 |
367 | #define EFI_DEV_MSG_ATAPI 1 | 366 | #define EFI_DEV_MSG_ATAPI 1 |
368 | #define EFI_DEV_MSG_SCSI 2 | 367 | #define EFI_DEV_MSG_SCSI 2 |
369 | #define EFI_DEV_MSG_FC 3 | 368 | #define EFI_DEV_MSG_FC 3 |
370 | #define EFI_DEV_MSG_1394 4 | 369 | #define EFI_DEV_MSG_1394 4 |
371 | #define EFI_DEV_MSG_USB 5 | 370 | #define EFI_DEV_MSG_USB 5 |
372 | #define EFI_DEV_MSG_USB_CLASS 15 | 371 | #define EFI_DEV_MSG_USB_CLASS 15 |
373 | #define EFI_DEV_MSG_I20 6 | 372 | #define EFI_DEV_MSG_I20 6 |
374 | #define EFI_DEV_MSG_MAC 11 | 373 | #define EFI_DEV_MSG_MAC 11 |
375 | #define EFI_DEV_MSG_IPV4 12 | 374 | #define EFI_DEV_MSG_IPV4 12 |
376 | #define EFI_DEV_MSG_IPV6 13 | 375 | #define EFI_DEV_MSG_IPV6 13 |
377 | #define EFI_DEV_MSG_INFINIBAND 9 | 376 | #define EFI_DEV_MSG_INFINIBAND 9 |
378 | #define EFI_DEV_MSG_UART 14 | 377 | #define EFI_DEV_MSG_UART 14 |
379 | #define EFI_DEV_MSG_VENDOR 10 | 378 | #define EFI_DEV_MSG_VENDOR 10 |
380 | #define EFI_DEV_MEDIA 0x04 | 379 | #define EFI_DEV_MEDIA 0x04 |
381 | #define EFI_DEV_MEDIA_HARD_DRIVE 1 | 380 | #define EFI_DEV_MEDIA_HARD_DRIVE 1 |
382 | #define EFI_DEV_MEDIA_CDROM 2 | 381 | #define EFI_DEV_MEDIA_CDROM 2 |
383 | #define EFI_DEV_MEDIA_VENDOR 3 | 382 | #define EFI_DEV_MEDIA_VENDOR 3 |
384 | #define EFI_DEV_MEDIA_FILE 4 | 383 | #define EFI_DEV_MEDIA_FILE 4 |
385 | #define EFI_DEV_MEDIA_PROTOCOL 5 | 384 | #define EFI_DEV_MEDIA_PROTOCOL 5 |
386 | #define EFI_DEV_BIOS_BOOT 0x05 | 385 | #define EFI_DEV_BIOS_BOOT 0x05 |
387 | #define EFI_DEV_END_PATH 0x7F | 386 | #define EFI_DEV_END_PATH 0x7F |
388 | #define EFI_DEV_END_PATH2 0xFF | 387 | #define EFI_DEV_END_PATH2 0xFF |
389 | #define EFI_DEV_END_INSTANCE 0x01 | 388 | #define EFI_DEV_END_INSTANCE 0x01 |
390 | #define EFI_DEV_END_ENTIRE 0xFF | 389 | #define EFI_DEV_END_ENTIRE 0xFF |
391 | 390 | ||
392 | struct efi_generic_dev_path { | 391 | struct efi_generic_dev_path { |
393 | u8 type; | 392 | u8 type; |
394 | u8 sub_type; | 393 | u8 sub_type; |
395 | u16 length; | 394 | u16 length; |
396 | } __attribute ((packed)); | 395 | } __attribute ((packed)); |
397 | 396 | ||
398 | #endif /* _LINUX_EFI_H */ | 397 | #endif /* _LINUX_EFI_H */ |
399 | 398 |