OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [ia64/] [kernel/] [efi.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Extensible Firmware Interface
3
 *
4
 * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999
5
 *
6
 * Copyright (C) 1999 VA Linux Systems
7
 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
8
 * Copyright (C) 1999-2003 Hewlett-Packard Co.
9
 *      David Mosberger-Tang <davidm@hpl.hp.com>
10
 *      Stephane Eranian <eranian@hpl.hp.com>
11
 *
12
 * All EFI Runtime Services are not implemented yet as EFI only
13
 * supports physical mode addressing on SoftSDV. This is to be fixed
14
 * in a future version.  --drummond 1999-07-20
15
 *
16
 * Implemented EFI runtime services and virtual mode calls.  --davidm
17
 *
18
 * Goutham Rao: <goutham.rao@intel.com>
19
 *      Skip non-WB memory and ignore empty memory ranges.
20
 */
21
#include <linux/config.h>
22
#include <linux/kernel.h>
23
#include <linux/init.h>
24
#include <linux/types.h>
25
#include <linux/time.h>
26
#include <linux/proc_fs.h>
27
#include <linux/efi.h>
28
 
29
#include <asm/io.h>
30
#include <asm/kregs.h>
31
#include <asm/pgtable.h>
32
#include <asm/processor.h>
33
#include <asm/mca.h>
34
 
35
#define EFI_DEBUG       0
36
 
37
extern efi_status_t efi_call_phys (void *, ...);
38
 
39
struct efi efi;
40
static efi_runtime_services_t *runtime;
41
 
42
/*
43
 * efi_dir is allocated here, but the directory isn't created
44
 * here, as proc_mkdir() doesn't work this early in the bootup
45
 * process.  Therefore, each module, like efivars, must test for
46
 *    if (!efi_dir)  efi_dir = proc_mkdir("efi", NULL);
47
 * prior to creating their own entries under /proc/efi.
48
 */
49
#ifdef CONFIG_PROC_FS
50
struct proc_dir_entry *efi_dir;
51
#endif
52
 
53
static unsigned long mem_limit = ~0UL;
54
 
55
#define efi_call_virt(f, args...)       (*(f))(args)
56
 
57
#define STUB_GET_TIME(prefix, adjust_arg)                                                       \
58
static efi_status_t                                                                             \
59
prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)                                          \
60
{                                                                                               \
61
        struct ia64_fpreg fr[6];                                                                \
62
        efi_status_t ret;                                                                       \
63
                                                                                                \
64
        ia64_save_scratch_fpregs(fr);                                                           \
65
        ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm),     \
66
                                adjust_arg(tc));                                                \
67
        ia64_load_scratch_fpregs(fr);                                                           \
68
        return ret;                                                                             \
69
}
70
 
71
#define STUB_SET_TIME(prefix, adjust_arg)                                                       \
72
static efi_status_t                                                                             \
73
prefix##_set_time (efi_time_t *tm)                                                              \
74
{                                                                                               \
75
        struct ia64_fpreg fr[6];                                                                \
76
        efi_status_t ret;                                                                       \
77
                                                                                                \
78
        ia64_save_scratch_fpregs(fr);                                                           \
79
        ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm));    \
80
        ia64_load_scratch_fpregs(fr);                                                           \
81
        return ret;                                                                             \
82
}
83
 
84
#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg)                                                \
85
static efi_status_t                                                                             \
86
prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm)             \
87
{                                                                                               \
88
        struct ia64_fpreg fr[6];                                                                \
89
        efi_status_t ret;                                                                       \
90
                                                                                                \
91
        ia64_save_scratch_fpregs(fr);                                                           \
92
        ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time),       \
93
                                adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm));      \
94
        ia64_load_scratch_fpregs(fr);                                                           \
95
        return ret;                                                                             \
96
}
97
 
98
#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg)                                                \
99
static efi_status_t                                                                             \
100
prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)                                   \
101
{                                                                                               \
102
        struct ia64_fpreg fr[6];                                                                \
103
        efi_status_t ret;                                                                       \
104
                                                                                                \
105
        ia64_save_scratch_fpregs(fr);                                                           \
106
        ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time),       \
107
                                enabled, adjust_arg(tm));                                       \
108
        ia64_load_scratch_fpregs(fr);                                                           \
109
        return ret;                                                                             \
110
}
111
 
112
#define STUB_GET_VARIABLE(prefix, adjust_arg)                                           \
113
static efi_status_t                                                                     \
114
prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,               \
115
                       unsigned long *data_size, void *data)                            \
116
{                                                                                       \
117
        struct ia64_fpreg fr[6];                                                        \
118
        efi_status_t ret;                                                               \
119
                                                                                        \
120
        ia64_save_scratch_fpregs(fr);                                                   \
121
        ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable),     \
122
                                adjust_arg(name), adjust_arg(vendor), adjust_arg(attr), \
123
                                adjust_arg(data_size), adjust_arg(data));               \
124
        ia64_load_scratch_fpregs(fr);                                                   \
125
        return ret;                                                                     \
126
}
127
 
128
#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg)                                              \
129
static efi_status_t                                                                             \
130
prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor)   \
131
{                                                                                               \
132
        struct ia64_fpreg fr[6];                                                                \
133
        efi_status_t ret;                                                                       \
134
                                                                                                \
135
        ia64_save_scratch_fpregs(fr);                                                           \
136
        ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable),   \
137
                                adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor));   \
138
        ia64_load_scratch_fpregs(fr);                                                           \
139
        return ret;                                                                             \
140
}
141
 
142
#define STUB_SET_VARIABLE(prefix, adjust_arg)                                           \
143
static efi_status_t                                                                     \
144
prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, u32 attr,                \
145
                       unsigned long data_size, void *data)                             \
146
{                                                                                       \
147
        struct ia64_fpreg fr[6];                                                        \
148
        efi_status_t ret;                                                               \
149
                                                                                        \
150
        ia64_save_scratch_fpregs(fr);                                                   \
151
        ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable),     \
152
                                adjust_arg(name), adjust_arg(vendor), attr, data_size,  \
153
                                adjust_arg(data));                                      \
154
        ia64_load_scratch_fpregs(fr);                                                   \
155
        return ret;                                                                     \
156
}
157
 
158
#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg)                                       \
159
static efi_status_t                                                                             \
160
prefix##_get_next_high_mono_count (u64 *count)                                                  \
161
{                                                                                               \
162
        struct ia64_fpreg fr[6];                                                                \
163
        efi_status_t ret;                                                                       \
164
                                                                                                \
165
        ia64_save_scratch_fpregs(fr);                                                           \
166
        ret = efi_call_##prefix((efi_get_next_high_mono_count_t *)                              \
167
                                __va(runtime->get_next_high_mono_count), adjust_arg(count));    \
168
        ia64_load_scratch_fpregs(fr);                                                           \
169
        return ret;                                                                             \
170
}
171
 
172
#define STUB_RESET_SYSTEM(prefix, adjust_arg)                                   \
173
static void                                                                     \
174
prefix##_reset_system (int reset_type, efi_status_t status,                     \
175
                       unsigned long data_size, efi_char16_t *data)             \
176
{                                                                               \
177
        struct ia64_fpreg fr[6];                                                \
178
                                                                                \
179
        ia64_save_scratch_fpregs(fr);                                           \
180
        efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system),   \
181
                          reset_type, status, data_size, adjust_arg(data));     \
182
        /* should not return, but just in case... */                            \
183
        ia64_load_scratch_fpregs(fr);                                           \
184
}
185
 
186
STUB_GET_TIME(phys, __pa)
187
STUB_SET_TIME(phys, __pa)
188
STUB_GET_WAKEUP_TIME(phys, __pa)
189
STUB_SET_WAKEUP_TIME(phys, __pa)
190
STUB_GET_VARIABLE(phys, __pa)
191
STUB_GET_NEXT_VARIABLE(phys, __pa)
192
STUB_SET_VARIABLE(phys, __pa)
193
STUB_GET_NEXT_HIGH_MONO_COUNT(phys, __pa)
194
STUB_RESET_SYSTEM(phys, __pa)
195
 
196
STUB_GET_TIME(virt, )
197
STUB_SET_TIME(virt, )
198
STUB_GET_WAKEUP_TIME(virt, )
199
STUB_SET_WAKEUP_TIME(virt, )
200
STUB_GET_VARIABLE(virt, )
201
STUB_GET_NEXT_VARIABLE(virt, )
202
STUB_SET_VARIABLE(virt, )
203
STUB_GET_NEXT_HIGH_MONO_COUNT(virt, )
204
STUB_RESET_SYSTEM(virt, )
205
 
206
void
207
efi_gettimeofday (struct timeval *tv)
208
{
209
        efi_time_t tm;
210
 
211
        memset(tv, 0, sizeof(tv));
212
        if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS)
213
                return;
214
 
215
        tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
216
        tv->tv_usec = tm.nanosecond / 1000;
217
}
218
 
219
static int
220
is_available_memory (efi_memory_desc_t *md)
221
{
222
        if (!(md->attribute & EFI_MEMORY_WB))
223
                return 0;
224
 
225
        switch (md->type) {
226
              case EFI_LOADER_CODE:
227
              case EFI_LOADER_DATA:
228
              case EFI_BOOT_SERVICES_CODE:
229
              case EFI_BOOT_SERVICES_DATA:
230
              case EFI_CONVENTIONAL_MEMORY:
231
                return 1;
232
        }
233
        return 0;
234
}
235
 
236
/*
237
 * Trim descriptor MD so its starts at address START_ADDR.  If the descriptor covers
238
 * memory that is normally available to the kernel, issue a warning that some memory
239
 * is being ignored.
240
 */
241
static void
242
trim_bottom (efi_memory_desc_t *md, u64 start_addr)
243
{
244
        u64 num_skipped_pages;
245
 
246
        if (md->phys_addr >= start_addr || !md->num_pages)
247
                return;
248
 
249
        num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
250
        if (num_skipped_pages > md->num_pages)
251
                num_skipped_pages = md->num_pages;
252
 
253
        if (is_available_memory(md))
254
                printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
255
                       "at 0x%lx\n", __FUNCTION__,
256
                       (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
257
                       md->phys_addr, start_addr - IA64_GRANULE_SIZE);
258
        /*
259
         * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
260
         * descriptor list to become unsorted.  In such a case, md->num_pages will be
261
         * zero, so the Right Thing will happen.
262
         */
263
        md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
264
        md->num_pages -= num_skipped_pages;
265
}
266
 
267
static void
268
trim_top (efi_memory_desc_t *md, u64 end_addr)
269
{
270
        u64 num_dropped_pages, md_end_addr;
271
 
272
        md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
273
 
274
        if (md_end_addr <= end_addr || !md->num_pages)
275
                return;
276
 
277
        num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT;
278
        if (num_dropped_pages > md->num_pages)
279
                num_dropped_pages = md->num_pages;
280
 
281
        if (is_available_memory(md))
282
                printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
283
                       "at 0x%lx\n", __FUNCTION__,
284
                       (num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
285
                       md->phys_addr, end_addr);
286
        md->num_pages -= num_dropped_pages;
287
}
288
 
289
/*
290
 * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
291
 * has memory that is available for OS use.
292
 */
293
void
294
efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
295
{
296
        int prev_valid = 0;
297
        struct range {
298
                u64 start;
299
                u64 end;
300
        } prev, curr;
301
        void *efi_map_start, *efi_map_end, *p, *q;
302
        efi_memory_desc_t *md, *check_md;
303
        u64 efi_desc_size, start, end, granule_addr, last_granule_addr, first_non_wb_addr = 0;
304
 
305
        efi_map_start = __va(ia64_boot_param->efi_memmap);
306
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
307
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
308
 
309
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
310
                md = p;
311
 
312
                /* skip over non-WB memory descriptors; that's all we're interested in... */
313
                if (!(md->attribute & EFI_MEMORY_WB))
314
                        continue;
315
 
316
                /*
317
                 * granule_addr is the base of md's first granule.
318
                 * [granule_addr - first_non_wb_addr) is guaranteed to
319
                 * be contiguous WB memory.
320
                 */
321
                granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1);
322
                first_non_wb_addr = max(first_non_wb_addr, granule_addr);
323
 
324
                if (first_non_wb_addr < md->phys_addr) {
325
                        trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
326
                        granule_addr = md->phys_addr & ~(IA64_GRANULE_SIZE - 1);
327
                        first_non_wb_addr = max(first_non_wb_addr, granule_addr);
328
                }
329
 
330
                for (q = p; q < efi_map_end; q += efi_desc_size) {
331
                        check_md = q;
332
 
333
                        if ((check_md->attribute & EFI_MEMORY_WB) &&
334
                            (check_md->phys_addr == first_non_wb_addr))
335
                                first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
336
                        else
337
                                break;          /* non-WB or hole */
338
                }
339
 
340
                last_granule_addr = first_non_wb_addr & ~(IA64_GRANULE_SIZE - 1);
341
                if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT))
342
                        trim_top(md, last_granule_addr);
343
 
344
                if (is_available_memory(md)) {
345
                        if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
346
                                if (md->phys_addr > mem_limit)
347
                                        continue;
348
                                md->num_pages = (mem_limit - md->phys_addr) >> EFI_PAGE_SHIFT;
349
                        }
350
 
351
                        if (md->num_pages == 0)
352
                                continue;
353
 
354
                        curr.start = PAGE_OFFSET + md->phys_addr;
355
                        curr.end   = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
356
 
357
                        if (!prev_valid) {
358
                                prev = curr;
359
                                prev_valid = 1;
360
                        } else {
361
                                if (curr.start < prev.start)
362
                                        printk(KERN_ERR "Oops: EFI memory table not ordered!\n");
363
 
364
                                if (prev.end == curr.start) {
365
                                        /* merge two consecutive memory ranges */
366
                                        prev.end = curr.end;
367
                                } else {
368
                                        start = PAGE_ALIGN(prev.start);
369
                                        end = prev.end & PAGE_MASK;
370
                                        if ((end > start) && (*callback)(start, end, arg) < 0)
371
                                                return;
372
                                        prev = curr;
373
                                }
374
                        }
375
                }
376
        }
377
        if (prev_valid) {
378
                start = PAGE_ALIGN(prev.start);
379
                end = prev.end & PAGE_MASK;
380
                if (end > start)
381
                        (*callback)(start, end, arg);
382
        }
383
}
384
 
385
/*
386
 * Look for the PAL_CODE region reported by EFI and maps it using an
387
 * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
388
 * Abstraction Layer chapter 11 in ADAG
389
 */
390
void
391
efi_map_pal_code (void)
392
{
393
        void *efi_map_start, *efi_map_end, *p;
394
        efi_memory_desc_t *md;
395
        u64 efi_desc_size;
396
        int pal_code_count = 0;
397
        u64 mask, psr;
398
        u64 vaddr;
399
#ifdef CONFIG_IA64_MCA
400
        int cpu;
401
#endif
402
 
403
        efi_map_start = __va(ia64_boot_param->efi_memmap);
404
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
405
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
406
 
407
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
408
                md = p;
409
                if (md->type != EFI_PAL_CODE)
410
                        continue;
411
 
412
                if (++pal_code_count > 1) {
413
                        printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n",
414
                               md->phys_addr);
415
                        continue;
416
                }
417
                /*
418
                 * The only ITLB entry in region 7 that is used is the one installed by
419
                 * __start().  That entry covers a 64MB range.
420
                 */
421
                mask  = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
422
                vaddr = PAGE_OFFSET + md->phys_addr;
423
 
424
                /*
425
                 * We must check that the PAL mapping won't overlap with the kernel
426
                 * mapping.
427
                 *
428
                 * PAL code is guaranteed to be aligned on a power of 2 between 4k and
429
                 * 256KB and that only one ITR is needed to map it. This implies that the
430
                 * PAL code is always aligned on its size, i.e., the closest matching page
431
                 * size supported by the TLB. Therefore PAL code is guaranteed never to
432
                 * cross a 64MB unless it is bigger than 64MB (very unlikely!).  So for
433
                 * now the following test is enough to determine whether or not we need a
434
                 * dedicated ITR for the PAL code.
435
                 */
436
                if ((vaddr & mask) == (KERNEL_START & mask)) {
437
                        printk(KERN_INFO "%s: no need to install ITR for PAL code\n",
438
                               __FUNCTION__);
439
                        continue;
440
                }
441
 
442
                if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE)
443
                        panic("Woah!  PAL code size bigger than a granule!");
444
 
445
                mask  = ~((1 << IA64_GRANULE_SHIFT) - 1);
446
#if EFI_DEBUG
447
                printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
448
                       smp_processor_id(), md->phys_addr,
449
                       md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
450
                       vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
451
#endif
452
 
453
                /*
454
                 * Cannot write to CRx with PSR.ic=1
455
                 */
456
                psr = ia64_clear_ic();
457
                ia64_itr(0x1, IA64_TR_PALCODE, vaddr & mask,
458
                         pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL)), IA64_GRANULE_SHIFT);
459
                ia64_set_psr(psr);              /* restore psr */
460
                ia64_srlz_i();
461
 
462
#ifdef CONFIG_IA64_MCA
463
                cpu = smp_processor_id();
464
 
465
                /* insert this TR into our list for MCA recovery purposes */
466
                ia64_mca_tlb_list[cpu].pal_base=vaddr & mask;
467
                ia64_mca_tlb_list[cpu].pal_paddr= pte_val(mk_pte_phys(md->phys_addr, PAGE_KERNEL));
468
#endif
469
        }
470
}
471
 
472
void __init
473
efi_init (void)
474
{
475
        void *efi_map_start, *efi_map_end;
476
        efi_config_table_t *config_tables;
477
        efi_char16_t *c16;
478
        u64 efi_desc_size;
479
        char *cp, *end, vendor[100] = "unknown";
480
        extern char saved_command_line[];
481
        int i;
482
 
483
        /* it's too early to be able to use the standard kernel command line support... */
484
        for (cp = saved_command_line; *cp; ) {
485
                if (memcmp(cp, "mem=", 4) == 0) {
486
                        cp += 4;
487
                        mem_limit = memparse(cp, &end) - 1;
488
                        if (end != cp)
489
                                break;
490
                        cp = end;
491
                } else {
492
                        while (*cp != ' ' && *cp)
493
                                ++cp;
494
                        while (*cp == ' ')
495
                                ++cp;
496
                }
497
        }
498
        if (mem_limit != ~0UL)
499
                printk(KERN_INFO "Ignoring memory above %luMB\n", mem_limit >> 20);
500
 
501
        efi.systab = __va(ia64_boot_param->efi_systab);
502
 
503
        /*
504
         * Verify the EFI Table
505
         */
506
        if (efi.systab == NULL)
507
                panic("Woah! Can't find EFI system table.\n");
508
        if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
509
                panic("Woah! EFI system table signature incorrect\n");
510
        if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
511
                printk(KERN_WARNING "Warning: EFI system table major version mismatch: "
512
                       "got %d.%02d, expected %d.%02d\n",
513
                       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff,
514
                       EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff);
515
 
516
        config_tables = __va(efi.systab->tables);
517
 
518
        /* Show what we know for posterity */
519
        c16 = __va(efi.systab->fw_vendor);
520
        if (c16) {
521
                for (i = 0;i < sizeof(vendor) && *c16; ++i)
522
                        vendor[i] = *c16++;
523
                vendor[i] = '\0';
524
        }
525
 
526
        printk(KERN_INFO "EFI v%u.%.02u by %s:",
527
               efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
528
 
529
        for (i = 0; i < efi.systab->nr_tables; i++) {
530
                if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) {
531
                        efi.mps = __va(config_tables[i].table);
532
                        printk(" MPS=0x%lx", config_tables[i].table);
533
                } else if (efi_guidcmp(config_tables[i].guid, ACPI_20_TABLE_GUID) == 0) {
534
                        efi.acpi20 = __va(config_tables[i].table);
535
                        printk(" ACPI 2.0=0x%lx", config_tables[i].table);
536
                } else if (efi_guidcmp(config_tables[i].guid, ACPI_TABLE_GUID) == 0) {
537
                        efi.acpi = __va(config_tables[i].table);
538
                        printk(" ACPI=0x%lx", config_tables[i].table);
539
                } else if (efi_guidcmp(config_tables[i].guid, SMBIOS_TABLE_GUID) == 0) {
540
                        efi.smbios = __va(config_tables[i].table);
541
                        printk(" SMBIOS=0x%lx", config_tables[i].table);
542
                } else if (efi_guidcmp(config_tables[i].guid, SAL_SYSTEM_TABLE_GUID) == 0) {
543
                        efi.sal_systab = __va(config_tables[i].table);
544
                        printk(" SALsystab=0x%lx", config_tables[i].table);
545
                } else if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
546
                        efi.hcdp = __va(config_tables[i].table);
547
                        printk(" HCDP=0x%lx", config_tables[i].table);
548
                }
549
        }
550
        printk("\n");
551
 
552
        runtime = __va(efi.systab->runtime);
553
        efi.get_time = phys_get_time;
554
        efi.set_time = phys_set_time;
555
        efi.get_wakeup_time = phys_get_wakeup_time;
556
        efi.set_wakeup_time = phys_set_wakeup_time;
557
        efi.get_variable = phys_get_variable;
558
        efi.get_next_variable = phys_get_next_variable;
559
        efi.set_variable = phys_set_variable;
560
        efi.get_next_high_mono_count = phys_get_next_high_mono_count;
561
        efi.reset_system = phys_reset_system;
562
 
563
        efi_map_start = __va(ia64_boot_param->efi_memmap);
564
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
565
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
566
 
567
#if EFI_DEBUG
568
        /* print EFI memory map: */
569
        {
570
                efi_memory_desc_t *md;
571
                void *p;
572
 
573
                for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
574
                        md = p;
575
                        printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
576
                               i, md->type, md->attribute, md->phys_addr,
577
                               md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
578
                               md->num_pages >> (20 - EFI_PAGE_SHIFT));
579
                }
580
        }
581
#endif
582
 
583
        efi_map_pal_code();
584
        efi_enter_virtual_mode();
585
}
586
 
587
void
588
efi_enter_virtual_mode (void)
589
{
590
        void *efi_map_start, *efi_map_end, *p;
591
        efi_memory_desc_t *md;
592
        efi_status_t status;
593
        u64 efi_desc_size;
594
 
595
        efi_map_start = __va(ia64_boot_param->efi_memmap);
596
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
597
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
598
 
599
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
600
                md = p;
601
                if (md->attribute & EFI_MEMORY_RUNTIME) {
602
                        /*
603
                         * Some descriptors have multiple bits set, so the order of
604
                         * the tests is relevant.
605
                         */
606
                        if (md->attribute & EFI_MEMORY_WB) {
607
                                md->virt_addr = (u64) __va(md->phys_addr);
608
                        } else if (md->attribute & EFI_MEMORY_UC) {
609
                                md->virt_addr = (u64) ioremap(md->phys_addr, 0);
610
                        } else if (md->attribute & EFI_MEMORY_WC) {
611
#if 0
612
                                md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
613
                                                                           | _PAGE_D
614
                                                                           | _PAGE_MA_WC
615
                                                                           | _PAGE_PL_0
616
                                                                           | _PAGE_AR_RW));
617
#else
618
                                printk(KERN_INFO "EFI_MEMORY_WC mapping\n");
619
                                md->virt_addr = (u64) ioremap(md->phys_addr, 0);
620
#endif
621
                        } else if (md->attribute & EFI_MEMORY_WT) {
622
#if 0
623
                                md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
624
                                                                           | _PAGE_D | _PAGE_MA_WT
625
                                                                           | _PAGE_PL_0
626
                                                                           | _PAGE_AR_RW));
627
#else
628
                                printk(KERN_INFO "EFI_MEMORY_WT mapping\n");
629
                                md->virt_addr = (u64) ioremap(md->phys_addr, 0);
630
#endif
631
                        }
632
                }
633
        }
634
 
635
        status = efi_call_phys(__va(runtime->set_virtual_address_map),
636
                               ia64_boot_param->efi_memmap_size,
637
                               efi_desc_size, ia64_boot_param->efi_memdesc_version,
638
                               ia64_boot_param->efi_memmap);
639
        if (status != EFI_SUCCESS) {
640
                printk(KERN_WARNING "warning: unable to switch EFI into virtual mode (status=0x%lx)\n", status);
641
                return;
642
        }
643
 
644
        /*
645
         * Now that EFI is in virtual mode, we call the EFI functions more efficiently:
646
         */
647
        efi.get_time = virt_get_time;
648
        efi.set_time = virt_set_time;
649
        efi.get_wakeup_time = virt_get_wakeup_time;
650
        efi.set_wakeup_time = virt_set_wakeup_time;
651
        efi.get_variable = virt_get_variable;
652
        efi.get_next_variable = virt_get_next_variable;
653
        efi.set_variable = virt_set_variable;
654
        efi.get_next_high_mono_count = virt_get_next_high_mono_count;
655
        efi.reset_system = virt_reset_system;
656
}
657
 
658
/*
659
 * Walk the EFI memory map looking for the I/O port range.  There can only be one entry of
660
 * this type, other I/O port ranges should be described via ACPI.
661
 */
662
u64
663
efi_get_iobase (void)
664
{
665
        void *efi_map_start, *efi_map_end, *p;
666
        efi_memory_desc_t *md;
667
        u64 efi_desc_size;
668
 
669
        efi_map_start = __va(ia64_boot_param->efi_memmap);
670
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
671
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
672
 
673
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
674
                md = p;
675
                if (md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) {
676
                        /* paranoia attribute checking */
677
                        if (md->attribute == (EFI_MEMORY_UC | EFI_MEMORY_RUNTIME))
678
                                return md->phys_addr;
679
                }
680
        }
681
        return 0;
682
}
683
 
684
u32
685
efi_mem_type (unsigned long phys_addr)
686
{
687
        void *efi_map_start, *efi_map_end, *p;
688
        efi_memory_desc_t *md;
689
        u64 efi_desc_size;
690
 
691
        efi_map_start = __va(ia64_boot_param->efi_memmap);
692
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
693
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
694
 
695
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
696
                md = p;
697
 
698
                if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
699
                         return md->type;
700
        }
701
        return 0;
702
}
703
 
704
u64
705
efi_mem_attributes (unsigned long phys_addr)
706
{
707
        void *efi_map_start, *efi_map_end, *p;
708
        efi_memory_desc_t *md;
709
        u64 efi_desc_size;
710
 
711
        efi_map_start = __va(ia64_boot_param->efi_memmap);
712
        efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
713
        efi_desc_size = ia64_boot_param->efi_memdesc_size;
714
 
715
        for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
716
                md = p;
717
 
718
                if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
719
                        return md->attribute;
720
        }
721
        return 0;
722
}
723
 
724
static void __exit
725
efivars_exit (void)
726
{
727
#ifdef CONFIG_PROC_FS
728
        remove_proc_entry(efi_dir->name, NULL);
729
#endif
730
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.