2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * Copyright (c) 1998,2000 Doug Rabson <dfr@freebsd.org>
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
27 * $FreeBSD: src/sys/boot/efi/loader/main.c,v 1.20 2003/08/02 08:22:03 marcel Exp $
33 #include <machine/sal.h>
34 #include <machine/pal.h>
35 #include <machine/pte.h>
36 #include <machine/dig64.h>
41 #include "bootstrap.h"
44 extern char bootprog_name[];
45 extern char bootprog_rev[];
46 extern char bootprog_date[];
47 extern char bootprog_maker[];
49 struct efi_devdesc currdev; /* our current device */
50 struct arch_switch archsw; /* MI/MD interface boundary */
52 extern u_int64_t ia64_pal_entry;
54 EFI_GUID acpi = ACPI_TABLE_GUID;
55 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
56 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
57 EFI_GUID hcdp = HCDP_TABLE_GUID;
58 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
59 EFI_GUID mps = MPS_TABLE_GUID;
60 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
61 EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
62 EFI_GUID smbios = SMBIOS_TABLE_GUID;
68 struct sal_system_table *saltab = NULL;
69 static int sizes[6] = {
70 48, 32, 16, 32, 16, 16
74 saltab = efi_get_table(&sal);
76 printf("Can't find SAL System Table\n");
80 if (memcmp(saltab->sal_signature, "SST_", 4)) {
81 printf("Bad signature for SAL System Table\n");
85 p = (u_int8_t *) (saltab + 1);
86 for (i = 0; i < saltab->sal_entry_count; i++) {
88 struct sal_entrypoint_descriptor *dp;
89 dp = (struct sal_entrypoint_descriptor *) p;
90 ia64_pal_entry = dp->sale_pal_proc;
96 printf("Can't find PAL proc\n");
101 main(int argc, CHAR16 *argv[])
103 EFI_LOADED_IMAGE *img;
107 * XXX Chicken-and-egg problem; we want to have console output
108 * early, but some console attributes may depend on reading from
109 * eg. the boot device, which we can't do yet. We can use
110 * printf() etc. once this is done.
115 * Initialise the block cache
117 bcache_init(32, 512); /* 16k XXX tune this */
122 * March through the device switch probing for things.
124 for (i = 0; devsw[i] != NULL; i++)
125 if (devsw[i]->dv_init != NULL)
126 (devsw[i]->dv_init)();
128 efinet_init_driver();
130 /* Get our loaded image protocol interface structure. */
131 BS->HandleProtocol(IH, &imgid, (VOID**)&img);
133 printf("Image base: 0x%016lx\n", (u_long)img->ImageBase);
136 printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
137 printf("(%s, %s)\n", bootprog_maker, bootprog_date);
139 i = efifs_get_unit(img->DeviceHandle);
141 currdev.d_dev = devsw[0]; /* XXX disk */
142 currdev.d_kind.efidisk.unit = i;
143 /* XXX should be able to detect this, default to autoprobe */
144 currdev.d_kind.efidisk.slice = -1;
145 currdev.d_kind.efidisk.partition = 0;
147 currdev.d_dev = devsw[1]; /* XXX net */
148 currdev.d_kind.netif.unit = 0; /* XXX */
150 currdev.d_type = currdev.d_dev->dv_type;
153 * Disable the watchdog timer. By default the boot manager sets
154 * the timer to 5 minutes before invoking a boot option. If we
155 * want to return to the boot manager, we have to disable the
156 * watchdog timer and since we're an interactive program, we don't
157 * want to wait until the user types "quit". The timer may have
158 * fired by then. We don't care if this fails. It does not prevent
159 * normal functioning in any way...
161 BS->SetWatchdogTimer(0, 0, 0, NULL);
163 env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
164 efi_setcurrdev, env_nounset);
165 env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
168 setenv("LINES", "24", 1); /* optional */
170 archsw.arch_autoload = efi_autoload;
171 archsw.arch_getdev = efi_getdev;
172 archsw.arch_copyin = efi_copyin;
173 archsw.arch_copyout = efi_copyout;
174 archsw.arch_readin = efi_readin;
176 interact(); /* doesn't return */
178 return (EFI_SUCCESS); /* keep compiler happy */
181 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
184 command_quit(int argc, char *argv[])
190 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
193 command_memmap(int argc, char *argv[])
196 EFI_MEMORY_DESCRIPTOR *map, *p;
201 static char *types[] = {
207 "RuntimeServicesCode",
208 "RuntimeServicesData",
209 "ConventionalMemory",
214 "MemoryMappedIOPortSpace",
219 status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
220 if (status != EFI_BUFFER_TOO_SMALL) {
221 printf("Can't determine memory map size\n");
225 status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
226 if (EFI_ERROR(status)) {
227 printf("Can't read memory map\n");
232 printf("%23s %12s %12s %8s %4s\n",
233 "Type", "Physical", "Virtual", "#Pages", "Attr");
235 for (i = 0, p = map; i < ndesc;
236 i++, p = NextMemoryDescriptor(p, dsz)) {
237 printf("%23s %012lx %012lx %08lx ",
242 if (p->Attribute & EFI_MEMORY_UC)
244 if (p->Attribute & EFI_MEMORY_WC)
246 if (p->Attribute & EFI_MEMORY_WT)
248 if (p->Attribute & EFI_MEMORY_WB)
250 if (p->Attribute & EFI_MEMORY_UCE)
252 if (p->Attribute & EFI_MEMORY_WP)
254 if (p->Attribute & EFI_MEMORY_RP)
256 if (p->Attribute & EFI_MEMORY_XP)
258 if (p->Attribute & EFI_MEMORY_RUNTIME)
266 COMMAND_SET(configuration, "configuration",
267 "print configuration tables", command_configuration);
270 guid_to_string(EFI_GUID *guid)
274 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
275 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
276 guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
277 guid->Data4[5], guid->Data4[6], guid->Data4[7]);
282 command_configuration(int argc, char *argv[])
286 printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
287 for (i = 0; i < ST->NumberOfTableEntries; i++) {
291 guid = &ST->ConfigurationTable[i].VendorGuid;
292 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
294 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
295 printf("ACPI Table");
296 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
297 printf("ACPI 2.0 Table");
298 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
299 printf("SMBIOS Table");
300 else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
301 printf("SAL System Table");
302 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
303 printf("DIG64 HCDP Table");
305 printf("Unknown Table (%s)", guid_to_string(guid));
306 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
312 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
315 command_sal(int argc, char *argv[])
318 struct sal_system_table *saltab = NULL;
319 static int sizes[6] = {
320 48, 32, 16, 32, 16, 16
324 saltab = efi_get_table(&sal);
325 if (saltab == NULL) {
326 printf("Can't find SAL System Table\n");
330 if (memcmp(saltab->sal_signature, "SST_", 4)) {
331 printf("Bad signature for SAL System Table\n");
335 printf("SAL Revision %x.%02x\n",
338 printf("SAL A Version %x.%02x\n",
339 saltab->sal_a_version[1],
340 saltab->sal_a_version[0]);
341 printf("SAL B Version %x.%02x\n",
342 saltab->sal_b_version[1],
343 saltab->sal_b_version[0]);
345 p = (u_int8_t *) (saltab + 1);
346 for (i = 0; i < saltab->sal_entry_count; i++) {
347 printf(" Desc %d", *p);
349 struct sal_entrypoint_descriptor *dp;
350 dp = (struct sal_entrypoint_descriptor *) p;
352 printf(" PAL Proc at 0x%lx\n",
354 printf(" SAL Proc at 0x%lx\n",
356 printf(" SAL GP at 0x%lx\n",
358 } else if (*p == 1) {
359 struct sal_memory_descriptor *dp;
360 dp = (struct sal_memory_descriptor *) p;
361 printf(" Type %d.%d, ",
362 dp->sale_memory_type[0],
363 dp->sale_memory_type[1]);
364 printf("Address 0x%lx, ",
365 dp->sale_physical_address);
366 printf("Length 0x%x\n",
368 } else if (*p == 5) {
369 struct sal_ap_wakeup_descriptor *dp;
370 dp = (struct sal_ap_wakeup_descriptor *) p;
372 printf(" Mechanism %d\n", dp->sale_mechanism);
373 printf(" Vector 0x%lx\n", dp->sale_vector);
386 struct ia64_pal_result res;
390 struct ia64_itir itir;
394 static const char* psnames[] = {
395 "1B", "2B", "4B", "8B",
396 "16B", "32B", "64B", "128B",
397 "256B", "512B", "1K", "2K",
398 "4K", "8K", "16K", "32K",
399 "64K", "128K", "256K", "512K",
400 "1M", "2M", "4M", "8M",
401 "16M", "32M", "64M", "128M",
402 "256M", "512M", "1G", "2G"
404 static const char* manames[] = {
405 "WB", "bad", "bad", "bad",
406 "UC", "UCE", "WC", "NaT",
410 res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
411 if (res.pal_status != 0) {
412 printf("Can't get VM summary\n");
417 maxtr = (res.pal_result[0] >> 40) & 0xff;
419 maxtr = (res.pal_result[0] >> 32) & 0xff;
421 printf("%d translation registers\n", maxtr);
424 pager_output("TR# RID Virtual Page Physical Page PgSz ED AR PL D A MA P KEY\n");
425 for (i = 0; i <= maxtr; i++) {
428 bzero(&buf, sizeof(buf));
429 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
431 if (res.pal_status != 0)
434 /* Only display valid translations */
435 if ((buf.ifa.ifa_ig & 1) == 0)
438 if (!(res.pal_result[0] & 1))
440 if (!(res.pal_result[0] & 2))
442 if (!(res.pal_result[0] & 4))
444 if (!(res.pal_result[0] & 8))
447 "%03d %06x %013lx %013lx %4s %d %d %d %d %d %-3s %d %06x\n",
452 psnames[buf.itir.itir_ps],
458 manames[buf.pte.pte_ma],
465 if (res.pal_status != 0) {
466 printf("Error while getting TR contents\n");
472 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
475 command_itr(int argc, char *argv[])
480 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
483 command_dtr(int argc, char *argv[])
488 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
491 hcdp_string(char *s, u_int len)
493 static char buffer[256];
495 memcpy(buffer, s, len);
501 command_hcdp(int argc, char *argv[])
503 struct dig64_hcdp_table *tbl;
504 struct dig64_hcdp_entry *ent;
505 struct dig64_gas *gas;
508 tbl = efi_get_table(&hcdp);
510 printf("No HCDP table present\n");
513 if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
514 printf("HCDP table has invalid signature\n");
517 if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
518 printf("HCDP table too short\n");
521 printf("HCDP table at 0x%016lx\n", (u_long)tbl);
522 printf("Signature = %s\n", hcdp_string(tbl->signature, 4));
523 printf("Length = %u\n", tbl->length);
524 printf("Revision = %u\n", tbl->revision);
525 printf("Checksum = %u\n", tbl->checksum);
526 printf("OEM Id = %s\n", hcdp_string(tbl->oem_id, 6));
527 printf("Table Id = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
528 printf("OEM rev = %u\n", tbl->oem_rev);
529 printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
530 printf("Creator rev= %u\n", tbl->creator_rev);
531 printf("Entries = %u\n", tbl->entries);
532 for (i = 0; i < tbl->entries; i++) {
533 ent = tbl->entry + i;
534 printf("Entry #%d:\n", i + 1);
535 printf(" Type = %u\n", ent->type);
536 printf(" Databits = %u\n", ent->databits);
537 printf(" Parity = %u\n", ent->parity);
538 printf(" Stopbits = %u\n", ent->stopbits);
539 printf(" PCI seg = %u\n", ent->pci_segment);
540 printf(" PCI bus = %u\n", ent->pci_bus);
541 printf(" PCI dev = %u\n", ent->pci_device);
542 printf(" PCI func = %u\n", ent->pci_function);
543 printf(" Interrupt = %u\n", ent->interrupt);
544 printf(" PCI flag = %u\n", ent->pci_flag);
545 printf(" Baudrate = %lu\n",
546 ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
548 printf(" Addr space= %u\n", gas->addr_space);
549 printf(" Bit width = %u\n", gas->bit_width);
550 printf(" Bit offset= %u\n", gas->bit_offset);
551 printf(" Address = 0x%016lx\n",
552 ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
553 printf(" PCI type = %u\n", ent->pci_devid);
554 printf(" PCI vndr = %u\n", ent->pci_vendor);
555 printf(" IRQ = %u\n", ent->irq);
556 printf(" PClock = %u\n", ent->pclock);
557 printf(" PCI iface = %u\n", ent->pci_interface);