]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/ia64/ia64/efi.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / ia64 / ia64 / efi.c
1 /*-
2  * Copyright (c) 2004 Marcel Moolenaar
3  * Copyright (c) 2001 Doug Rabson
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <machine/bootinfo.h>
34 #include <machine/efi.h>
35 #include <machine/sal.h>
36 #include <vm/vm.h>
37 #include <vm/pmap.h>
38
39 extern uint64_t ia64_call_efi_physical(uint64_t, uint64_t, uint64_t, uint64_t,
40     uint64_t, uint64_t);
41
42 static struct efi_systbl *efi_systbl;
43 static struct efi_cfgtbl *efi_cfgtbl;
44 static struct efi_rt *efi_runtime;
45
46 static int efi_status2err[25] = {
47         0,              /* EFI_SUCCESS */
48         ENOEXEC,        /* EFI_LOAD_ERROR */
49         EINVAL,         /* EFI_INVALID_PARAMETER */
50         ENOSYS,         /* EFI_UNSUPPORTED */
51         EMSGSIZE,       /* EFI_BAD_BUFFER_SIZE */
52         EOVERFLOW,      /* EFI_BUFFER_TOO_SMALL */
53         EBUSY,          /* EFI_NOT_READY */
54         EIO,            /* EFI_DEVICE_ERROR */
55         EROFS,          /* EFI_WRITE_PROTECTED */
56         EAGAIN,         /* EFI_OUT_OF_RESOURCES */
57         EIO,            /* EFI_VOLUME_CORRUPTED */
58         ENOSPC,         /* EFI_VOLUME_FULL */
59         ENXIO,          /* EFI_NO_MEDIA */
60         ESTALE,         /* EFI_MEDIA_CHANGED */
61         ENOENT,         /* EFI_NOT_FOUND */
62         EACCES,         /* EFI_ACCESS_DENIED */
63         ETIMEDOUT,      /* EFI_NO_RESPONSE */
64         EADDRNOTAVAIL,  /* EFI_NO_MAPPING */
65         ETIMEDOUT,      /* EFI_TIMEOUT */
66         EDOOFUS,        /* EFI_NOT_STARTED */
67         EALREADY,       /* EFI_ALREADY_STARTED */
68         ECANCELED,      /* EFI_ABORTED */
69         EPROTO,         /* EFI_ICMP_ERROR */
70         EPROTO,         /* EFI_TFTP_ERROR */
71         EPROTO          /* EFI_PROTOCOL_ERROR */
72 };
73
74 static int
75 efi_status_to_errno(efi_status status)
76 {
77         u_long code;
78         int error;
79
80         code = status & 0x3ffffffffffffffful;
81         error = (code < 25) ? efi_status2err[code] : EDOOFUS;
82         return (error);
83 }
84
85 void
86 efi_boot_finish(void)
87 {
88 }
89
90 /*
91  * Collect the entry points for PAL and SAL. Be extra careful about NULL
92  * pointer values. We're running pre-console, so it's better to return
93  * error values than to cause panics, machine checks and other traps and
94  * faults. Keep this minimal...
95  */
96 int
97 efi_boot_minimal(uint64_t systbl)
98 {
99         struct efi_md *md;
100         efi_status status;
101
102         if (systbl == 0)
103                 return (EINVAL);
104         efi_systbl = (struct efi_systbl *)IA64_PHYS_TO_RR7(systbl);
105         if (efi_systbl->st_hdr.th_sig != EFI_SYSTBL_SIG) {
106                 efi_systbl = NULL;
107                 return (EFAULT);
108         }
109         efi_cfgtbl = (efi_systbl->st_cfgtbl == 0) ? NULL :
110             (struct efi_cfgtbl *)IA64_PHYS_TO_RR7(efi_systbl->st_cfgtbl);
111         if (efi_cfgtbl == NULL)
112                 return (ENOENT);
113         efi_runtime = (efi_systbl->st_rt == 0) ? NULL :
114             (struct efi_rt *)IA64_PHYS_TO_RR7(efi_systbl->st_rt);
115         if (efi_runtime == NULL)
116                 return (ENOENT);
117
118         /*
119          * Relocate runtime memory segments for firmware.
120          */
121         md = efi_md_first();
122         while (md != NULL) {
123                 if (md->md_attr & EFI_MD_ATTR_RT) {
124                         if (md->md_attr & EFI_MD_ATTR_WB)
125                                 md->md_virt =
126                                     (void *)IA64_PHYS_TO_RR7(md->md_phys);
127                         else if (md->md_attr & EFI_MD_ATTR_UC)
128                                 md->md_virt = pmap_mapdev(md->md_phys,
129                                     md->md_pages * EFI_PAGE_SIZE);
130                 }
131                 md = efi_md_next(md);
132         }
133         status = ia64_call_efi_physical((uint64_t)efi_runtime->rt_setvirtual,
134             bootinfo.bi_memmap_size, bootinfo.bi_memdesc_size,
135             bootinfo.bi_memdesc_version, bootinfo.bi_memmap, 0);
136         return ((status < 0) ? EFAULT : 0);
137 }
138
139 void *
140 efi_get_table(struct uuid *uuid)
141 {
142         struct efi_cfgtbl *ct;
143         u_long count;
144
145         if (efi_cfgtbl == NULL)
146                 return (NULL);
147         count = efi_systbl->st_entries;
148         ct = efi_cfgtbl;
149         while (count--) {
150                 if (!bcmp(&ct->ct_uuid, uuid, sizeof(*uuid)))
151                         return ((void *)IA64_PHYS_TO_RR7(ct->ct_data));
152                 ct++;
153         }
154         return (NULL);
155 }
156
157 void
158 efi_get_time(struct efi_tm *tm)
159 {
160
161         efi_runtime->rt_gettime(tm, NULL);
162 }
163
164 struct efi_md *
165 efi_md_first(void)
166 {
167
168         if (bootinfo.bi_memmap == 0)
169                 return (NULL);
170         return ((struct efi_md *)IA64_PHYS_TO_RR7(bootinfo.bi_memmap));
171 }
172
173 struct efi_md *
174 efi_md_next(struct efi_md *md)
175 {
176         uint64_t plim;
177
178         plim = IA64_PHYS_TO_RR7(bootinfo.bi_memmap + bootinfo.bi_memmap_size);
179         md = (struct efi_md *)((uintptr_t)md + bootinfo.bi_memdesc_size);
180         return ((md >= (struct efi_md *)plim) ? NULL : md);
181 }
182
183 void
184 efi_reset_system(void)
185 {
186
187         if (efi_runtime != NULL)
188                 efi_runtime->rt_reset(EFI_RESET_WARM, 0, 0, NULL);
189         panic("%s: unable to reset the machine", __func__);
190 }
191
192 int
193 efi_set_time(struct efi_tm *tm)
194 {
195
196         return (efi_status_to_errno(efi_runtime->rt_settime(tm)));
197 }
198
199 int
200 efi_var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
201     size_t *datasize, void *data)
202 {
203         efi_status status;
204
205         status = efi_runtime->rt_getvar(name, vendor, attrib, datasize, data);
206         return (efi_status_to_errno(status));
207 }
208
209 int
210 efi_var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
211 {
212         efi_status status;
213
214         status = efi_runtime->rt_scanvar(namesize, name, vendor);
215         return (efi_status_to_errno(status));
216 }
217  
218 int
219 efi_var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
220     size_t datasize, void *data)
221 {
222         efi_status status;
223  
224         status = efi_runtime->rt_setvar(name, vendor, attrib, datasize, data);
225         return (efi_status_to_errno(status));
226 }