xref: /netbsd-src/sys/arch/ia64/stand/ia64/efi/main.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /*	$NetBSD: main.c,v 1.12 2018/08/18 06:52:57 kre Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
5  * Copyright (c) 1998,2000 Doug Rabson <dfr@freebsd.org>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 #include <sys/cdefs.h>
31 
32 #include <lib/libsa/stand.h>
33 #include <lib/libsa/loadfile.h>
34 
35 #include <machine/sal.h>
36 #include <machine/pal.h>
37 #include <machine/pte.h>
38 #include <machine/dig64.h>
39 
40 #include <efi.h>
41 #include <efilib.h>
42 #include <efifsdev.h>
43 
44 #include <machine/efilib.h>
45 
46 #include "bootstrap.h"
47 #include "efiboot.h"
48 
49 extern char bootprog_name[];
50 extern char bootprog_rev[];
51 
52 struct efi_devdesc	currdev;	/* our current device */
53 struct arch_switch	archsw;		/* MI/MD interface boundary */
54 
55 vaddr_t ia64_unwindtab;
56 vsize_t ia64_unwindtablen;
57 
58 extern u_int64_t	ia64_pal_entry;
59 
60 EFI_GUID acpi = ACPI_TABLE_GUID;
61 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
62 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
63 EFI_GUID hcdp = HCDP_TABLE_GUID;
64 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
65 EFI_GUID mps = MPS_TABLE_GUID;
66 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID;
67 EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
68 EFI_GUID smbios = SMBIOS_TABLE_GUID;
69 
70 static void
71 find_pal_proc(void)
72 {
73 	int i;
74 	struct sal_system_table *saltab = 0;
75 	static int sizes[6] = {
76 		48, 32, 16, 32, 16, 16
77 	};
78 	u_int8_t *p;
79 
80 	saltab = efi_get_table(&sal);
81 	if (saltab == NULL) {
82 		printf("Can't find SAL System Table\n");
83 		return;
84 	}
85 
86 	if (memcmp(saltab->sal_signature, "SST_", 4)) {
87 		printf("Bad signature for SAL System Table\n");
88 		return;
89 	}
90 
91 	p = (u_int8_t *) (saltab + 1);
92 	for (i = 0; i < saltab->sal_entry_count; i++) {
93 		if (*p == 0) {
94 			struct sal_entrypoint_descriptor *dp;
95 			dp = (struct sal_entrypoint_descriptor *) p;
96 			ia64_pal_entry = dp->sale_pal_proc;
97 			return;
98 		}
99 		p += sizes[*p];
100 	}
101 
102 	printf("Can't find PAL proc\n");
103 	return;
104 }
105 
106 EFI_STATUS
107 main(int argc, CHAR16 *argv[])
108 {
109 	EFI_LOADED_IMAGE *img;
110 	int i;
111 
112 	/*
113 	 * XXX Chicken-and-egg problem; we want to have console output
114 	 * early, but some console attributes may depend on reading from
115 	 * eg. the boot device, which we can't do yet.  We can use
116 	 * printf() etc. once this is done.
117 	 */
118 	cons_probe();
119 
120 	/*
121 	 * Initialise the block cache
122 	 */
123 	/* bcache_init(32, 512); */		/* 16k XXX tune this */
124 
125 	find_pal_proc();
126 
127 	efifs_dev_init();
128 
129 	efinet_init_driver();
130 
131 	/* Get our loaded image protocol interface structure. */
132 	BS->HandleProtocol(IH, &imgid, (VOID**)&img);
133 
134 	printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
135 
136 	printf("\n");
137 	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
138 
139 	i = efifs_get_unit(img->DeviceHandle);
140 	if (i >= 0) {
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;
146 		currdev.d_type = DEVT_DISK;
147 	} else {
148 		currdev.d_dev = &devsw[1];		/* XXX net */
149 		currdev.d_kind.netif.unit = 0;		/* XXX */
150 		currdev.d_type = DEVT_NET;
151 
152 		/* XXX overwrite disk ops with nfs ops */
153 		memcpy(&file_system[0], &file_system[1], sizeof(struct fs_ops));
154 	}
155 
156 
157 	/*
158 	 * Disable the watchdog timer. By default the boot manager sets
159 	 * the timer to 5 minutes before invoking a boot option. If we
160 	 * want to return to the boot manager, we have to disable the
161 	 * watchdog timer and since we're an interactive program, we don't
162 	 * want to wait until the user types "quit". The timer may have
163 	 * fired by then. We don't care if this fails. It does not prevent
164 	 * normal functioning in any way...
165 	 */
166 	BS->SetWatchdogTimer(0, 0, 0, NULL);
167 
168 	env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
169 	    (ev_sethook_t *) efi_setcurrdev, env_nounset);
170 	env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
171 	    env_nounset);
172 
173 	setenv("LINES", "24", 1);	/* optional */
174 
175 	archsw.arch_autoload = efi_autoload;
176 	archsw.arch_getdev = efi_getdev;
177 	archsw.arch_copyin = efi_copyin;
178 	archsw.arch_copyout = efi_copyout;
179 	archsw.arch_readin = efi_readin;
180 
181 	interact();			/* doesn't return */
182 
183 	return (EFI_SUCCESS);		/* keep compiler happy */
184 }
185 
186 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
187 
188 static int
189 command_quit(int argc, char *argv[])
190 {
191 	exit(0);
192 	return (CMD_OK);
193 }
194 
195 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
196 
197 static int
198 command_memmap(int argc, char *argv[])
199 {
200 	UINTN sz;
201 	EFI_MEMORY_DESCRIPTOR *map, *p;
202 	UINTN key, dsz;
203 	UINT32 dver;
204 	EFI_STATUS status;
205 	int i, ndesc;
206 	static char *types[] = {
207 	    "Reserved",
208 	    "LoaderCode",
209 	    "LoaderData",
210 	    "BootServicesCode",
211 	    "BootServicesData",
212 	    "RuntimeServicesCode",
213 	    "RuntimeServicesData",
214 	    "ConventionalMemory",
215 	    "UnusableMemory",
216 	    "ACPIReclaimMemory",
217 	    "ACPIMemoryNVS",
218 	    "MemoryMappedIO",
219 	    "MemoryMappedIOPortSpace",
220 	    "PalCode"
221 	};
222 
223 	sz = 0;
224 	status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
225 	if (status != EFI_BUFFER_TOO_SMALL) {
226 		printf("Can't determine memory map size\n");
227 		return CMD_ERROR;
228 	}
229 	map = alloc(sz);
230 	status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
231 	if (EFI_ERROR(status)) {
232 		printf("Can't read memory map\n");
233 		return CMD_ERROR;
234 	}
235 
236 	ndesc = sz / dsz;
237 	printf("%23s %12s %12s %8s %4s\n",
238 	       "Type", "Physical", "Virtual", "#Pages", "Attr");
239 
240 	for (i = 0, p = map; i < ndesc;
241 	     i++, p = NextMemoryDescriptor(p, dsz)) {
242 	    printf("%23s %012lx %012lx %08lx ",
243 		   types[p->Type],
244 		   p->PhysicalStart,
245 		   p->VirtualStart,
246 		   p->NumberOfPages);
247 	    if (p->Attribute & EFI_MEMORY_UC)
248 		printf("UC ");
249 	    if (p->Attribute & EFI_MEMORY_WC)
250 		printf("WC ");
251 	    if (p->Attribute & EFI_MEMORY_WT)
252 		printf("WT ");
253 	    if (p->Attribute & EFI_MEMORY_WB)
254 		printf("WB ");
255 	    if (p->Attribute & EFI_MEMORY_UCE)
256 		printf("UCE ");
257 	    if (p->Attribute & EFI_MEMORY_WP)
258 		printf("WP ");
259 	    if (p->Attribute & EFI_MEMORY_RP)
260 		printf("RP ");
261 	    if (p->Attribute & EFI_MEMORY_XP)
262 		printf("XP ");
263 	    if (p->Attribute & EFI_MEMORY_RUNTIME)
264 		printf("RUNTIME");
265 	    printf("\n");
266 	}
267 
268 	return CMD_OK;
269 }
270 
271 COMMAND_SET(configuration, "configuration",
272 	    "print configuration tables", command_configuration);
273 
274 static const char *
275 guid_to_string(EFI_GUID *guid)
276 {
277 	static char buf[40];
278 
279 	snprintf(buf, sizeof(buf),
280 	    "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
281 	    guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
282 	    guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
283 	    guid->Data4[5], guid->Data4[6], guid->Data4[7]);
284 	return (buf);
285 }
286 
287 static int
288 command_configuration(int argc, char *argv[])
289 {
290 	int i;
291 
292 	printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
293 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
294 		EFI_GUID *guid;
295 
296 		printf("  ");
297 		guid = &ST->ConfigurationTable[i].VendorGuid;
298 		if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
299 			printf("MPS Table");
300 		else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
301 			printf("ACPI Table");
302 		else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
303 			printf("ACPI 2.0 Table");
304 		else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
305 			printf("SMBIOS Table");
306 		else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
307 			printf("SAL System Table");
308 		else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
309 			printf("DIG64 HCDP Table");
310 		else
311 			printf("Unknown Table (%s)", guid_to_string(guid));
312 		printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
313 	}
314 
315 	return CMD_OK;
316 }
317 
318 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
319 
320 static int
321 command_sal(int argc, char *argv[])
322 {
323 	int i;
324 	struct sal_system_table *saltab = 0;
325 	static int sizes[6] = {
326 		48, 32, 16, 32, 16, 16
327 	};
328 	u_int8_t *p;
329 
330 	saltab = efi_get_table(&sal);
331 	if (saltab == NULL) {
332 		printf("Can't find SAL System Table\n");
333 		return CMD_ERROR;
334 	}
335 
336 	if (memcmp(saltab->sal_signature, "SST_", 4)) {
337 		printf("Bad signature for SAL System Table\n");
338 		return CMD_ERROR;
339 	}
340 
341 	printf("SAL Revision %x.%02x\n",
342 	       saltab->sal_rev[1],
343 	       saltab->sal_rev[0]);
344 	printf("SAL A Version %x.%02x\n",
345 	       saltab->sal_a_version[1],
346 	       saltab->sal_a_version[0]);
347 	printf("SAL B Version %x.%02x\n",
348 	       saltab->sal_b_version[1],
349 	       saltab->sal_b_version[0]);
350 
351 	p = (u_int8_t *) (saltab + 1);
352 	for (i = 0; i < saltab->sal_entry_count; i++) {
353 		printf("  Desc %d", *p);
354 		if (*p == 0) {
355 			struct sal_entrypoint_descriptor *dp;
356 			dp = (struct sal_entrypoint_descriptor *) p;
357 			printf("\n");
358 			printf("    PAL Proc at 0x%lx\n",
359 			       dp->sale_pal_proc);
360 			printf("    SAL Proc at 0x%lx\n",
361 			       dp->sale_sal_proc);
362 			printf("    SAL GP at 0x%lx\n",
363 			       dp->sale_sal_gp);
364 		} else if (*p == 1) {
365 			struct sal_memory_descriptor *dp;
366 			dp = (struct sal_memory_descriptor *) p;
367 			printf(" Type %d.%d, ",
368 			       dp->sale_memory_type[0],
369 			       dp->sale_memory_type[1]);
370 			printf("Address 0x%lx, ",
371 			       dp->sale_physical_address);
372 			printf("Length 0x%x\n",
373 			       dp->sale_length);
374 		} else if (*p == 5) {
375 			struct sal_ap_wakeup_descriptor *dp;
376 			dp = (struct sal_ap_wakeup_descriptor *) p;
377 			printf("\n");
378 			printf("    Mechanism %d\n", dp->sale_mechanism);
379 			printf("    Vector 0x%lx\n", dp->sale_vector);
380 		} else
381 			printf("\n");
382 
383 		p += sizes[*p];
384 	}
385 
386 	return CMD_OK;
387 }
388 
389 int
390 print_trs(int type)
391 {
392 	struct ia64_pal_result res;
393 	int i, maxtr;
394 	struct {
395 		pt_entry_t	pte;
396 		uint64_t	itir;
397 		uint64_t	ifa;
398 		struct ia64_rr	rr;
399 	} buf;
400 	static const char *psnames[] = {
401 		"1B",	"2B",	"4B",	"8B",
402 		"16B",	"32B",	"64B",	"128B",
403 		"256B",	"512B",	"1K",	"2K",
404 		"4K",	"8K",	"16K",	"32K",
405 		"64K",	"128K",	"256K",	"512K",
406 		"1M",	"2M",	"4M",	"8M",
407 		"16M",	"32M",	"64M",	"128M",
408 		"256M",	"512M",	"1G",	"2G"
409 	};
410 	static const char *manames[] = {
411 		"WB",	"bad",	"bad",	"bad",
412 		"UC",	"UCE",	"WC",	"NaT",
413 	};
414 
415 	res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0);
416 	if (res.pal_status != 0) {
417 		printf("Can't get VM summary\n");
418 		return CMD_ERROR;
419 	}
420 
421 	if (type == 0)
422 		maxtr = (res.pal_result[0] >> 40) & 0xff;
423 	else
424 		maxtr = (res.pal_result[0] >> 32) & 0xff;
425 
426 	printf("%d translation registers\n", maxtr);
427 
428 	pager_open();
429 	pager_output("TR# RID    Virtual Page  Physical Page PgSz ED AR PL D A MA  P KEY\n");
430 	for (i = 0; i <= maxtr; i++) {
431 		char lbuf[128];
432 
433 		memset(&buf, 0, sizeof(buf));
434 		res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
435 					    (u_int64_t) &buf);
436 		if (res.pal_status != 0)
437 			break;
438 
439 		/* Only display valid translations */
440 		if ((buf.ifa & 1) == 0)
441 			continue;
442 
443 		if (!(res.pal_result[0] & 1))
444 			buf.pte &= ~PTE_AR_MASK;
445 		if (!(res.pal_result[0] & 2))
446 			buf.pte &= ~PTE_PL_MASK;
447 		if (!(res.pal_result[0] & 4))
448 			buf.pte &= ~PTE_DIRTY;
449 		if (!(res.pal_result[0] & 8))
450 			buf.pte &= ~PTE_MA_MASK;
451 		snprintf(lbuf, sizeof(lbuf),
452 		    "%03d %06x %013lx %013lx %4s %d  %d  %d  %d %d "
453 		    "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
454 		    (buf.pte & PTE_PPN_MASK) >> 12,
455 		    psnames[(buf.itir & ITIR_PS_MASK) >> 2],
456 		    (buf.pte & PTE_ED) ? 1 : 0,
457 		    (int)(buf.pte & PTE_AR_MASK) >> 9,
458 		    (int)(buf.pte & PTE_PL_MASK) >> 7,
459 		    (buf.pte & PTE_DIRTY) ? 1 : 0,
460 		    (buf.pte & PTE_ACCESSED) ? 1 : 0,
461 		    manames[(buf.pte & PTE_MA_MASK) >> 2],
462 		    (buf.pte & PTE_PRESENT) ? 1 : 0,
463 		    (int)((buf.itir & ITIR_KEY_MASK) >> 8));
464 		pager_output(lbuf);
465 	}
466 	pager_close();
467 
468 	if (res.pal_status != 0) {
469 		printf("Error while getting TR contents\n");
470 		return CMD_ERROR;
471 	}
472 	return CMD_OK;
473 }
474 
475 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
476 
477 static int
478 command_itr(int argc, char *argv[])
479 {
480 	return print_trs(0);
481 }
482 
483 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
484 
485 static int
486 command_dtr(int argc, char *argv[])
487 {
488 	return print_trs(1);
489 }
490 
491 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
492 
493 static char *
494 hcdp_string(char *s, u_int len)
495 {
496 	static char buffer[256];
497 
498 	memcpy(buffer, s, len);
499 	buffer[len] = 0;
500 	return (buffer);
501 }
502 
503 static int
504 command_hcdp(int argc, char *argv[])
505 {
506 	struct dig64_hcdp_table *tbl;
507 	union dev_desc *desc;
508 	int i, m, n;
509 
510 	tbl = efi_get_table(&hcdp);
511 	if (tbl == NULL) {
512 		printf("No HCDP table present\n");
513 		return (CMD_OK);
514 	}
515 	if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
516 		printf("HCDP table has invalid signature\n");
517 		return (CMD_OK);
518 	}
519 	printf("HCDP table at 0x%lx\n", (u_long)tbl);
520 	printf("Signature  = %s\n", hcdp_string(tbl->signature, 4));
521 	printf("Length     = %u\n", tbl->length);
522 	printf("Revision   = %u\n", tbl->revision);
523 	printf("Checksum   = %u\n", tbl->checksum);
524 	printf("OEM Id     = %s\n", hcdp_string(tbl->oem_id, 6));
525 	printf("Table Id   = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
526 	printf("OEM rev    = %u\n", tbl->oem_rev);
527 	printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
528 	printf("Creator rev= %u\n", tbl->creator_rev);
529 	printf("Entries    = %u\n", tbl->entries);
530 	n = 0;
531 	m = tbl->length - sizeof(struct dig64_hcdp_table);
532 	i = 1;
533 	while (n < m) {
534 		printf("Entry #%d:\n", i);
535 		desc = (union dev_desc *)((char *)tbl->entry + n);
536 		printf("    Type      = %u\n", desc->type);
537 		if (desc->type == DIG64_ENTRYTYPE_TYPE0 ||
538 		    desc->type == DIG64_ENTRYTYPE_TYPE1) {
539 			struct dig64_hcdp_entry *ent = &desc->uart;
540 			struct dig64_gas *gas;
541 			printf("    Databits  = %u\n", ent->databits);
542 			printf("    Parity    = %u\n", ent->parity);
543 			printf("    Stopbits  = %u\n", ent->stopbits);
544 			printf("    PCI seg   = %u\n", ent->pci_segment);
545 			printf("    PCI bus   = %u\n", ent->pci_bus);
546 			printf("    PCI dev   = %u\n", ent->pci_device);
547 			printf("    PCI func  = %u\n", ent->pci_function);
548 			printf("    Interrupt = %u\n", ent->interrupt);
549 			printf("    PCI flag  = %u\n", ent->pci_flag);
550 			printf("    Baudrate  = %lu\n",
551 			    ((u_long)ent->baud_high << 32) +
552 			    (u_long)ent->baud_low);
553 			gas = &ent->address;
554 			printf("    Addr space= %u\n", gas->addr_space);
555 			printf("    Bit width = %u\n", gas->bit_width);
556 			printf("    Bit offset= %u\n", gas->bit_offset);
557 			printf("    Address   = 0x%lx\n",
558 			    ((u_long)gas->addr_high << 32) +
559 			    (u_long)gas->addr_low);
560 			printf("    PCI type  = %u\n", ent->pci_devid);
561 			printf("    PCI vndr  = %u\n", ent->pci_vendor);
562 			printf("    IRQ       = %u\n", ent->irq);
563 			printf("    PClock    = %u\n", ent->pclock);
564 			printf("    PCI iface = %u\n", ent->pci_interface);
565 
566 			n += sizeof(struct dig64_hcdp_entry);
567 		} else {
568 			struct dig64_pcdp_entry *pcdp = &desc->pcdp;
569 
570 			if (tbl->revision < 3) {
571 				printf("PCDP not support\n");
572 				return (CMD_OK);
573 			}
574 
575 			printf("    Length    = %u\n", pcdp->length);
576 			printf("    Index EFI = %u\n", pcdp->index);
577 			printf("    Interconn = %u", pcdp->specs.type);
578 
579 			switch (pcdp->specs.type) {
580 			case DIG64_PCDP_SPEC_ACPI:
581 			{
582 				struct dig64_acpi_spec *acpi =
583 				    &pcdp->specs.acpi;
584 
585 				printf("(ACPI)\n");
586 				printf("    Length    = %u\n", acpi->length);
587 				printf("    ACPI_UID  = %x\n", acpi->uid);
588 				printf("    ACPI_HID  = %x\n", acpi->hid);
589 				printf("    ACPI GSI  = %x\n", acpi->acpi_gsi);
590 				printf("    MMIO_TRA  = %lx\n", acpi->mmio_tra);
591 				printf("    IOPort_TRA= %lx\n",
592 				    acpi->ioport_tra);
593 				printf("    Flags     = %x\n", acpi->flags);
594 				break;
595 			}
596 			case DIG64_PCDP_SPEC_PCI:
597 			{
598 				struct dig64_pci_spec *pci = &pcdp->specs.pci;
599 
600 				printf("(PCI)\n");
601 				printf("    Length    = %u\n", pci->length);
602 				printf("    Seg GrpNum= %u\n", pci->sgn);
603 				printf("    Bus       = %u\n", pci->bus);
604 				printf("    Device    = %u\n", pci->device);
605 				printf("    Function  = %u\n", pci->function);
606 				printf("    Device ID = %u\n", pci->device_id);
607 				printf("    Vendor ID = %u\n", pci->vendor_id);
608 				printf("    ACPI GSI  = %x\n", pci->acpi_gsi);
609 				printf("    MMIO_TRA  = %lx\n", pci->mmio_tra);
610 				printf("    IOPort_TRA= %lx\n",
611 				    pci->ioport_tra);
612 				printf("    Flags     = %x\n", pci->flags);
613 				break;
614 			}
615 			}
616 
617 			n += pcdp->length;
618 		}
619 	}
620 	printf("<EOT>\n");
621 	return (CMD_OK);
622 }
623 
624 struct bootblk_command commands[] = {
625         COMMON_COMMANDS,
626         { "quit",       "exit the loader",      command_quit },
627         { "memmap",	"print memory map",	command_memmap },
628         { "configuration", "print configuration tables", command_configuration },
629         { "sal",	"print SAL System Table", command_sal },
630         { "itr",	"print instruction TRs", command_itr },
631         { "dtr",	"print data TRs",	command_dtr },
632         { "hcdp",	"Dump HCDP info",	command_hcdp },
633         { NULL,         NULL,                   NULL         },
634 };
635