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 $
28 * $DragonFly: src/sys/boot/efi/loader/main.c,v 1.1 2003/11/10 06:08:33 dillon Exp $
34 #include <machine/sal.h>
35 #include <machine/pal.h>
36 #include <machine/pte.h>
37 #include <machine/dig64.h>
42 #include "bootstrap.h"
45 extern char bootprog_name[];
46 extern char bootprog_rev[];
47 extern char bootprog_date[];
48 extern char bootprog_maker[];
50 struct efi_devdesc currdev; /* our current device */
51 struct arch_switch archsw; /* MI/MD interface boundary */
53 extern u_int64_t ia64_pal_entry;
55 EFI_GUID acpi = ACPI_TABLE_GUID;
56 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
57 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
58 EFI_GUID hcdp = HCDP_TABLE_GUID;
59 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
60 EFI_GUID mps = MPS_TABLE_GUID;
61 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
62 EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
63 EFI_GUID smbios = SMBIOS_TABLE_GUID;
69 struct sal_system_table *saltab = 0;
70 static int sizes[6] = {
71 48, 32, 16, 32, 16, 16
75 saltab = efi_get_table(&sal);
77 printf("Can't find SAL System Table\n");
81 if (memcmp(saltab->sal_signature, "SST_", 4)) {
82 printf("Bad signature for SAL System Table\n");
86 p = (u_int8_t *) (saltab + 1);
87 for (i = 0; i < saltab->sal_entry_count; i++) {
89 struct sal_entrypoint_descriptor *dp;
90 dp = (struct sal_entrypoint_descriptor *) p;
91 ia64_pal_entry = dp->sale_pal_proc;
97 printf("Can't find PAL proc\n");
102 main(int argc, CHAR16 *argv[])
104 EFI_LOADED_IMAGE *img;
108 * XXX Chicken-and-egg problem; we want to have console output
109 * early, but some console attributes may depend on reading from
110 * eg. the boot device, which we can't do yet. We can use
111 * printf() etc. once this is done.
116 * Initialise the block cache
118 bcache_init(32, 512); /* 16k XXX tune this */
123 * March through the device switch probing for things.
125 for (i = 0; devsw[i] != NULL; i++)
126 if (devsw[i]->dv_init != NULL)
127 (devsw[i]->dv_init)();
129 efinet_init_driver();
131 /* Get our loaded image protocol interface structure. */
132 BS->HandleProtocol(IH, &imgid, (VOID**)&img);
134 printf("Image base: 0x%016lx\n", (u_long)img->ImageBase);
137 printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
138 printf("(%s, %s)\n", bootprog_maker, bootprog_date);
140 i = efifs_get_unit(img->DeviceHandle);
142 currdev.d_dev = devsw[0]; /* XXX disk */
143 currdev.d_kind.efidisk.unit = i;
144 /* XXX should be able to detect this, default to autoprobe */
145 currdev.d_kind.efidisk.slice = -1;
146 currdev.d_kind.efidisk.partition = 0;
148 currdev.d_dev = devsw[1]; /* XXX net */
149 currdev.d_kind.netif.unit = 0; /* XXX */
151 currdev.d_type = currdev.d_dev->dv_type;
154 * Disable the watchdog timer. By default the boot manager sets
155 * the timer to 5 minutes before invoking a boot option. If we
156 * want to return to the boot manager, we have to disable the
157 * watchdog timer and since we're an interactive program, we don't
158 * want to wait until the user types "quit". The timer may have
159 * fired by then. We don't care if this fails. It does not prevent
160 * normal functioning in any way...
162 BS->SetWatchdogTimer(0, 0, 0, NULL);
164 env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
165 efi_setcurrdev, env_nounset);
166 env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
169 setenv("LINES", "24", 1); /* optional */
171 archsw.arch_autoload = efi_autoload;
172 archsw.arch_getdev = efi_getdev;
173 archsw.arch_copyin = efi_copyin;
174 archsw.arch_copyout = efi_copyout;
175 archsw.arch_readin = efi_readin;
177 interact(); /* doesn't return */
179 return (EFI_SUCCESS); /* keep compiler happy */
182 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
185 command_quit(int argc, char *argv[])
191 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
194 command_memmap(int argc, char *argv[])
197 EFI_MEMORY_DESCRIPTOR *map, *p;
202 static char *types[] = {
208 "RuntimeServicesCode",
209 "RuntimeServicesData",
210 "ConventionalMemory",
215 "MemoryMappedIOPortSpace",
220 status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
221 if (status != EFI_BUFFER_TOO_SMALL) {
222 printf("Can't determine memory map size\n");
226 status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
227 if (EFI_ERROR(status)) {
228 printf("Can't read memory map\n");
233 printf("%23s %12s %12s %8s %4s\n",
234 "Type", "Physical", "Virtual", "#Pages", "Attr");
236 for (i = 0, p = map; i < ndesc;
237 i++, p = NextMemoryDescriptor(p, dsz)) {
238 printf("%23s %012lx %012lx %08lx ",
243 if (p->Attribute & EFI_MEMORY_UC)
245 if (p->Attribute & EFI_MEMORY_WC)
247 if (p->Attribute & EFI_MEMORY_WT)
249 if (p->Attribute & EFI_MEMORY_WB)
251 if (p->Attribute & EFI_MEMORY_UCE)
253 if (p->Attribute & EFI_MEMORY_WP)
255 if (p->Attribute & EFI_MEMORY_RP)
257 if (p->Attribute & EFI_MEMORY_XP)
259 if (p->Attribute & EFI_MEMORY_RUNTIME)
267 COMMAND_SET(configuration, "configuration",
268 "print configuration tables", command_configuration);
271 guid_to_string(EFI_GUID *guid)
275 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
276 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
277 guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
278 guid->Data4[5], guid->Data4[6], guid->Data4[7]);
283 command_configuration(int argc, char *argv[])
287 printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
288 for (i = 0; i < ST->NumberOfTableEntries; i++) {
292 guid = &ST->ConfigurationTable[i].VendorGuid;
293 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
295 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
296 printf("ACPI Table");
297 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
298 printf("ACPI 2.0 Table");
299 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
300 printf("SMBIOS Table");
301 else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
302 printf("SAL System Table");
303 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
304 printf("DIG64 HCDP Table");
306 printf("Unknown Table (%s)", guid_to_string(guid));
307 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
313 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
316 command_sal(int argc, char *argv[])
319 struct sal_system_table *saltab = 0;
320 static int sizes[6] = {
321 48, 32, 16, 32, 16, 16
325 saltab = efi_get_table(&sal);
326 if (saltab == NULL) {
327 printf("Can't find SAL System Table\n");
331 if (memcmp(saltab->sal_signature, "SST_", 4)) {
332 printf("Bad signature for SAL System Table\n");
336 printf("SAL Revision %x.%02x\n",
339 printf("SAL A Version %x.%02x\n",
340 saltab->sal_a_version[1],
341 saltab->sal_a_version[0]);
342 printf("SAL B Version %x.%02x\n",
343 saltab->sal_b_version[1],
344 saltab->sal_b_version[0]);
346 p = (u_int8_t *) (saltab + 1);
347 for (i = 0; i < saltab->sal_entry_count; i++) {
348 printf(" Desc %d", *p);
350 struct sal_entrypoint_descriptor *dp;
351 dp = (struct sal_entrypoint_descriptor *) p;
353 printf(" PAL Proc at 0x%lx\n",
355 printf(" SAL Proc at 0x%lx\n",
357 printf(" SAL GP at 0x%lx\n",
359 } else if (*p == 1) {
360 struct sal_memory_descriptor *dp;
361 dp = (struct sal_memory_descriptor *) p;
362 printf(" Type %d.%d, ",
363 dp->sale_memory_type[0],
364 dp->sale_memory_type[1]);
365 printf("Address 0x%lx, ",
366 dp->sale_physical_address);
367 printf("Length 0x%x\n",
369 } else if (*p == 5) {
370 struct sal_ap_wakeup_descriptor *dp;
371 dp = (struct sal_ap_wakeup_descriptor *) p;
373 printf(" Mechanism %d\n", dp->sale_mechanism);
374 printf(" Vector 0x%lx\n", dp->sale_vector);
387 struct ia64_pal_result res;
391 struct ia64_itir itir;
395 static const char* psnames[] = {
396 "1B", "2B", "4B", "8B",
397 "16B", "32B", "64B", "128B",
398 "256B", "512B", "1K", "2K",
399 "4K", "8K", "16K", "32K",
400 "64K", "128K", "256K", "512K",
401 "1M", "2M", "4M", "8M",
402 "16M", "32M", "64M", "128M",
403 "256M", "512M", "1G", "2G"
405 static const char* manames[] = {
406 "WB", "bad", "bad", "bad",
407 "UC", "UCE", "WC", "NaT",
411 res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
412 if (res.pal_status != 0) {
413 printf("Can't get VM summary\n");
418 maxtr = (res.pal_result[0] >> 40) & 0xff;
420 maxtr = (res.pal_result[0] >> 32) & 0xff;
422 printf("%d translation registers\n", maxtr);
425 pager_output("TR# RID Virtual Page Physical Page PgSz ED AR PL D A MA P KEY\n");
426 for (i = 0; i <= maxtr; i++) {
429 bzero(&buf, sizeof(buf));
430 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
432 if (res.pal_status != 0)
435 /* Only display valid translations */
436 if ((buf.ifa.ifa_ig & 1) == 0)
439 if (!(res.pal_result[0] & 1))
441 if (!(res.pal_result[0] & 2))
443 if (!(res.pal_result[0] & 4))
445 if (!(res.pal_result[0] & 8))
448 "%03d %06x %013lx %013lx %4s %d %d %d %d %d %-3s %d %06x\n",
453 psnames[buf.itir.itir_ps],
459 manames[buf.pte.pte_ma],
466 if (res.pal_status != 0) {
467 printf("Error while getting TR contents\n");
473 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
476 command_itr(int argc, char *argv[])
481 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
484 command_dtr(int argc, char *argv[])
489 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
492 hcdp_string(char *s, u_int len)
494 static char buffer[256];
496 memcpy(buffer, s, len);
502 command_hcdp(int argc, char *argv[])
504 struct dig64_hcdp_table *tbl;
505 struct dig64_hcdp_entry *ent;
506 struct dig64_gas *gas;
509 tbl = efi_get_table(&hcdp);
511 printf("No HCDP table present\n");
514 if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
515 printf("HCDP table has invalid signature\n");
518 if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
519 printf("HCDP table too short\n");
522 printf("HCDP table at 0x%016lx\n", (u_long)tbl);
523 printf("Signature = %s\n", hcdp_string(tbl->signature, 4));
524 printf("Length = %u\n", tbl->length);
525 printf("Revision = %u\n", tbl->revision);
526 printf("Checksum = %u\n", tbl->checksum);
527 printf("OEM Id = %s\n", hcdp_string(tbl->oem_id, 6));
528 printf("Table Id = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
529 printf("OEM rev = %u\n", tbl->oem_rev);
530 printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
531 printf("Creator rev= %u\n", tbl->creator_rev);
532 printf("Entries = %u\n", tbl->entries);
533 for (i = 0; i < tbl->entries; i++) {
534 ent = tbl->entry + i;
535 printf("Entry #%d:\n", i + 1);
536 printf(" Type = %u\n", ent->type);
537 printf(" Databits = %u\n", ent->databits);
538 printf(" Parity = %u\n", ent->parity);
539 printf(" Stopbits = %u\n", ent->stopbits);
540 printf(" PCI seg = %u\n", ent->pci_segment);
541 printf(" PCI bus = %u\n", ent->pci_bus);
542 printf(" PCI dev = %u\n", ent->pci_device);
543 printf(" PCI func = %u\n", ent->pci_function);
544 printf(" Interrupt = %u\n", ent->interrupt);
545 printf(" PCI flag = %u\n", ent->pci_flag);
546 printf(" Baudrate = %lu\n",
547 ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
549 printf(" Addr space= %u\n", gas->addr_space);
550 printf(" Bit width = %u\n", gas->bit_width);
551 printf(" Bit offset= %u\n", gas->bit_offset);
552 printf(" Address = 0x%016lx\n",
553 ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
554 printf(" PCI type = %u\n", ent->pci_devid);
555 printf(" PCI vndr = %u\n", ent->pci_vendor);
556 printf(" IRQ = %u\n", ent->irq);
557 printf(" PClock = %u\n", ent->pclock);
558 printf(" PCI iface = %u\n", ent->pci_interface);