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>
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;
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",
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 & 1) == 0)
438 if (!(res.pal_result[0] & 1))
439 buf.pte &= ~PTE_AR_MASK;
440 if (!(res.pal_result[0] & 2))
441 buf.pte &= ~PTE_PL_MASK;
442 if (!(res.pal_result[0] & 4))
443 buf.pte &= ~PTE_DIRTY;
444 if (!(res.pal_result[0] & 8))
445 buf.pte &= ~PTE_MA_MASK;
446 sprintf(lbuf, "%03d %06x %013lx %013lx %4s %d %d %d %d %d "
447 "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
448 (buf.pte & PTE_PPN_MASK) >> 12,
449 psnames[(buf.itir & ITIR_PS_MASK) >> 2],
450 (buf.pte & PTE_ED) ? 1 : 0,
451 (int)(buf.pte & PTE_AR_MASK) >> 9,
452 (int)(buf.pte & PTE_PL_MASK) >> 7,
453 (buf.pte & PTE_DIRTY) ? 1 : 0,
454 (buf.pte & PTE_ACCESSED) ? 1 : 0,
455 manames[(buf.pte & PTE_MA_MASK) >> 2],
456 (buf.pte & PTE_PRESENT) ? 1 : 0,
457 (int)((buf.itir & ITIR_KEY_MASK) >> 8));
462 if (res.pal_status != 0) {
463 printf("Error while getting TR contents\n");
469 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
472 command_itr(int argc, char *argv[])
477 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
480 command_dtr(int argc, char *argv[])
485 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
488 hcdp_string(char *s, u_int len)
490 static char buffer[256];
492 memcpy(buffer, s, len);
498 command_hcdp(int argc, char *argv[])
500 struct dig64_hcdp_table *tbl;
501 struct dig64_hcdp_entry *ent;
502 struct dig64_gas *gas;
505 tbl = efi_get_table(&hcdp);
507 printf("No HCDP table present\n");
510 if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
511 printf("HCDP table has invalid signature\n");
514 if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
515 printf("HCDP table too short\n");
518 printf("HCDP table at 0x%016lx\n", (u_long)tbl);
519 printf("Signature = %s\n", hcdp_string(tbl->signature, 4));
520 printf("Length = %u\n", tbl->length);
521 printf("Revision = %u\n", tbl->revision);
522 printf("Checksum = %u\n", tbl->checksum);
523 printf("OEM Id = %s\n", hcdp_string(tbl->oem_id, 6));
524 printf("Table Id = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
525 printf("OEM rev = %u\n", tbl->oem_rev);
526 printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
527 printf("Creator rev= %u\n", tbl->creator_rev);
528 printf("Entries = %u\n", tbl->entries);
529 for (i = 0; i < tbl->entries; i++) {
530 ent = tbl->entry + i;
531 printf("Entry #%d:\n", i + 1);
532 printf(" Type = %u\n", ent->type);
533 printf(" Databits = %u\n", ent->databits);
534 printf(" Parity = %u\n", ent->parity);
535 printf(" Stopbits = %u\n", ent->stopbits);
536 printf(" PCI seg = %u\n", ent->pci_segment);
537 printf(" PCI bus = %u\n", ent->pci_bus);
538 printf(" PCI dev = %u\n", ent->pci_device);
539 printf(" PCI func = %u\n", ent->pci_function);
540 printf(" Interrupt = %u\n", ent->interrupt);
541 printf(" PCI flag = %u\n", ent->pci_flag);
542 printf(" Baudrate = %lu\n",
543 ((u_long)ent->baud_high << 32) + (u_long)ent->baud_low);
545 printf(" Addr space= %u\n", gas->addr_space);
546 printf(" Bit width = %u\n", gas->bit_width);
547 printf(" Bit offset= %u\n", gas->bit_offset);
548 printf(" Address = 0x%016lx\n",
549 ((u_long)gas->addr_high << 32) + (u_long)gas->addr_low);
550 printf(" PCI type = %u\n", ent->pci_devid);
551 printf(" PCI vndr = %u\n", ent->pci_vendor);
552 printf(" IRQ = %u\n", ent->irq);
553 printf(" PClock = %u\n", ent->pclock);
554 printf(" PCI iface = %u\n", ent->pci_interface);