1/*	$NetBSD: efi.c,v 1.1 2006/04/07 14:21:18 cherry 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
40extern uint64_t ia64_call_efi_physical(uint64_t, uint64_t, uint64_t, uint64_t,
41    uint64_t, uint64_t);
42
43static struct efi_systbl *efi_systbl;
44static struct efi_cfgtbl *efi_cfgtbl;
45static struct efi_rt *efi_runtime;
46
47void
48efi_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 */
58int
59efi_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 == 0) ? NULL :
72	    (struct efi_cfgtbl *)IA64_PHYS_TO_RR7(efi_systbl->st_cfgtbl);
73	if (efi_cfgtbl == NULL)
74		return (ENOENT);
75	efi_runtime = (efi_systbl->st_rt == 0) ? NULL :
76	    (struct efi_rt *)IA64_PHYS_TO_RR7(efi_systbl->st_rt);
77	if (efi_runtime == NULL)
78		return (ENOENT);
79
80	/*
81	 * Relocate runtime memory segments for firmware.
82	 */
83	md = efi_md_first();
84	while (md != NULL) {
85		if (md->md_attr & EFI_MD_ATTR_RT) {
86			if (md->md_attr & EFI_MD_ATTR_WB)
87				md->md_virt =
88				    (void *)IA64_PHYS_TO_RR7(md->md_phys);
89			else if (md->md_attr & EFI_MD_ATTR_UC)
90				md->md_virt =
91				    (void *)IA64_PHYS_TO_RR6(md->md_phys);
92		}
93		md = efi_md_next(md);
94	}
95	status = ia64_call_efi_physical((uint64_t)efi_runtime->rt_setvirtual,
96	    bootinfo.bi_memmap_size, bootinfo.bi_memdesc_size,
97	    bootinfo.bi_memdesc_version, bootinfo.bi_memmap, 0);
98	return ((status < 0) ? EFAULT : 0);
99}
100
101void *
102efi_get_table(struct uuid *uuid)
103{
104	struct efi_cfgtbl *ct;
105	u_long count;
106
107	if (efi_cfgtbl == NULL)
108		return (NULL);
109	count = efi_systbl->st_entries;
110	ct = efi_cfgtbl;
111	while (count--) {
112		if (!memcmp(&ct->ct_uuid, uuid, sizeof(*uuid)))
113			return ((void *)IA64_PHYS_TO_RR7(ct->ct_data));
114		ct++;
115	}
116	return (NULL);
117}
118
119void
120efi_get_time(struct efi_tm *tm)
121{
122
123	efi_runtime->rt_gettime(tm, NULL);
124}
125
126struct efi_md *
127efi_md_first(void)
128{
129
130	if (bootinfo.bi_memmap == 0)
131		return (NULL);
132	return ((struct efi_md *)IA64_PHYS_TO_RR7(bootinfo.bi_memmap));
133}
134
135struct efi_md *
136efi_md_next(struct efi_md *md)
137{
138	uint64_t plim;
139
140	plim = IA64_PHYS_TO_RR7(bootinfo.bi_memmap + bootinfo.bi_memmap_size);
141	md = (struct efi_md *)((uintptr_t)md + bootinfo.bi_memdesc_size);
142	return ((md >= (struct efi_md *)plim) ? NULL : md);
143}
144
145void
146efi_reset_system(void)
147{
148
149	if (efi_runtime != NULL)
150		efi_runtime->rt_reset(EFI_RESET_WARM, 0, 0, NULL);
151	panic("%s: unable to reset the machine", __func__);
152}
153
154efi_status
155efi_set_time(struct efi_tm *tm)
156{
157
158	return (efi_runtime->rt_settime(tm));
159}
160