main.c revision 83857
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * Copyright (c) 1998,2000 Doug Rabson <dfr@freebsd.org>
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#ifndef lint
29static const char rcsid[] =
30  "$FreeBSD: head/sys/boot/ia64/efi/main.c 83857 2001-09-23 10:28:01Z dfr $";
31#endif /* not lint */
32
33#include <stand.h>
34#include <string.h>
35#include <setjmp.h>
36#include <machine/sal.h>
37
38#include <efi.h>
39#include <efilib.h>
40
41#include "bootstrap.h"
42#include "efiboot.h"
43
44extern char bootprog_name[];
45extern char bootprog_rev[];
46extern char bootprog_date[];
47extern char bootprog_maker[];
48
49struct efi_devdesc	currdev;	/* our current device */
50struct arch_switch	archsw;		/* MI/MD interface boundary */
51
52EFI_STATUS
53efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
54{
55	int i;
56	EFI_PHYSICAL_ADDRESS mem;
57
58	efi_init(image_handle, system_table);
59
60	/*
61	 * Initialise the heap as early as possible.  Once this is done,
62	 * alloc() is usable. The stack is buried inside us, so this is
63	 * safe.
64	 */
65	BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
66			  512*1024/4096, &mem);
67	setheap((void *)mem, (void *)(mem + 512*1024));
68
69	/*
70	 * XXX Chicken-and-egg problem; we want to have console output
71	 * early, but some console attributes may depend on reading from
72	 * eg. the boot device, which we can't do yet.  We can use
73	 * printf() etc. once this is done.
74	 */
75	cons_probe();
76
77	/*
78	 * Initialise the block cache
79	 */
80	bcache_init(32, 512);		/* 16k XXX tune this */
81
82	/*
83	 * March through the device switch probing for things.
84	 */
85	for (i = 0; devsw[i] != NULL; i++)
86		if (devsw[i]->dv_init != NULL)
87			(devsw[i]->dv_init)();
88
89	efinet_init_driver();
90
91	printf("\n");
92	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
93	printf("(%s, %s)\n", bootprog_maker, bootprog_date);
94#if 0
95	printf("Memory: %ld k\n", memsize() / 1024);
96#endif
97
98	/* XXX presumes that biosdisk is first in devsw */
99	currdev.d_dev = devsw[0];
100	currdev.d_type = currdev.d_dev->dv_type;
101	currdev.d_kind.efidisk.unit = 0;
102	/* XXX should be able to detect this, default to autoprobe */
103	currdev.d_kind.efidisk.slice = -1;
104	/* default to 'a' */
105	currdev.d_kind.efidisk.partition = 0;
106
107#if 0
108	/* Create arc-specific variables */
109	bootfile = GetEnvironmentVariable(ARCENV_BOOTFILE);
110	if (bootfile)
111		setenv("bootfile", bootfile, 1);
112#endif
113
114	env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
115	    efi_setcurrdev, env_nounset);
116	env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
117	    env_nounset);
118
119	setenv("LINES", "24", 1);	/* optional */
120
121	archsw.arch_autoload = efi_autoload;
122	archsw.arch_getdev = efi_getdev;
123	archsw.arch_copyin = efi_copyin;
124	archsw.arch_copyout = efi_copyout;
125	archsw.arch_readin = efi_readin;
126
127	interact();			/* doesn't return */
128
129	return (EFI_SUCCESS);		/* keep compiler happy */
130}
131
132COMMAND_SET(quit, "quit", "exit the loader", command_quit);
133
134static int
135command_quit(int argc, char *argv[])
136{
137	exit(0);
138	return (CMD_OK);
139}
140
141COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
142
143static int
144command_memmap(int argc, char *argv[])
145{
146	UINTN sz;
147	EFI_MEMORY_DESCRIPTOR *map, *p;
148	UINTN key, dsz;
149	UINT32 dver;
150	EFI_STATUS status;
151	int i, ndesc;
152	static char *types[] = {
153	    "Reserved",
154	    "LoaderCode",
155	    "LoaderData",
156	    "BootServicesCode",
157	    "BootServicesData",
158	    "RuntimeServicesCode",
159	    "RuntimeServicesData",
160	    "ConventionalMemory",
161	    "UnusableMemory",
162	    "ACPIReclaimMemory",
163	    "ACPIMemoryNVS",
164	    "MemoryMappedIO",
165	    "MemoryMappedIOPortSpace",
166	    "PalCode"
167	};
168
169	sz = 0;
170	status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
171	if (status != EFI_BUFFER_TOO_SMALL) {
172		printf("Can't determine memory map size\n");
173		return CMD_ERROR;
174	}
175	map = malloc(sz);
176	status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
177	if (EFI_ERROR(status)) {
178		printf("Can't read memory map\n");
179		return CMD_ERROR;
180	}
181
182	ndesc = sz / dsz;
183	printf("%23s %12s %12s %8s %4s\n",
184	       "Type", "Physical", "Virtual", "#Pages", "Attr");
185
186	for (i = 0, p = map; i < ndesc;
187	     i++, p = NextMemoryDescriptor(p, dsz)) {
188	    printf("%23s %012lx %012lx %08lx ",
189		   types[p->Type],
190		   p->PhysicalStart,
191		   p->VirtualStart,
192		   p->NumberOfPages);
193	    if (p->Attribute & EFI_MEMORY_UC)
194		printf("UC ");
195	    if (p->Attribute & EFI_MEMORY_WC)
196		printf("WC ");
197	    if (p->Attribute & EFI_MEMORY_WT)
198		printf("WT ");
199	    if (p->Attribute & EFI_MEMORY_WB)
200		printf("WB ");
201	    if (p->Attribute & EFI_MEMORY_UCE)
202		printf("UCE ");
203	    if (p->Attribute & EFI_MEMORY_WP)
204		printf("WP ");
205	    if (p->Attribute & EFI_MEMORY_RP)
206		printf("RP ");
207	    if (p->Attribute & EFI_MEMORY_XP)
208		printf("XP ");
209	    if (p->Attribute & EFI_MEMORY_RUNTIME)
210		printf("RUNTIME");
211	    printf("\n");
212	}
213
214	return CMD_OK;
215}
216
217COMMAND_SET(configuration, "configuration",
218	    "print configuration tables", command_configuration);
219
220static int
221command_configuration(int argc, char *argv[])
222{
223	int i;
224
225	printf("NumberOfTableEntries=%d\n", ST->NumberOfTableEntries);
226	for (i = 0; i < ST->NumberOfTableEntries; i++) {
227		static EFI_GUID mps = MPS_TABLE_GUID;
228		static EFI_GUID acpi = ACPI_TABLE_GUID;
229		static EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
230		static EFI_GUID smbios = SMBIOS_TABLE_GUID;
231		static EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
232
233		printf("  ");
234		if (!memcmp(&ST->ConfigurationTable[i].VendorGuid,
235			    &mps, sizeof(EFI_GUID)))
236			printf("MPS Table");
237		else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid,
238				 &acpi, sizeof(EFI_GUID)))
239			printf("ACPI Table");
240		else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid,
241				 &acpi20, sizeof(EFI_GUID)))
242			printf("ACPI 2.0 Table");
243		else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid,
244				 &smbios, sizeof(EFI_GUID)))
245			printf("SMBIOS Table");
246		else if (!memcmp(&ST->ConfigurationTable[i].VendorGuid,
247				 &sal, sizeof(EFI_GUID)))
248			printf("SAL System Table");
249		else
250			printf("Unknown Table");
251		printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
252	}
253
254	return CMD_OK;
255}
256
257COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
258
259static int
260command_sal(int argc, char *argv[])
261{
262	int i;
263	struct sal_system_table *saltab = 0;
264	static int sizes[6] = {
265		48, 32, 16, 32, 16, 16
266	};
267	u_int8_t *p;
268
269	for (i = 0; i < ST->NumberOfTableEntries; i++) {
270		static EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
271		if (!memcmp(&ST->ConfigurationTable[i].VendorGuid,
272				 &sal, sizeof(EFI_GUID)))
273			saltab = ST->ConfigurationTable[i].VendorTable;
274	}
275
276	if (!saltab) {
277		printf("Can't find SAL System Table\n");
278		return CMD_ERROR;
279	}
280
281	if (memcmp(saltab->sal_signature, "SST_", 4)) {
282		printf("Bad signature for SAL System Table\n");
283		return CMD_ERROR;
284	}
285
286	printf("SAL Revision %x.%02x\n",
287	       saltab->sal_rev[1],
288	       saltab->sal_rev[0]);
289	printf("SAL A Version %x.%02x\n",
290	       saltab->sal_a_version[1],
291	       saltab->sal_a_version[0]);
292	printf("SAL B Version %x.%02x\n",
293	       saltab->sal_b_version[1],
294	       saltab->sal_b_version[0]);
295
296	p = (u_int8_t *) (saltab + 1);
297	for (i = 0; i < saltab->sal_entry_count; i++) {
298		printf("  Desc %d", *p);
299		if (*p == 0) {
300			struct sal_entrypoint_descriptor *dp;
301			dp = (struct sal_entrypoint_descriptor *) p;
302			printf("\n");
303			printf("    PAL Proc at 0x%lx\n",
304			       dp->sale_pal_proc);
305			printf("    SAL Proc at 0x%lx\n",
306			       dp->sale_sal_proc);
307			printf("    SAL GP at 0x%lx\n",
308			       dp->sale_sal_gp);
309		} else if (*p == 1) {
310			struct sal_memory_descriptor *dp;
311			dp = (struct sal_memory_descriptor *) p;
312			printf(" Type %d.%d, ",
313			       dp->sale_memory_type[0],
314			       dp->sale_memory_type[1]);
315			printf("Address 0x%lx, ",
316			       dp->sale_physical_address);
317			printf("Length 0x%x\n",
318			       dp->sale_length);
319		} else {
320			printf("\n");
321		}
322		p += sizes[*p];
323	}
324
325	return CMD_OK;
326}
327