2 * Copyright (c) 2004 Marcel Moolenaar
3 * Copyright (c) 2001 Doug Rabson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <machine/bootinfo.h>
34 #include <machine/efi.h>
35 #include <machine/md_var.h>
36 #include <machine/sal.h>
40 static struct efi_systbl *efi_systbl;
41 static struct efi_cfgtbl *efi_cfgtbl;
42 static struct efi_rt *efi_runtime;
44 static int efi_status2err[25] = {
46 ENOEXEC, /* EFI_LOAD_ERROR */
47 EINVAL, /* EFI_INVALID_PARAMETER */
48 ENOSYS, /* EFI_UNSUPPORTED */
49 EMSGSIZE, /* EFI_BAD_BUFFER_SIZE */
50 EOVERFLOW, /* EFI_BUFFER_TOO_SMALL */
51 EBUSY, /* EFI_NOT_READY */
52 EIO, /* EFI_DEVICE_ERROR */
53 EROFS, /* EFI_WRITE_PROTECTED */
54 EAGAIN, /* EFI_OUT_OF_RESOURCES */
55 EIO, /* EFI_VOLUME_CORRUPTED */
56 ENOSPC, /* EFI_VOLUME_FULL */
57 ENXIO, /* EFI_NO_MEDIA */
58 ESTALE, /* EFI_MEDIA_CHANGED */
59 ENOENT, /* EFI_NOT_FOUND */
60 EACCES, /* EFI_ACCESS_DENIED */
61 ETIMEDOUT, /* EFI_NO_RESPONSE */
62 EADDRNOTAVAIL, /* EFI_NO_MAPPING */
63 ETIMEDOUT, /* EFI_TIMEOUT */
64 EDOOFUS, /* EFI_NOT_STARTED */
65 EALREADY, /* EFI_ALREADY_STARTED */
66 ECANCELED, /* EFI_ABORTED */
67 EPROTO, /* EFI_ICMP_ERROR */
68 EPROTO, /* EFI_TFTP_ERROR */
69 EPROTO /* EFI_PROTOCOL_ERROR */
73 efi_status_to_errno(efi_status status)
78 code = status & 0x3ffffffffffffffful;
79 error = (code < 25) ? efi_status2err[code] : EDOOFUS;
89 * Collect the entry points for PAL and SAL. Be extra careful about NULL
90 * pointer values. We're running pre-console, so it's better to return
91 * error values than to cause panics, machine checks and other traps and
92 * faults. Keep this minimal...
95 efi_boot_minimal(uint64_t systbl)
103 efi_systbl = (struct efi_systbl *)IA64_PHYS_TO_RR7(systbl);
104 if (efi_systbl->st_hdr.th_sig != EFI_SYSTBL_SIG) {
108 efi_cfgtbl = (efi_systbl->st_cfgtbl == 0) ? NULL :
109 (struct efi_cfgtbl *)IA64_PHYS_TO_RR7(efi_systbl->st_cfgtbl);
110 if (efi_cfgtbl == NULL)
112 efi_runtime = (efi_systbl->st_rt == 0) ? NULL :
113 (struct efi_rt *)IA64_PHYS_TO_RR7(efi_systbl->st_rt);
114 if (efi_runtime == NULL)
118 * Relocate runtime memory segments for firmware.
122 if (md->md_attr & EFI_MD_ATTR_RT) {
123 md->md_virt = (md->md_attr & EFI_MD_ATTR_WB) ?
124 (void *)IA64_PHYS_TO_RR7(md->md_phys) :
125 (void *)IA64_PHYS_TO_RR6(md->md_phys);
127 md = efi_md_next(md);
129 setvirt = (void *)IA64_PHYS_TO_RR7((u_long)efi_runtime->rt_setvirtual);
130 status = ia64_efi_physical(setvirt, bootinfo->bi_memmap_size,
131 bootinfo->bi_memdesc_size, bootinfo->bi_memdesc_version,
132 ia64_tpa(bootinfo->bi_memmap));
133 return ((status < 0) ? EFAULT : 0);
137 efi_get_table(struct uuid *uuid)
139 struct efi_cfgtbl *ct;
142 if (efi_cfgtbl == NULL)
144 count = efi_systbl->st_entries;
147 if (!bcmp(&ct->ct_uuid, uuid, sizeof(*uuid)))
148 return ((void *)IA64_PHYS_TO_RR7(ct->ct_data));
155 efi_get_time(struct efi_tm *tm)
158 efi_runtime->rt_gettime(tm, NULL);
166 if (bootinfo->bi_memmap == 0)
168 md = (struct efi_md *)bootinfo->bi_memmap;
177 if (bootinfo->bi_memmap == 0)
179 md = (struct efi_md *)(bootinfo->bi_memmap + bootinfo->bi_memmap_size -
180 bootinfo->bi_memdesc_size);
185 efi_md_next(struct efi_md *md)
190 md = (struct efi_md *)((uintptr_t)md + bootinfo->bi_memdesc_size);
191 return ((md > lim) ? NULL : md);
195 efi_md_prev(struct efi_md *md)
199 lim = efi_md_first();
200 md = (struct efi_md *)((uintptr_t)md - bootinfo->bi_memdesc_size);
201 return ((md < lim) ? NULL : md);
205 efi_md_find(vm_paddr_t pa)
207 static struct efi_md *last = NULL;
208 struct efi_md *md, *p0, *p1;
210 md = (last != NULL) ? last : efi_md_first();
212 while (md != NULL && md != p1) {
213 if (pa >= md->md_phys &&
214 pa < md->md_phys + md->md_pages * EFI_PAGE_SIZE) {
221 md = (pa < md->md_phys) ? efi_md_prev(md) : efi_md_next(md);
228 efi_reset_system(void)
231 if (efi_runtime != NULL)
232 efi_runtime->rt_reset(EFI_RESET_WARM, 0, 0, NULL);
233 panic("%s: unable to reset the machine", __func__);
237 efi_set_time(struct efi_tm *tm)
240 return (efi_status_to_errno(efi_runtime->rt_settime(tm)));
244 efi_var_get(efi_char *name, struct uuid *vendor, uint32_t *attrib,
245 size_t *datasize, void *data)
249 status = efi_runtime->rt_getvar(name, vendor, attrib, datasize, data);
250 return (efi_status_to_errno(status));
254 efi_var_nextname(size_t *namesize, efi_char *name, struct uuid *vendor)
258 status = efi_runtime->rt_scanvar(namesize, name, vendor);
259 return (efi_status_to_errno(status));
263 efi_var_set(efi_char *name, struct uuid *vendor, uint32_t attrib,
264 size_t datasize, void *data)
268 status = efi_runtime->rt_setvar(name, vendor, attrib, datasize, data);
269 return (efi_status_to_errno(status));