1 /* $NetBSD: efi.c,v 1.5 2022/08/20 10:55:03 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2004 Marcel Moolenaar
5 * Copyright (c) 2001 Doug Rabson
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/lock.h>
34
35 #include <machine/bootinfo.h>
36 #include <machine/efi.h>
37 #include <machine/sal.h>
38 #include <machine/vmparam.h>
39
40 extern uint64_t ia64_call_efi_physical(uint64_t, uint64_t, uint64_t, uint64_t,
41 uint64_t, uint64_t);
42
43 static struct efi_systbl *efi_systbl;
44 static struct efi_cfgtbl *efi_cfgtbl;
45 static struct efi_rt *efi_runtime;
46
47 void
efi_boot_finish(void)48 efi_boot_finish(void)
49 {
50 }
51
52 /*
53 * Collect the entry points for PAL and SAL. Be extra careful about NULL
54 * pointer values. We're running pre-console, so it's better to return
55 * error values than to cause panics, machine checks and other traps and
56 * faults. Keep this minimal...
57 */
58 int
efi_boot_minimal(uint64_t systbl)59 efi_boot_minimal(uint64_t systbl)
60 {
61 struct efi_md *md;
62 efi_status status;
63
64 if (systbl == 0)
65 return (EINVAL);
66 efi_systbl = (struct efi_systbl *)IA64_PHYS_TO_RR7(systbl);
67 if (efi_systbl->st_hdr.th_sig != EFI_SYSTBL_SIG) {
68 efi_systbl = NULL;
69 return (EFAULT);
70 }
71 efi_cfgtbl = (efi_systbl->st_cfgtbl == NULL) ? NULL :
72 (struct efi_cfgtbl *)IA64_PHYS_TO_RR7(
73 (uint64_t)efi_systbl->st_cfgtbl);
74 if (efi_cfgtbl == NULL)
75 return (ENOENT);
76 efi_runtime = (efi_systbl->st_rt == NULL) ? NULL :
77 (struct efi_rt *)IA64_PHYS_TO_RR7((uint64_t)efi_systbl->st_rt);
78 if (efi_runtime == NULL)
79 return (ENOENT);
80
81 /*
82 * Relocate runtime memory segments for firmware.
83 */
84 md = efi_md_first();
85 while (md != NULL) {
86 if (md->md_attr & EFI_MD_ATTR_RT) {
87 if (md->md_attr & EFI_MD_ATTR_WB)
88 md->md_virt =
89 (uint64_t)IA64_PHYS_TO_RR7(md->md_phys);
90 else if (md->md_attr & EFI_MD_ATTR_UC)
91 md->md_virt =
92 (uint64_t)IA64_PHYS_TO_RR6(md->md_phys);
93 }
94 md = efi_md_next(md);
95 }
96 status = ia64_call_efi_physical((uint64_t)efi_runtime->rt_setvirtual,
97 bootinfo.bi_memmap_size, bootinfo.bi_memdesc_size,
98 bootinfo.bi_memdesc_version, bootinfo.bi_memmap, 0);
99 return ((status < 0) ? EFAULT : 0);
100 }
101
102 void *
efi_get_table(struct uuid * uuid)103 efi_get_table(struct uuid *uuid)
104 {
105 struct efi_cfgtbl *ct;
106 u_long count;
107
108 if (efi_cfgtbl == NULL)
109 return (NULL);
110 count = efi_systbl->st_entries;
111 ct = efi_cfgtbl;
112 while (count--) {
113 if (!memcmp(&ct->ct_uuid, uuid, sizeof(*uuid))) {
114 uint64_t data_pa = (uint64_t)(uintptr_t)ct->ct_data;
115 return ((void *)IA64_PHYS_TO_RR7(data_pa));
116 }
117 ct++;
118 }
119 return (NULL);
120 }
121
122 void
efi_get_time(struct efi_tm * tm)123 efi_get_time(struct efi_tm *tm)
124 {
125
126 efi_runtime->rt_gettime(tm, NULL);
127 }
128
129 struct efi_md *
efi_md_first(void)130 efi_md_first(void)
131 {
132
133 if (bootinfo.bi_memmap == 0)
134 return (NULL);
135 return ((struct efi_md *)IA64_PHYS_TO_RR7(bootinfo.bi_memmap));
136 }
137
138 struct efi_md *
efi_md_next(struct efi_md * md)139 efi_md_next(struct efi_md *md)
140 {
141 uint64_t plim;
142
143 plim = IA64_PHYS_TO_RR7(bootinfo.bi_memmap + bootinfo.bi_memmap_size);
144 md = (struct efi_md *)((uintptr_t)md + bootinfo.bi_memdesc_size);
145 return ((md >= (struct efi_md *)plim) ? NULL : md);
146 }
147
148 void
efi_reset_system(void)149 efi_reset_system(void)
150 {
151
152 if (efi_runtime != NULL)
153 efi_runtime->rt_reset(EFI_RESET_WARM, 0, 0, NULL);
154 panic("%s: unable to reset the machine", __func__);
155 }
156
157 efi_status
efi_set_time(struct efi_tm * tm)158 efi_set_time(struct efi_tm *tm)
159 {
160
161 return (efi_runtime->rt_settime(tm));
162 }
163