diff options
Diffstat (limited to 'arch/ia64/kernel/efi.c')
-rw-r--r-- | arch/ia64/kernel/efi.c | 502 |
1 files changed, 272 insertions, 230 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 242d79341120..919070a9aed7 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c | |||
@@ -1,7 +1,8 @@ | |||
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 |
5 | * April 30, 1999 | ||
5 | * | 6 | * |
6 | * Copyright (C) 1999 VA Linux Systems | 7 | * Copyright (C) 1999 VA Linux Systems |
7 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> | 8 | * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> |
@@ -48,145 +49,157 @@ static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL; | |||
48 | 49 | ||
49 | #define efi_call_virt(f, args...) (*(f))(args) | 50 | #define efi_call_virt(f, args...) (*(f))(args) |
50 | 51 | ||
51 | #define STUB_GET_TIME(prefix, adjust_arg) \ | 52 | #define STUB_GET_TIME(prefix, adjust_arg) \ |
52 | static efi_status_t \ | 53 | static efi_status_t \ |
53 | prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ | 54 | prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc) \ |
54 | { \ | 55 | { \ |
55 | struct ia64_fpreg fr[6]; \ | 56 | struct ia64_fpreg fr[6]; \ |
56 | efi_time_cap_t *atc = NULL; \ | 57 | efi_time_cap_t *atc = NULL; \ |
57 | efi_status_t ret; \ | 58 | efi_status_t ret; \ |
58 | \ | 59 | \ |
59 | if (tc) \ | 60 | if (tc) \ |
60 | atc = adjust_arg(tc); \ | 61 | atc = adjust_arg(tc); \ |
61 | ia64_save_scratch_fpregs(fr); \ | 62 | ia64_save_scratch_fpregs(fr); \ |
62 | ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \ | 63 | ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), \ |
63 | ia64_load_scratch_fpregs(fr); \ | 64 | adjust_arg(tm), atc); \ |
64 | return ret; \ | 65 | ia64_load_scratch_fpregs(fr); \ |
66 | return ret; \ | ||
65 | } | 67 | } |
66 | 68 | ||
67 | #define STUB_SET_TIME(prefix, adjust_arg) \ | 69 | #define STUB_SET_TIME(prefix, adjust_arg) \ |
68 | static efi_status_t \ | 70 | static efi_status_t \ |
69 | prefix##_set_time (efi_time_t *tm) \ | 71 | prefix##_set_time (efi_time_t *tm) \ |
70 | { \ | 72 | { \ |
71 | struct ia64_fpreg fr[6]; \ | 73 | struct ia64_fpreg fr[6]; \ |
72 | efi_status_t ret; \ | 74 | efi_status_t ret; \ |
73 | \ | 75 | \ |
74 | ia64_save_scratch_fpregs(fr); \ | 76 | ia64_save_scratch_fpregs(fr); \ |
75 | ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm)); \ | 77 | ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), \ |
76 | ia64_load_scratch_fpregs(fr); \ | 78 | adjust_arg(tm)); \ |
77 | return ret; \ | 79 | ia64_load_scratch_fpregs(fr); \ |
80 | return ret; \ | ||
78 | } | 81 | } |
79 | 82 | ||
80 | #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \ | 83 | #define STUB_GET_WAKEUP_TIME(prefix, adjust_arg) \ |
81 | static efi_status_t \ | 84 | static efi_status_t \ |
82 | prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm) \ | 85 | prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, \ |
83 | { \ | 86 | efi_time_t *tm) \ |
84 | struct ia64_fpreg fr[6]; \ | 87 | { \ |
85 | efi_status_t ret; \ | 88 | struct ia64_fpreg fr[6]; \ |
86 | \ | 89 | efi_status_t ret; \ |
87 | ia64_save_scratch_fpregs(fr); \ | 90 | \ |
88 | ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \ | 91 | ia64_save_scratch_fpregs(fr); \ |
89 | adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \ | 92 | ret = efi_call_##prefix( \ |
90 | ia64_load_scratch_fpregs(fr); \ | 93 | (efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time), \ |
91 | return ret; \ | 94 | adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm)); \ |
95 | ia64_load_scratch_fpregs(fr); \ | ||
96 | return ret; \ | ||
92 | } | 97 | } |
93 | 98 | ||
94 | #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \ | 99 | #define STUB_SET_WAKEUP_TIME(prefix, adjust_arg) \ |
95 | static efi_status_t \ | 100 | static efi_status_t \ |
96 | prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ | 101 | prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm) \ |
97 | { \ | 102 | { \ |
98 | struct ia64_fpreg fr[6]; \ | 103 | struct ia64_fpreg fr[6]; \ |
99 | efi_time_t *atm = NULL; \ | 104 | efi_time_t *atm = NULL; \ |
100 | efi_status_t ret; \ | 105 | efi_status_t ret; \ |
101 | \ | 106 | \ |
102 | if (tm) \ | 107 | if (tm) \ |
103 | atm = adjust_arg(tm); \ | 108 | atm = adjust_arg(tm); \ |
104 | ia64_save_scratch_fpregs(fr); \ | 109 | ia64_save_scratch_fpregs(fr); \ |
105 | ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ | 110 | ret = efi_call_##prefix( \ |
106 | enabled, atm); \ | 111 | (efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time), \ |
107 | ia64_load_scratch_fpregs(fr); \ | 112 | enabled, atm); \ |
108 | return ret; \ | 113 | ia64_load_scratch_fpregs(fr); \ |
114 | return ret; \ | ||
109 | } | 115 | } |
110 | 116 | ||
111 | #define STUB_GET_VARIABLE(prefix, adjust_arg) \ | 117 | #define STUB_GET_VARIABLE(prefix, adjust_arg) \ |
112 | static efi_status_t \ | 118 | static efi_status_t \ |
113 | prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ | 119 | prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, \ |
114 | unsigned long *data_size, void *data) \ | 120 | unsigned long *data_size, void *data) \ |
115 | { \ | 121 | { \ |
116 | struct ia64_fpreg fr[6]; \ | 122 | struct ia64_fpreg fr[6]; \ |
117 | u32 *aattr = NULL; \ | 123 | u32 *aattr = NULL; \ |
118 | efi_status_t ret; \ | 124 | efi_status_t ret; \ |
119 | \ | 125 | \ |
120 | if (attr) \ | 126 | if (attr) \ |
121 | aattr = adjust_arg(attr); \ | 127 | aattr = adjust_arg(attr); \ |
122 | ia64_save_scratch_fpregs(fr); \ | 128 | ia64_save_scratch_fpregs(fr); \ |
123 | ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable), \ | 129 | ret = efi_call_##prefix( \ |
124 | adjust_arg(name), adjust_arg(vendor), aattr, \ | 130 | (efi_get_variable_t *) __va(runtime->get_variable), \ |
125 | adjust_arg(data_size), adjust_arg(data)); \ | 131 | adjust_arg(name), adjust_arg(vendor), aattr, \ |
126 | ia64_load_scratch_fpregs(fr); \ | 132 | adjust_arg(data_size), adjust_arg(data)); \ |
127 | return ret; \ | 133 | ia64_load_scratch_fpregs(fr); \ |
134 | return ret; \ | ||
128 | } | 135 | } |
129 | 136 | ||
130 | #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \ | 137 | #define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg) \ |
131 | static efi_status_t \ | 138 | static efi_status_t \ |
132 | prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor) \ | 139 | prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, \ |
133 | { \ | 140 | efi_guid_t *vendor) \ |
134 | struct ia64_fpreg fr[6]; \ | 141 | { \ |
135 | efi_status_t ret; \ | 142 | struct ia64_fpreg fr[6]; \ |
136 | \ | 143 | efi_status_t ret; \ |
137 | ia64_save_scratch_fpregs(fr); \ | 144 | \ |
138 | ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable), \ | 145 | ia64_save_scratch_fpregs(fr); \ |
139 | adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \ | 146 | ret = efi_call_##prefix( \ |
140 | ia64_load_scratch_fpregs(fr); \ | 147 | (efi_get_next_variable_t *) __va(runtime->get_next_variable), \ |
141 | return ret; \ | 148 | adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor)); \ |
149 | ia64_load_scratch_fpregs(fr); \ | ||
150 | return ret; \ | ||
142 | } | 151 | } |
143 | 152 | ||
144 | #define STUB_SET_VARIABLE(prefix, adjust_arg) \ | 153 | #define STUB_SET_VARIABLE(prefix, adjust_arg) \ |
145 | static efi_status_t \ | 154 | static efi_status_t \ |
146 | prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long attr, \ | 155 | prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, \ |
147 | unsigned long data_size, void *data) \ | 156 | unsigned long attr, unsigned long data_size, \ |
148 | { \ | 157 | void *data) \ |
149 | struct ia64_fpreg fr[6]; \ | 158 | { \ |
150 | efi_status_t ret; \ | 159 | struct ia64_fpreg fr[6]; \ |
151 | \ | 160 | efi_status_t ret; \ |
152 | ia64_save_scratch_fpregs(fr); \ | 161 | \ |
153 | ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable), \ | 162 | ia64_save_scratch_fpregs(fr); \ |
154 | adjust_arg(name), adjust_arg(vendor), attr, data_size, \ | 163 | ret = efi_call_##prefix( \ |
155 | adjust_arg(data)); \ | 164 | (efi_set_variable_t *) __va(runtime->set_variable), \ |
156 | ia64_load_scratch_fpregs(fr); \ | 165 | adjust_arg(name), adjust_arg(vendor), attr, data_size, \ |
157 | return ret; \ | 166 | adjust_arg(data)); \ |
167 | ia64_load_scratch_fpregs(fr); \ | ||
168 | return ret; \ | ||
158 | } | 169 | } |
159 | 170 | ||
160 | #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \ | 171 | #define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg) \ |
161 | static efi_status_t \ | 172 | static efi_status_t \ |
162 | prefix##_get_next_high_mono_count (u32 *count) \ | 173 | prefix##_get_next_high_mono_count (u32 *count) \ |
163 | { \ | 174 | { \ |
164 | struct ia64_fpreg fr[6]; \ | 175 | struct ia64_fpreg fr[6]; \ |
165 | efi_status_t ret; \ | 176 | efi_status_t ret; \ |
166 | \ | 177 | \ |
167 | ia64_save_scratch_fpregs(fr); \ | 178 | ia64_save_scratch_fpregs(fr); \ |
168 | ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \ | 179 | ret = efi_call_##prefix((efi_get_next_high_mono_count_t *) \ |
169 | __va(runtime->get_next_high_mono_count), adjust_arg(count)); \ | 180 | __va(runtime->get_next_high_mono_count), \ |
170 | ia64_load_scratch_fpregs(fr); \ | 181 | adjust_arg(count)); \ |
171 | return ret; \ | 182 | ia64_load_scratch_fpregs(fr); \ |
183 | return ret; \ | ||
172 | } | 184 | } |
173 | 185 | ||
174 | #define STUB_RESET_SYSTEM(prefix, adjust_arg) \ | 186 | #define STUB_RESET_SYSTEM(prefix, adjust_arg) \ |
175 | static void \ | 187 | static void \ |
176 | prefix##_reset_system (int reset_type, efi_status_t status, \ | 188 | prefix##_reset_system (int reset_type, efi_status_t status, \ |
177 | unsigned long data_size, efi_char16_t *data) \ | 189 | unsigned long data_size, efi_char16_t *data) \ |
178 | { \ | 190 | { \ |
179 | struct ia64_fpreg fr[6]; \ | 191 | struct ia64_fpreg fr[6]; \ |
180 | efi_char16_t *adata = NULL; \ | 192 | efi_char16_t *adata = NULL; \ |
181 | \ | 193 | \ |
182 | if (data) \ | 194 | if (data) \ |
183 | adata = adjust_arg(data); \ | 195 | adata = adjust_arg(data); \ |
184 | \ | 196 | \ |
185 | ia64_save_scratch_fpregs(fr); \ | 197 | ia64_save_scratch_fpregs(fr); \ |
186 | efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system), \ | 198 | efi_call_##prefix( \ |
187 | reset_type, status, data_size, adata); \ | 199 | (efi_reset_system_t *) __va(runtime->reset_system), \ |
188 | /* should not return, but just in case... */ \ | 200 | reset_type, status, data_size, adata); \ |
189 | ia64_load_scratch_fpregs(fr); \ | 201 | /* should not return, but just in case... */ \ |
202 | ia64_load_scratch_fpregs(fr); \ | ||
190 | } | 203 | } |
191 | 204 | ||
192 | #define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg)) | 205 | #define phys_ptr(arg) ((__typeof__(arg)) ia64_tpa(arg)) |
@@ -223,7 +236,8 @@ efi_gettimeofday (struct timespec *ts) | |||
223 | return; | 236 | return; |
224 | } | 237 | } |
225 | 238 | ||
226 | ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); | 239 | ts->tv_sec = mktime(tm.year, tm.month, tm.day, |
240 | tm.hour, tm.minute, tm.second); | ||
227 | ts->tv_nsec = tm.nanosecond; | 241 | ts->tv_nsec = tm.nanosecond; |
228 | } | 242 | } |
229 | 243 | ||
@@ -297,8 +311,8 @@ walk (efi_freemem_callback_t callback, void *arg, u64 attr) | |||
297 | } | 311 | } |
298 | 312 | ||
299 | /* | 313 | /* |
300 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that | 314 | * Walk the EFI memory map and call CALLBACK once for each EFI memory |
301 | * has memory that is available for OS use. | 315 | * descriptor that has memory that is available for OS use. |
302 | */ | 316 | */ |
303 | void | 317 | void |
304 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) | 318 | efi_memmap_walk (efi_freemem_callback_t callback, void *arg) |
@@ -307,8 +321,8 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg) | |||
307 | } | 321 | } |
308 | 322 | ||
309 | /* | 323 | /* |
310 | * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that | 324 | * Walk the EFI memory map and call CALLBACK once for each EFI memory |
311 | * has memory that is available for uncached allocator. | 325 | * descriptor that has memory that is available for uncached allocator. |
312 | */ | 326 | */ |
313 | void | 327 | void |
314 | efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) | 328 | efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) |
@@ -317,11 +331,10 @@ efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) | |||
317 | } | 331 | } |
318 | 332 | ||
319 | /* | 333 | /* |
320 | * Look for the PAL_CODE region reported by EFI and maps it using an | 334 | * Look for the PAL_CODE region reported by EFI and map it using an |
321 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor | 335 | * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor |
322 | * Abstraction Layer chapter 11 in ADAG | 336 | * Abstraction Layer chapter 11 in ADAG |
323 | */ | 337 | */ |
324 | |||
325 | void * | 338 | void * |
326 | efi_get_pal_addr (void) | 339 | efi_get_pal_addr (void) |
327 | { | 340 | { |
@@ -341,45 +354,47 @@ efi_get_pal_addr (void) | |||
341 | continue; | 354 | continue; |
342 | 355 | ||
343 | if (++pal_code_count > 1) { | 356 | if (++pal_code_count > 1) { |
344 | printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n", | 357 | printk(KERN_ERR "Too many EFI Pal Code memory ranges, " |
345 | md->phys_addr); | 358 | "dropped @ %lx\n", md->phys_addr); |
346 | continue; | 359 | continue; |
347 | } | 360 | } |
348 | /* | 361 | /* |
349 | * The only ITLB entry in region 7 that is used is the one installed by | 362 | * The only ITLB entry in region 7 that is used is the one |
350 | * __start(). That entry covers a 64MB range. | 363 | * installed by __start(). That entry covers a 64MB range. |
351 | */ | 364 | */ |
352 | mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1); | 365 | mask = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1); |
353 | vaddr = PAGE_OFFSET + md->phys_addr; | 366 | vaddr = PAGE_OFFSET + md->phys_addr; |
354 | 367 | ||
355 | /* | 368 | /* |
356 | * We must check that the PAL mapping won't overlap with the kernel | 369 | * We must check that the PAL mapping won't overlap with the |
357 | * mapping. | 370 | * kernel mapping. |
358 | * | 371 | * |
359 | * PAL code is guaranteed to be aligned on a power of 2 between 4k and | 372 | * PAL code is guaranteed to be aligned on a power of 2 between |
360 | * 256KB and that only one ITR is needed to map it. This implies that the | 373 | * 4k and 256KB and that only one ITR is needed to map it. This |
361 | * PAL code is always aligned on its size, i.e., the closest matching page | 374 | * implies that the PAL code is always aligned on its size, |
362 | * size supported by the TLB. Therefore PAL code is guaranteed never to | 375 | * i.e., the closest matching page size supported by the TLB. |
363 | * cross a 64MB unless it is bigger than 64MB (very unlikely!). So for | 376 | * Therefore PAL code is guaranteed never to cross a 64MB unless |
364 | * now the following test is enough to determine whether or not we need a | 377 | * it is bigger than 64MB (very unlikely!). So for now the |
365 | * dedicated ITR for the PAL code. | 378 | * following test is enough to determine whether or not we need |
379 | * a dedicated ITR for the PAL code. | ||
366 | */ | 380 | */ |
367 | if ((vaddr & mask) == (KERNEL_START & mask)) { | 381 | if ((vaddr & mask) == (KERNEL_START & mask)) { |
368 | printk(KERN_INFO "%s: no need to install ITR for PAL code\n", | 382 | printk(KERN_INFO "%s: no need to install ITR for " |
369 | __FUNCTION__); | 383 | "PAL code\n", __FUNCTION__); |
370 | continue; | 384 | continue; |
371 | } | 385 | } |
372 | 386 | ||
373 | if (efi_md_size(md) > IA64_GRANULE_SIZE) | 387 | if (efi_md_size(md) > IA64_GRANULE_SIZE) |
374 | panic("Woah! PAL code size bigger than a granule!"); | 388 | panic("Whoa! PAL code size bigger than a granule!"); |
375 | 389 | ||
376 | #if EFI_DEBUG | 390 | #if EFI_DEBUG |
377 | mask = ~((1 << IA64_GRANULE_SHIFT) - 1); | 391 | mask = ~((1 << IA64_GRANULE_SHIFT) - 1); |
378 | 392 | ||
379 | printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n", | 393 | printk(KERN_INFO "CPU %d: mapping PAL code " |
380 | smp_processor_id(), md->phys_addr, | 394 | "[0x%lx-0x%lx) into [0x%lx-0x%lx)\n", |
381 | md->phys_addr + efi_md_size(md), | 395 | smp_processor_id(), md->phys_addr, |
382 | vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); | 396 | md->phys_addr + efi_md_size(md), |
397 | vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); | ||
383 | #endif | 398 | #endif |
384 | return __va(md->phys_addr); | 399 | return __va(md->phys_addr); |
385 | } | 400 | } |
@@ -401,11 +416,11 @@ efi_map_pal_code (void) | |||
401 | * Cannot write to CRx with PSR.ic=1 | 416 | * Cannot write to CRx with PSR.ic=1 |
402 | */ | 417 | */ |
403 | psr = ia64_clear_ic(); | 418 | psr = ia64_clear_ic(); |
404 | ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) pal_vaddr), | 419 | ia64_itr(0x1, IA64_TR_PALCODE, |
420 | GRANULEROUNDDOWN((unsigned long) pal_vaddr), | ||
405 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), | 421 | pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)), |
406 | IA64_GRANULE_SHIFT); | 422 | IA64_GRANULE_SHIFT); |
407 | ia64_set_psr(psr); /* restore psr */ | 423 | ia64_set_psr(psr); /* restore psr */ |
408 | ia64_srlz_i(); | ||
409 | } | 424 | } |
410 | 425 | ||
411 | void __init | 426 | void __init |
@@ -418,7 +433,10 @@ efi_init (void) | |||
418 | char *cp, vendor[100] = "unknown"; | 433 | char *cp, vendor[100] = "unknown"; |
419 | int i; | 434 | int i; |
420 | 435 | ||
421 | /* it's too early to be able to use the standard kernel command line support... */ | 436 | /* |
437 | * It's too early to be able to use the standard kernel command line | ||
438 | * support... | ||
439 | */ | ||
422 | for (cp = boot_command_line; *cp; ) { | 440 | for (cp = boot_command_line; *cp; ) { |
423 | if (memcmp(cp, "mem=", 4) == 0) { | 441 | if (memcmp(cp, "mem=", 4) == 0) { |
424 | mem_limit = memparse(cp + 4, &cp); | 442 | mem_limit = memparse(cp + 4, &cp); |
@@ -434,9 +452,11 @@ efi_init (void) | |||
434 | } | 452 | } |
435 | } | 453 | } |
436 | if (min_addr != 0UL) | 454 | if (min_addr != 0UL) |
437 | printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20); | 455 | printk(KERN_INFO "Ignoring memory below %luMB\n", |
456 | min_addr >> 20); | ||
438 | if (max_addr != ~0UL) | 457 | if (max_addr != ~0UL) |
439 | printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20); | 458 | printk(KERN_INFO "Ignoring memory above %luMB\n", |
459 | max_addr >> 20); | ||
440 | 460 | ||
441 | efi.systab = __va(ia64_boot_param->efi_systab); | 461 | efi.systab = __va(ia64_boot_param->efi_systab); |
442 | 462 | ||
@@ -444,9 +464,9 @@ efi_init (void) | |||
444 | * Verify the EFI Table | 464 | * Verify the EFI Table |
445 | */ | 465 | */ |
446 | if (efi.systab == NULL) | 466 | if (efi.systab == NULL) |
447 | panic("Woah! Can't find EFI system table.\n"); | 467 | panic("Whoa! Can't find EFI system table.\n"); |
448 | if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | 468 | if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) |
449 | panic("Woah! EFI system table signature incorrect\n"); | 469 | panic("Whoa! EFI system table signature incorrect\n"); |
450 | if ((efi.systab->hdr.revision >> 16) == 0) | 470 | if ((efi.systab->hdr.revision >> 16) == 0) |
451 | printk(KERN_WARNING "Warning: EFI system table version " | 471 | printk(KERN_WARNING "Warning: EFI system table version " |
452 | "%d.%02d, expected 1.00 or greater\n", | 472 | "%d.%02d, expected 1.00 or greater\n", |
@@ -464,7 +484,8 @@ efi_init (void) | |||
464 | } | 484 | } |
465 | 485 | ||
466 | printk(KERN_INFO "EFI v%u.%.02u by %s:", | 486 | printk(KERN_INFO "EFI v%u.%.02u by %s:", |
467 | efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); | 487 | efi.systab->hdr.revision >> 16, |
488 | efi.systab->hdr.revision & 0xffff, vendor); | ||
468 | 489 | ||
469 | efi.mps = EFI_INVALID_TABLE_ADDR; | 490 | efi.mps = EFI_INVALID_TABLE_ADDR; |
470 | efi.acpi = EFI_INVALID_TABLE_ADDR; | 491 | efi.acpi = EFI_INVALID_TABLE_ADDR; |
@@ -519,9 +540,12 @@ efi_init (void) | |||
519 | efi_memory_desc_t *md; | 540 | efi_memory_desc_t *md; |
520 | void *p; | 541 | void *p; |
521 | 542 | ||
522 | for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) { | 543 | for (i = 0, p = efi_map_start; p < efi_map_end; |
544 | ++i, p += efi_desc_size) | ||
545 | { | ||
523 | md = p; | 546 | md = p; |
524 | printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", | 547 | printk("mem%02u: type=%u, attr=0x%lx, " |
548 | "range=[0x%016lx-0x%016lx) (%luMB)\n", | ||
525 | i, md->type, md->attribute, md->phys_addr, | 549 | i, md->type, md->attribute, md->phys_addr, |
526 | md->phys_addr + efi_md_size(md), | 550 | md->phys_addr + efi_md_size(md), |
527 | md->num_pages >> (20 - EFI_PAGE_SHIFT)); | 551 | md->num_pages >> (20 - EFI_PAGE_SHIFT)); |
@@ -549,8 +573,8 @@ efi_enter_virtual_mode (void) | |||
549 | md = p; | 573 | md = p; |
550 | if (md->attribute & EFI_MEMORY_RUNTIME) { | 574 | if (md->attribute & EFI_MEMORY_RUNTIME) { |
551 | /* | 575 | /* |
552 | * Some descriptors have multiple bits set, so the order of | 576 | * Some descriptors have multiple bits set, so the |
553 | * the tests is relevant. | 577 | * order of the tests is relevant. |
554 | */ | 578 | */ |
555 | if (md->attribute & EFI_MEMORY_WB) { | 579 | if (md->attribute & EFI_MEMORY_WB) { |
556 | md->virt_addr = (u64) __va(md->phys_addr); | 580 | md->virt_addr = (u64) __va(md->phys_addr); |
@@ -558,21 +582,26 @@ efi_enter_virtual_mode (void) | |||
558 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 582 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
559 | } else if (md->attribute & EFI_MEMORY_WC) { | 583 | } else if (md->attribute & EFI_MEMORY_WC) { |
560 | #if 0 | 584 | #if 0 |
561 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P | 585 | md->virt_addr = ia64_remap(md->phys_addr, |
562 | | _PAGE_D | 586 | (_PAGE_A | |
563 | | _PAGE_MA_WC | 587 | _PAGE_P | |
564 | | _PAGE_PL_0 | 588 | _PAGE_D | |
565 | | _PAGE_AR_RW)); | 589 | _PAGE_MA_WC | |
590 | _PAGE_PL_0 | | ||
591 | _PAGE_AR_RW)); | ||
566 | #else | 592 | #else |
567 | printk(KERN_INFO "EFI_MEMORY_WC mapping\n"); | 593 | printk(KERN_INFO "EFI_MEMORY_WC mapping\n"); |
568 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 594 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
569 | #endif | 595 | #endif |
570 | } else if (md->attribute & EFI_MEMORY_WT) { | 596 | } else if (md->attribute & EFI_MEMORY_WT) { |
571 | #if 0 | 597 | #if 0 |
572 | md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P | 598 | md->virt_addr = ia64_remap(md->phys_addr, |
573 | | _PAGE_D | _PAGE_MA_WT | 599 | (_PAGE_A | |
574 | | _PAGE_PL_0 | 600 | _PAGE_P | |
575 | | _PAGE_AR_RW)); | 601 | _PAGE_D | |
602 | _PAGE_MA_WT | | ||
603 | _PAGE_PL_0 | | ||
604 | _PAGE_AR_RW)); | ||
576 | #else | 605 | #else |
577 | printk(KERN_INFO "EFI_MEMORY_WT mapping\n"); | 606 | printk(KERN_INFO "EFI_MEMORY_WT mapping\n"); |
578 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); | 607 | md->virt_addr = (u64) ioremap(md->phys_addr, 0); |
@@ -583,16 +612,18 @@ efi_enter_virtual_mode (void) | |||
583 | 612 | ||
584 | status = efi_call_phys(__va(runtime->set_virtual_address_map), | 613 | status = efi_call_phys(__va(runtime->set_virtual_address_map), |
585 | ia64_boot_param->efi_memmap_size, | 614 | ia64_boot_param->efi_memmap_size, |
586 | efi_desc_size, ia64_boot_param->efi_memdesc_version, | 615 | efi_desc_size, |
616 | ia64_boot_param->efi_memdesc_version, | ||
587 | ia64_boot_param->efi_memmap); | 617 | ia64_boot_param->efi_memmap); |
588 | if (status != EFI_SUCCESS) { | 618 | if (status != EFI_SUCCESS) { |
589 | printk(KERN_WARNING "warning: unable to switch EFI into virtual mode " | 619 | printk(KERN_WARNING "warning: unable to switch EFI into " |
590 | "(status=%lu)\n", status); | 620 | "virtual mode (status=%lu)\n", status); |
591 | return; | 621 | return; |
592 | } | 622 | } |
593 | 623 | ||
594 | /* | 624 | /* |
595 | * Now that EFI is in virtual mode, we call the EFI functions more efficiently: | 625 | * Now that EFI is in virtual mode, we call the EFI functions more |
626 | * efficiently: | ||
596 | */ | 627 | */ |
597 | efi.get_time = virt_get_time; | 628 | efi.get_time = virt_get_time; |
598 | efi.set_time = virt_set_time; | 629 | efi.set_time = virt_set_time; |
@@ -606,8 +637,8 @@ efi_enter_virtual_mode (void) | |||
606 | } | 637 | } |
607 | 638 | ||
608 | /* | 639 | /* |
609 | * Walk the EFI memory map looking for the I/O port range. There can only be one entry of | 640 | * Walk the EFI memory map looking for the I/O port range. There can only be |
610 | * this type, other I/O port ranges should be described via ACPI. | 641 | * one entry of this type, other I/O port ranges should be described via ACPI. |
611 | */ | 642 | */ |
612 | u64 | 643 | u64 |
613 | efi_get_iobase (void) | 644 | efi_get_iobase (void) |
@@ -678,7 +709,6 @@ efi_memmap_intersects (unsigned long phys_addr, unsigned long size) | |||
678 | 709 | ||
679 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 710 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
680 | md = p; | 711 | md = p; |
681 | |||
682 | if (md->phys_addr < end && efi_md_end(md) > phys_addr) | 712 | if (md->phys_addr < end && efi_md_end(md) > phys_addr) |
683 | return 1; | 713 | return 1; |
684 | } | 714 | } |
@@ -731,7 +761,7 @@ efi_mem_attribute (unsigned long phys_addr, unsigned long size) | |||
731 | if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr) | 761 | if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr) |
732 | return 0; | 762 | return 0; |
733 | } while (md); | 763 | } while (md); |
734 | return 0; | 764 | return 0; /* never reached */ |
735 | } | 765 | } |
736 | 766 | ||
737 | u64 | 767 | u64 |
@@ -767,7 +797,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size) | |||
767 | if (!md || md->attribute != attr) | 797 | if (!md || md->attribute != attr) |
768 | return 0; | 798 | return 0; |
769 | } while (md); | 799 | } while (md); |
770 | return 0; | 800 | return 0; /* never reached */ |
771 | } | 801 | } |
772 | EXPORT_SYMBOL(kern_mem_attribute); | 802 | EXPORT_SYMBOL(kern_mem_attribute); |
773 | 803 | ||
@@ -883,7 +913,7 @@ efi_uart_console_only(void) | |||
883 | return 1; | 913 | return 1; |
884 | uart = 0; | 914 | uart = 0; |
885 | } | 915 | } |
886 | hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length); | 916 | hdr = (struct efi_generic_dev_path *)((u8 *) hdr + hdr->length); |
887 | } | 917 | } |
888 | printk(KERN_ERR "Malformed %s value\n", name); | 918 | printk(KERN_ERR "Malformed %s value\n", name); |
889 | return 0; | 919 | return 0; |
@@ -921,10 +951,12 @@ find_memmap_space (void) | |||
921 | if (!efi_wb(md)) { | 951 | if (!efi_wb(md)) { |
922 | continue; | 952 | continue; |
923 | } | 953 | } |
924 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | 954 | if (pmd == NULL || !efi_wb(pmd) || |
955 | efi_md_end(pmd) != md->phys_addr) { | ||
925 | contig_low = GRANULEROUNDUP(md->phys_addr); | 956 | contig_low = GRANULEROUNDUP(md->phys_addr); |
926 | contig_high = efi_md_end(md); | 957 | contig_high = efi_md_end(md); |
927 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | 958 | for (q = p + efi_desc_size; q < efi_map_end; |
959 | q += efi_desc_size) { | ||
928 | check_md = q; | 960 | check_md = q; |
929 | if (!efi_wb(check_md)) | 961 | if (!efi_wb(check_md)) |
930 | break; | 962 | break; |
@@ -988,8 +1020,9 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
988 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { | 1020 | for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) { |
989 | md = p; | 1021 | md = p; |
990 | if (!efi_wb(md)) { | 1022 | if (!efi_wb(md)) { |
991 | if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY || | 1023 | if (efi_uc(md) && |
992 | md->type == EFI_BOOT_SERVICES_DATA)) { | 1024 | (md->type == EFI_CONVENTIONAL_MEMORY || |
1025 | md->type == EFI_BOOT_SERVICES_DATA)) { | ||
993 | k->attribute = EFI_MEMORY_UC; | 1026 | k->attribute = EFI_MEMORY_UC; |
994 | k->start = md->phys_addr; | 1027 | k->start = md->phys_addr; |
995 | k->num_pages = md->num_pages; | 1028 | k->num_pages = md->num_pages; |
@@ -997,10 +1030,12 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
997 | } | 1030 | } |
998 | continue; | 1031 | continue; |
999 | } | 1032 | } |
1000 | if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) { | 1033 | if (pmd == NULL || !efi_wb(pmd) || |
1034 | efi_md_end(pmd) != md->phys_addr) { | ||
1001 | contig_low = GRANULEROUNDUP(md->phys_addr); | 1035 | contig_low = GRANULEROUNDUP(md->phys_addr); |
1002 | contig_high = efi_md_end(md); | 1036 | contig_high = efi_md_end(md); |
1003 | for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) { | 1037 | for (q = p + efi_desc_size; q < efi_map_end; |
1038 | q += efi_desc_size) { | ||
1004 | check_md = q; | 1039 | check_md = q; |
1005 | if (!efi_wb(check_md)) | 1040 | if (!efi_wb(check_md)) |
1006 | break; | 1041 | break; |
@@ -1025,13 +1060,17 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
1025 | if (md->phys_addr < contig_low) { | 1060 | if (md->phys_addr < contig_low) { |
1026 | lim = min(efi_md_end(md), contig_low); | 1061 | lim = min(efi_md_end(md), contig_low); |
1027 | if (efi_uc(md)) { | 1062 | if (efi_uc(md)) { |
1028 | if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC && | 1063 | if (k > kern_memmap && |
1064 | (k-1)->attribute == EFI_MEMORY_UC && | ||
1029 | kmd_end(k-1) == md->phys_addr) { | 1065 | kmd_end(k-1) == md->phys_addr) { |
1030 | (k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | 1066 | (k-1)->num_pages += |
1067 | (lim - md->phys_addr) | ||
1068 | >> EFI_PAGE_SHIFT; | ||
1031 | } else { | 1069 | } else { |
1032 | k->attribute = EFI_MEMORY_UC; | 1070 | k->attribute = EFI_MEMORY_UC; |
1033 | k->start = md->phys_addr; | 1071 | k->start = md->phys_addr; |
1034 | k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT; | 1072 | k->num_pages = (lim - md->phys_addr) |
1073 | >> EFI_PAGE_SHIFT; | ||
1035 | k++; | 1074 | k++; |
1036 | } | 1075 | } |
1037 | } | 1076 | } |
@@ -1049,7 +1088,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e) | |||
1049 | } else { | 1088 | } else { |
1050 | k->attribute = EFI_MEMORY_UC; | 1089 | k->attribute = EFI_MEMORY_UC; |
1051 | k->start = lim; | 1090 | k->start = lim; |
1052 | k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT; | 1091 | k->num_pages = (efi_md_end(md) - lim) |
1092 | >> EFI_PAGE_SHIFT; | ||
1053 | k++; | 1093 | k++; |
1054 | } | 1094 | } |
1055 | } | 1095 | } |
@@ -1151,8 +1191,10 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
1151 | break; | 1191 | break; |
1152 | } | 1192 | } |
1153 | 1193 | ||
1154 | if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) { | 1194 | if ((res = kzalloc(sizeof(struct resource), |
1155 | printk(KERN_ERR "failed to alocate resource for iomem\n"); | 1195 | GFP_KERNEL)) == NULL) { |
1196 | printk(KERN_ERR | ||
1197 | "failed to allocate resource for iomem\n"); | ||
1156 | return; | 1198 | return; |
1157 | } | 1199 | } |
1158 | 1200 | ||
@@ -1187,44 +1229,44 @@ efi_initialize_iomem_resources(struct resource *code_resource, | |||
1187 | rsvd_regions are sorted | 1229 | rsvd_regions are sorted |
1188 | */ | 1230 | */ |
1189 | unsigned long __init | 1231 | unsigned long __init |
1190 | kdump_find_rsvd_region (unsigned long size, | 1232 | kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n) |
1191 | struct rsvd_region *r, int n) | ||
1192 | { | 1233 | { |
1193 | int i; | 1234 | int i; |
1194 | u64 start, end; | 1235 | u64 start, end; |
1195 | u64 alignment = 1UL << _PAGE_SIZE_64M; | 1236 | u64 alignment = 1UL << _PAGE_SIZE_64M; |
1196 | void *efi_map_start, *efi_map_end, *p; | 1237 | void *efi_map_start, *efi_map_end, *p; |
1197 | efi_memory_desc_t *md; | 1238 | efi_memory_desc_t *md; |
1198 | u64 efi_desc_size; | 1239 | u64 efi_desc_size; |
1199 | 1240 | ||
1200 | efi_map_start = __va(ia64_boot_param->efi_memmap); | 1241 | efi_map_start = __va(ia64_boot_param->efi_memmap); |
1201 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; | 1242 | efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; |
1202 | efi_desc_size = ia64_boot_param->efi_memdesc_size; | 1243 | efi_desc_size = ia64_boot_param->efi_memdesc_size; |
1203 | 1244 | ||
1204 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { | 1245 | for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { |
1205 | md = p; | 1246 | md = p; |
1206 | if (!efi_wb(md)) | 1247 | if (!efi_wb(md)) |
1207 | continue; | 1248 | continue; |
1208 | start = ALIGN(md->phys_addr, alignment); | 1249 | start = ALIGN(md->phys_addr, alignment); |
1209 | end = efi_md_end(md); | 1250 | end = efi_md_end(md); |
1210 | for (i = 0; i < n; i++) { | 1251 | for (i = 0; i < n; i++) { |
1211 | if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { | 1252 | if (__pa(r[i].start) >= start && __pa(r[i].end) < end) { |
1212 | if (__pa(r[i].start) > start + size) | 1253 | if (__pa(r[i].start) > start + size) |
1213 | return start; | 1254 | return start; |
1214 | start = ALIGN(__pa(r[i].end), alignment); | 1255 | start = ALIGN(__pa(r[i].end), alignment); |
1215 | if (i < n-1 && __pa(r[i+1].start) < start + size) | 1256 | if (i < n-1 && |
1216 | continue; | 1257 | __pa(r[i+1].start) < start + size) |
1217 | else | 1258 | continue; |
1218 | break; | 1259 | else |
1260 | break; | ||
1261 | } | ||
1219 | } | 1262 | } |
1220 | } | 1263 | if (end > start + size) |
1221 | if (end > start + size) | 1264 | return start; |
1222 | return start; | 1265 | } |
1223 | } | 1266 | |
1224 | 1267 | printk(KERN_WARNING | |
1225 | printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n", | 1268 | "Cannot reserve 0x%lx byte of memory for crashdump\n", size); |
1226 | size); | 1269 | return ~0UL; |
1227 | return ~0UL; | ||
1228 | } | 1270 | } |
1229 | #endif | 1271 | #endif |
1230 | 1272 | ||