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
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
34 #include <machine/sal.h>
35 #include <machine/pal.h>
36 #include <machine/pte.h>
37 #include <machine/dig64.h>
44 /* DIG64 Headless Console & Debug Port Table. */
45 #define HCDP_TABLE_GUID \
46 {0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}}
48 extern char bootprog_name[];
49 extern char bootprog_rev[];
50 extern char bootprog_date[];
51 extern char bootprog_maker[];
53 struct arch_switch archsw; /* MI/MD interface boundary */
55 extern u_int64_t ia64_pal_entry;
57 EFI_GUID acpi = ACPI_TABLE_GUID;
58 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
59 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
60 EFI_GUID hcdp = HCDP_TABLE_GUID;
61 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
62 EFI_GUID mps = MPS_TABLE_GUID;
63 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
64 EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
65 EFI_GUID smbios = SMBIOS_TABLE_GUID;
71 struct sal_system_table *saltab = 0;
72 static int sizes[6] = {
73 48, 32, 16, 32, 16, 16
77 saltab = efi_get_table(&sal);
79 printf("Can't find SAL System Table\n");
83 if (memcmp(saltab->sal_signature, "SST_", 4)) {
84 printf("Bad signature for SAL System Table\n");
88 p = (u_int8_t *) (saltab + 1);
89 for (i = 0; i < saltab->sal_entry_count; i++) {
91 struct sal_entrypoint_descriptor *dp;
92 dp = (struct sal_entrypoint_descriptor *) p;
93 ia64_pal_entry = dp->sale_pal_proc;
99 printf("Can't find PAL proc\n");
104 usc2cmp(CHAR16 *s1, CHAR16 *s2)
107 while (*s1 == *s2++) {
111 return (*s1 - *(s2 - 1));
115 get_dev_option(int argc, CHAR16 *argv[])
123 for (i = 0; i < argc; i++) {
124 if (usc2cmp(argv[i], L"-dev") == 0 && i < argc - 1) {
127 while (j < sizeof(dev) && *arg != 0)
129 if (j == sizeof(dev))
141 main(int argc, CHAR16 *argv[])
143 struct devdesc currdev;
144 EFI_LOADED_IMAGE *img;
149 * XXX Chicken-and-egg problem; we want to have console output
150 * early, but some console attributes may depend on reading from
151 * eg. the boot device, which we can't do yet. We can use
152 * printf() etc. once this is done.
156 printf("\n%s, Revision %s\n", bootprog_name, bootprog_rev);
161 * March through the device switch probing for things.
163 for (i = 0; devsw[i] != NULL; i++)
164 if (devsw[i]->dv_init != NULL)
165 (devsw[i]->dv_init)();
168 * Disable the watchdog timer. By default the boot manager sets
169 * the timer to 5 minutes before invoking a boot option. If we
170 * want to return to the boot manager, we have to disable the
171 * watchdog timer and since we're an interactive program, we don't
172 * want to wait until the user types "quit". The timer may have
173 * fired by then. We don't care if this fails. It does not prevent
174 * normal functioning in any way...
176 BS->SetWatchdogTimer(0, 0, 0, NULL);
178 /* Get our loaded image protocol interface structure. */
179 BS->HandleProtocol(IH, &imgid, (VOID**)&img);
181 bzero(&currdev, sizeof(currdev));
182 efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
183 currdev.d_type = currdev.d_dev->dv_type;
185 env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset,
188 dev = get_dev_option(argc, argv);
190 dev = ia64_fmtdev(&currdev);
192 env_setenv("currdev", EV_VOLATILE, dev, ia64_setcurrdev, env_nounset);
194 setenv("LINES", "24", 1); /* optional */
196 archsw.arch_autoload = ia64_autoload;
197 archsw.arch_copyin = ia64_copyin;
198 archsw.arch_copyout = ia64_copyout;
199 archsw.arch_getdev = ia64_getdev;
200 archsw.arch_loadaddr = ia64_loadaddr;
201 archsw.arch_loadseg = ia64_loadseg;
202 archsw.arch_readin = ia64_readin;
204 interact(); /* doesn't return */
206 return (EFI_SUCCESS); /* keep compiler happy */
209 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
212 command_quit(int argc, char *argv[])
219 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
222 command_reboot(int argc, char *argv[])
225 RS->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
230 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
233 command_memmap(int argc, char *argv[])
236 EFI_MEMORY_DESCRIPTOR *map, *p;
241 static char *types[] = {
247 "RuntimeServicesCode",
248 "RuntimeServicesData",
249 "ConventionalMemory",
254 "MemoryMappedIOPortSpace",
259 status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
260 if (status != EFI_BUFFER_TOO_SMALL) {
261 printf("Can't determine memory map size\n");
265 status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
266 if (EFI_ERROR(status)) {
267 printf("Can't read memory map\n");
272 printf("%23s %12s %12s %8s %4s\n",
273 "Type", "Physical", "Virtual", "#Pages", "Attr");
275 for (i = 0, p = map; i < ndesc;
276 i++, p = NextMemoryDescriptor(p, dsz)) {
277 printf("%23s %012lx %012lx %08lx ",
282 if (p->Attribute & EFI_MEMORY_UC)
284 if (p->Attribute & EFI_MEMORY_WC)
286 if (p->Attribute & EFI_MEMORY_WT)
288 if (p->Attribute & EFI_MEMORY_WB)
290 if (p->Attribute & EFI_MEMORY_UCE)
292 if (p->Attribute & EFI_MEMORY_WP)
294 if (p->Attribute & EFI_MEMORY_RP)
296 if (p->Attribute & EFI_MEMORY_XP)
298 if (p->Attribute & EFI_MEMORY_RUNTIME)
306 COMMAND_SET(configuration, "configuration",
307 "print configuration tables", command_configuration);
310 guid_to_string(EFI_GUID *guid)
314 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
315 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
316 guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
317 guid->Data4[5], guid->Data4[6], guid->Data4[7]);
322 command_configuration(int argc, char *argv[])
326 printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
327 for (i = 0; i < ST->NumberOfTableEntries; i++) {
331 guid = &ST->ConfigurationTable[i].VendorGuid;
332 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
334 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
335 printf("ACPI Table");
336 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
337 printf("ACPI 2.0 Table");
338 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
339 printf("SMBIOS Table");
340 else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
341 printf("SAL System Table");
342 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
343 printf("DIG64 HCDP Table");
345 printf("Unknown Table (%s)", guid_to_string(guid));
346 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
352 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
355 command_sal(int argc, char *argv[])
358 struct sal_system_table *saltab = 0;
359 static int sizes[6] = {
360 48, 32, 16, 32, 16, 16
364 saltab = efi_get_table(&sal);
365 if (saltab == NULL) {
366 printf("Can't find SAL System Table\n");
370 if (memcmp(saltab->sal_signature, "SST_", 4)) {
371 printf("Bad signature for SAL System Table\n");
375 printf("SAL Revision %x.%02x\n",
378 printf("SAL A Version %x.%02x\n",
379 saltab->sal_a_version[1],
380 saltab->sal_a_version[0]);
381 printf("SAL B Version %x.%02x\n",
382 saltab->sal_b_version[1],
383 saltab->sal_b_version[0]);
385 p = (u_int8_t *) (saltab + 1);
386 for (i = 0; i < saltab->sal_entry_count; i++) {
387 printf(" Desc %d", *p);
389 struct sal_entrypoint_descriptor *dp;
390 dp = (struct sal_entrypoint_descriptor *) p;
392 printf(" PAL Proc at 0x%lx\n",
394 printf(" SAL Proc at 0x%lx\n",
396 printf(" SAL GP at 0x%lx\n",
398 } else if (*p == 1) {
399 struct sal_memory_descriptor *dp;
400 dp = (struct sal_memory_descriptor *) p;
401 printf(" Type %d.%d, ",
402 dp->sale_memory_type[0],
403 dp->sale_memory_type[1]);
404 printf("Address 0x%lx, ",
405 dp->sale_physical_address);
406 printf("Length 0x%x\n",
408 } else if (*p == 5) {
409 struct sal_ap_wakeup_descriptor *dp;
410 dp = (struct sal_ap_wakeup_descriptor *) p;
412 printf(" Mechanism %d\n", dp->sale_mechanism);
413 printf(" Vector 0x%lx\n", dp->sale_vector);
426 struct ia64_pal_result res;
434 static const char *psnames[] = {
435 "1B", "2B", "4B", "8B",
436 "16B", "32B", "64B", "128B",
437 "256B", "512B", "1K", "2K",
438 "4K", "8K", "16K", "32K",
439 "64K", "128K", "256K", "512K",
440 "1M", "2M", "4M", "8M",
441 "16M", "32M", "64M", "128M",
442 "256M", "512M", "1G", "2G"
444 static const char *manames[] = {
445 "WB", "bad", "bad", "bad",
446 "UC", "UCE", "WC", "NaT",
449 res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
450 if (res.pal_status != 0) {
451 printf("Can't get VM summary\n");
456 maxtr = (res.pal_result[0] >> 40) & 0xff;
458 maxtr = (res.pal_result[0] >> 32) & 0xff;
460 printf("%d translation registers\n", maxtr);
463 pager_output("TR# RID Virtual Page Physical Page PgSz ED AR PL D A MA P KEY\n");
464 for (i = 0; i <= maxtr; i++) {
467 bzero(&buf, sizeof(buf));
468 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
470 if (res.pal_status != 0)
473 /* Only display valid translations */
474 if ((buf.ifa & 1) == 0)
477 if (!(res.pal_result[0] & 1))
478 buf.pte &= ~PTE_AR_MASK;
479 if (!(res.pal_result[0] & 2))
480 buf.pte &= ~PTE_PL_MASK;
481 if (!(res.pal_result[0] & 4))
482 buf.pte &= ~PTE_DIRTY;
483 if (!(res.pal_result[0] & 8))
484 buf.pte &= ~PTE_MA_MASK;
485 sprintf(lbuf, "%03d %06x %013lx %013lx %4s %d %d %d %d %d "
486 "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
487 (buf.pte & PTE_PPN_MASK) >> 12,
488 psnames[(buf.itir & ITIR_PS_MASK) >> 2],
489 (buf.pte & PTE_ED) ? 1 : 0,
490 (int)(buf.pte & PTE_AR_MASK) >> 9,
491 (int)(buf.pte & PTE_PL_MASK) >> 7,
492 (buf.pte & PTE_DIRTY) ? 1 : 0,
493 (buf.pte & PTE_ACCESSED) ? 1 : 0,
494 manames[(buf.pte & PTE_MA_MASK) >> 2],
495 (buf.pte & PTE_PRESENT) ? 1 : 0,
496 (int)((buf.itir & ITIR_KEY_MASK) >> 8));
501 if (res.pal_status != 0) {
502 printf("Error while getting TR contents\n");
508 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
511 command_itr(int argc, char *argv[])
516 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
519 command_dtr(int argc, char *argv[])
524 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
527 hcdp_string(char *s, u_int len)
529 static char buffer[256];
531 memcpy(buffer, s, len);
537 command_hcdp(int argc, char *argv[])
539 struct dig64_hcdp_table *tbl;
540 struct dig64_hcdp_entry *ent;
541 struct dig64_gas *gas;
544 tbl = efi_get_table(&hcdp);
546 printf("No HCDP table present\n");
549 if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
550 printf("HCDP table has invalid signature\n");
553 if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
554 printf("HCDP table too short\n");
557 printf("HCDP table at 0x%016lx\n", (u_long)tbl);
558 printf("Signature = %s\n", hcdp_string(tbl->signature, 4));
559 printf("Length = %u\n", tbl->length);
560 printf("Revision = %u\n", tbl->revision);
561 printf("Checksum = %u\n", tbl->checksum);
562 printf("OEM Id = %s\n", hcdp_string(tbl->oem_id, 6));
563 printf("Table Id = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
564 printf("OEM rev = %u\n", tbl->oem_rev);
565 printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
566 printf("Creator rev= %u\n", tbl->creator_rev);
567 printf("Entries = %u\n", tbl->entries);
568 for (i = 0; i < tbl->entries; i++) {
569 ent = tbl->entry + i;
570 printf("Entry #%d:\n", i + 1);
571 printf(" Type = %u\n", ent->type);
572 printf(" Databits = %u\n", ent->databits);
573 printf(" Parity = %u\n", ent->parity);
574 printf(" Stopbits = %u\n", ent->stopbits);
575 printf(" PCI seg = %u\n", ent->pci_segment);
576 printf(" PCI bus = %u\n", ent->pci_bus);
577 printf(" PCI dev = %u\n", ent->pci_device);
578 printf(" PCI func = %u\n", ent->pci_function);
579 printf(" Interrupt = %u\n", ent->interrupt);
580 printf(" PCI flag = %u\n", ent->pci_flag);
581 printf(" Baudrate = %lu\n",
582 ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
584 printf(" Addr space= %u\n", gas->addr_space);
585 printf(" Bit width = %u\n", gas->bit_width);
586 printf(" Bit offset= %u\n", gas->bit_offset);
587 printf(" Address = 0x%016lx\n",
588 ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
589 printf(" PCI type = %u\n", ent->pci_devid);
590 printf(" PCI vndr = %u\n", ent->pci_vendor);
591 printf(" IRQ = %u\n", ent->irq);
592 printf(" PClock = %u\n", ent->pclock);
593 printf(" PCI iface = %u\n", ent->pci_interface);
599 COMMAND_SET(about, "about", "about the loader", command_about);
601 extern uint64_t _start_plabel[];
604 command_about(int argc, char *argv[])
606 EFI_LOADED_IMAGE *img;
608 printf("%s\n", bootprog_name);
609 printf("revision %s\n", bootprog_rev);
610 printf("built by %s\n", bootprog_maker);
611 printf("built on %s\n", bootprog_date);
615 BS->HandleProtocol(IH, &imgid, (VOID**)&img);
616 printf("image loaded at %p\n", img->ImageBase);
617 printf("entry at %#lx (%#lx)\n", _start_plabel[0], _start_plabel[1]);