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,
183 &currdev.d_unit, NULL);
184 currdev.d_type = currdev.d_dev->dv_type;
186 env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset,
189 dev = get_dev_option(argc, argv);
191 dev = ia64_fmtdev(&currdev);
193 env_setenv("currdev", EV_VOLATILE, dev, ia64_setcurrdev, env_nounset);
195 setenv("LINES", "24", 1); /* optional */
197 archsw.arch_autoload = ia64_autoload;
198 archsw.arch_copyin = ia64_copyin;
199 archsw.arch_copyout = ia64_copyout;
200 archsw.arch_getdev = ia64_getdev;
201 archsw.arch_loadaddr = ia64_loadaddr;
202 archsw.arch_loadseg = ia64_loadseg;
203 archsw.arch_readin = ia64_readin;
205 interact(); /* doesn't return */
207 return (EFI_SUCCESS); /* keep compiler happy */
210 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
213 command_quit(int argc, char *argv[])
220 COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
223 command_reboot(int argc, char *argv[])
226 RS->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
231 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
234 command_memmap(int argc, char *argv[])
237 EFI_MEMORY_DESCRIPTOR *map, *p;
242 static char *types[] = {
248 "RuntimeServicesCode",
249 "RuntimeServicesData",
250 "ConventionalMemory",
255 "MemoryMappedIOPortSpace",
260 status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
261 if (status != EFI_BUFFER_TOO_SMALL) {
262 printf("Can't determine memory map size\n");
266 status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
267 if (EFI_ERROR(status)) {
268 printf("Can't read memory map\n");
273 printf("%23s %12s %12s %8s %4s\n",
274 "Type", "Physical", "Virtual", "#Pages", "Attr");
276 for (i = 0, p = map; i < ndesc;
277 i++, p = NextMemoryDescriptor(p, dsz)) {
278 printf("%23s %012lx %012lx %08lx ",
283 if (p->Attribute & EFI_MEMORY_UC)
285 if (p->Attribute & EFI_MEMORY_WC)
287 if (p->Attribute & EFI_MEMORY_WT)
289 if (p->Attribute & EFI_MEMORY_WB)
291 if (p->Attribute & EFI_MEMORY_UCE)
293 if (p->Attribute & EFI_MEMORY_WP)
295 if (p->Attribute & EFI_MEMORY_RP)
297 if (p->Attribute & EFI_MEMORY_XP)
299 if (p->Attribute & EFI_MEMORY_RUNTIME)
307 COMMAND_SET(configuration, "configuration",
308 "print configuration tables", command_configuration);
311 guid_to_string(EFI_GUID *guid)
315 sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
316 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
317 guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
318 guid->Data4[5], guid->Data4[6], guid->Data4[7]);
323 command_configuration(int argc, char *argv[])
327 printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
328 for (i = 0; i < ST->NumberOfTableEntries; i++) {
332 guid = &ST->ConfigurationTable[i].VendorGuid;
333 if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
335 else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
336 printf("ACPI Table");
337 else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
338 printf("ACPI 2.0 Table");
339 else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
340 printf("SMBIOS Table");
341 else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
342 printf("SAL System Table");
343 else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
344 printf("DIG64 HCDP Table");
346 printf("Unknown Table (%s)", guid_to_string(guid));
347 printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
353 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
356 command_sal(int argc, char *argv[])
359 struct sal_system_table *saltab = 0;
360 static int sizes[6] = {
361 48, 32, 16, 32, 16, 16
365 saltab = efi_get_table(&sal);
366 if (saltab == NULL) {
367 printf("Can't find SAL System Table\n");
371 if (memcmp(saltab->sal_signature, "SST_", 4)) {
372 printf("Bad signature for SAL System Table\n");
376 printf("SAL Revision %x.%02x\n",
379 printf("SAL A Version %x.%02x\n",
380 saltab->sal_a_version[1],
381 saltab->sal_a_version[0]);
382 printf("SAL B Version %x.%02x\n",
383 saltab->sal_b_version[1],
384 saltab->sal_b_version[0]);
386 p = (u_int8_t *) (saltab + 1);
387 for (i = 0; i < saltab->sal_entry_count; i++) {
388 printf(" Desc %d", *p);
390 struct sal_entrypoint_descriptor *dp;
391 dp = (struct sal_entrypoint_descriptor *) p;
393 printf(" PAL Proc at 0x%lx\n",
395 printf(" SAL Proc at 0x%lx\n",
397 printf(" SAL GP at 0x%lx\n",
399 } else if (*p == 1) {
400 struct sal_memory_descriptor *dp;
401 dp = (struct sal_memory_descriptor *) p;
402 printf(" Type %d.%d, ",
403 dp->sale_memory_type[0],
404 dp->sale_memory_type[1]);
405 printf("Address 0x%lx, ",
406 dp->sale_physical_address);
407 printf("Length 0x%x\n",
409 } else if (*p == 5) {
410 struct sal_ap_wakeup_descriptor *dp;
411 dp = (struct sal_ap_wakeup_descriptor *) p;
413 printf(" Mechanism %d\n", dp->sale_mechanism);
414 printf(" Vector 0x%lx\n", dp->sale_vector);
427 struct ia64_pal_result res;
435 static const char *psnames[] = {
436 "1B", "2B", "4B", "8B",
437 "16B", "32B", "64B", "128B",
438 "256B", "512B", "1K", "2K",
439 "4K", "8K", "16K", "32K",
440 "64K", "128K", "256K", "512K",
441 "1M", "2M", "4M", "8M",
442 "16M", "32M", "64M", "128M",
443 "256M", "512M", "1G", "2G"
445 static const char *manames[] = {
446 "WB", "bad", "bad", "bad",
447 "UC", "UCE", "WC", "NaT",
450 res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
451 if (res.pal_status != 0) {
452 printf("Can't get VM summary\n");
457 maxtr = (res.pal_result[0] >> 40) & 0xff;
459 maxtr = (res.pal_result[0] >> 32) & 0xff;
461 printf("%d translation registers\n", maxtr);
464 pager_output("TR# RID Virtual Page Physical Page PgSz ED AR PL D A MA P KEY\n");
465 for (i = 0; i <= maxtr; i++) {
468 bzero(&buf, sizeof(buf));
469 res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
471 if (res.pal_status != 0)
474 /* Only display valid translations */
475 if ((buf.ifa & 1) == 0)
478 if (!(res.pal_result[0] & 1))
479 buf.pte &= ~PTE_AR_MASK;
480 if (!(res.pal_result[0] & 2))
481 buf.pte &= ~PTE_PL_MASK;
482 if (!(res.pal_result[0] & 4))
483 buf.pte &= ~PTE_DIRTY;
484 if (!(res.pal_result[0] & 8))
485 buf.pte &= ~PTE_MA_MASK;
486 sprintf(lbuf, "%03d %06x %013lx %013lx %4s %d %d %d %d %d "
487 "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
488 (buf.pte & PTE_PPN_MASK) >> 12,
489 psnames[(buf.itir & ITIR_PS_MASK) >> 2],
490 (buf.pte & PTE_ED) ? 1 : 0,
491 (int)(buf.pte & PTE_AR_MASK) >> 9,
492 (int)(buf.pte & PTE_PL_MASK) >> 7,
493 (buf.pte & PTE_DIRTY) ? 1 : 0,
494 (buf.pte & PTE_ACCESSED) ? 1 : 0,
495 manames[(buf.pte & PTE_MA_MASK) >> 2],
496 (buf.pte & PTE_PRESENT) ? 1 : 0,
497 (int)((buf.itir & ITIR_KEY_MASK) >> 8));
502 if (res.pal_status != 0) {
503 printf("Error while getting TR contents\n");
509 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
512 command_itr(int argc, char *argv[])
517 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
520 command_dtr(int argc, char *argv[])
525 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
528 hcdp_string(char *s, u_int len)
530 static char buffer[256];
532 memcpy(buffer, s, len);
538 command_hcdp(int argc, char *argv[])
540 struct dig64_hcdp_table *tbl;
541 struct dig64_hcdp_entry *ent;
542 struct dig64_gas *gas;
545 tbl = efi_get_table(&hcdp);
547 printf("No HCDP table present\n");
550 if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
551 printf("HCDP table has invalid signature\n");
554 if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
555 printf("HCDP table too short\n");
558 printf("HCDP table at 0x%016lx\n", (u_long)tbl);
559 printf("Signature = %s\n", hcdp_string(tbl->signature, 4));
560 printf("Length = %u\n", tbl->length);
561 printf("Revision = %u\n", tbl->revision);
562 printf("Checksum = %u\n", tbl->checksum);
563 printf("OEM Id = %s\n", hcdp_string(tbl->oem_id, 6));
564 printf("Table Id = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
565 printf("OEM rev = %u\n", tbl->oem_rev);
566 printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
567 printf("Creator rev= %u\n", tbl->creator_rev);
568 printf("Entries = %u\n", tbl->entries);
569 for (i = 0; i < tbl->entries; i++) {
570 ent = tbl->entry + i;
571 printf("Entry #%d:\n", i + 1);
572 printf(" Type = %u\n", ent->type);
573 printf(" Databits = %u\n", ent->databits);
574 printf(" Parity = %u\n", ent->parity);
575 printf(" Stopbits = %u\n", ent->stopbits);
576 printf(" PCI seg = %u\n", ent->pci_segment);
577 printf(" PCI bus = %u\n", ent->pci_bus);
578 printf(" PCI dev = %u\n", ent->pci_device);
579 printf(" PCI func = %u\n", ent->pci_function);
580 printf(" Interrupt = %u\n", ent->interrupt);
581 printf(" PCI flag = %u\n", ent->pci_flag);
582 printf(" Baudrate = %lu\n",
583 ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
585 printf(" Addr space= %u\n", gas->addr_space);
586 printf(" Bit width = %u\n", gas->bit_width);
587 printf(" Bit offset= %u\n", gas->bit_offset);
588 printf(" Address = 0x%016lx\n",
589 ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
590 printf(" PCI type = %u\n", ent->pci_devid);
591 printf(" PCI vndr = %u\n", ent->pci_vendor);
592 printf(" IRQ = %u\n", ent->irq);
593 printf(" PClock = %u\n", ent->pclock);
594 printf(" PCI iface = %u\n", ent->pci_interface);
600 COMMAND_SET(about, "about", "about the loader", command_about);
602 extern uint64_t _start_plabel[];
605 command_about(int argc, char *argv[])
607 EFI_LOADED_IMAGE *img;
609 printf("%s\n", bootprog_name);
610 printf("revision %s\n", bootprog_rev);
611 printf("built by %s\n", bootprog_maker);
612 printf("built on %s\n", bootprog_date);
616 BS->HandleProtocol(IH, &imgid, (VOID**)&img);
617 printf("image loaded at %p\n", img->ImageBase);
618 printf("entry at %#lx (%#lx)\n", _start_plabel[0], _start_plabel[1]);