xref: /netbsd-src/sys/arch/ia64/stand/ia64/efi/main.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: main.c,v 1.9 2014/03/25 18:35:33 christos 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 "bootstrap.h"
45 #include "efiboot.h"
46 
47 extern char bootprog_name[];
48 extern char bootprog_rev[];
49 
50 struct efi_devdesc	currdev;	/* our current device */
51 struct arch_switch	archsw;		/* MI/MD interface boundary */
52 
53 vaddr_t ia64_unwindtab;
54 vsize_t ia64_unwindtablen;
55 
56 extern u_int64_t	ia64_pal_entry;
57 
58 EFI_GUID acpi = ACPI_TABLE_GUID;
59 EFI_GUID acpi20 = ACPI_20_TABLE_GUID;
60 EFI_GUID devid = DEVICE_PATH_PROTOCOL;
61 EFI_GUID hcdp = HCDP_TABLE_GUID;
62 EFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
63 EFI_GUID mps = MPS_TABLE_GUID;
64 EFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
65 EFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
66 EFI_GUID smbios = SMBIOS_TABLE_GUID;
67 
68 static void
69 find_pal_proc(void)
70 {
71 	int i;
72 	struct sal_system_table *saltab = 0;
73 	static int sizes[6] = {
74 		48, 32, 16, 32, 16, 16
75 	};
76 	u_int8_t *p;
77 
78 	saltab = efi_get_table(&sal);
79 	if (saltab == NULL) {
80 		printf("Can't find SAL System Table\n");
81 		return;
82 	}
83 
84 	if (memcmp(saltab->sal_signature, "SST_", 4)) {
85 		printf("Bad signature for SAL System Table\n");
86 		return;
87 	}
88 
89 	p = (u_int8_t *) (saltab + 1);
90 	for (i = 0; i < saltab->sal_entry_count; i++) {
91 		if (*p == 0) {
92 			struct sal_entrypoint_descriptor *dp;
93 			dp = (struct sal_entrypoint_descriptor *) p;
94 			ia64_pal_entry = dp->sale_pal_proc;
95 			return;
96 		}
97 		p += sizes[*p];
98 	}
99 
100 	printf("Can't find PAL proc\n");
101 	return;
102 }
103 
104 EFI_STATUS
105 main(int argc, CHAR16 *argv[])
106 {
107 	EFI_LOADED_IMAGE *img;
108 	int i;
109 
110 	/*
111 	 * XXX Chicken-and-egg problem; we want to have console output
112 	 * early, but some console attributes may depend on reading from
113 	 * eg. the boot device, which we can't do yet.  We can use
114 	 * printf() etc. once this is done.
115 	 */
116 	cons_probe();
117 
118 	/*
119 	 * Initialise the block cache
120 	 */
121 	/* bcache_init(32, 512); */		/* 16k XXX tune this */
122 
123 	find_pal_proc();
124 
125 	efifs_dev_init();
126 
127         /*	efinet_init_driver(); XXX enable net boot. */
128 
129 	/* Get our loaded image protocol interface structure. */
130 	BS->HandleProtocol(IH, &imgid, (VOID**)&img);
131 
132 	printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
133 
134 	printf("\n");
135 	printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
136 
137 	i = efifs_get_unit(img->DeviceHandle);
138 	if (i >= 0) {
139 		currdev.d_dev = &devsw[0];		/* XXX disk */
140 		currdev.d_kind.efidisk.unit = i;
141 		/* XXX should be able to detect this, default to autoprobe */
142 		currdev.d_kind.efidisk.slice = -1;
143 		currdev.d_kind.efidisk.partition = 0;
144 		currdev.d_type = DEVT_DISK;
145 	} else {
146 		currdev.d_dev = &devsw[1];		/* XXX net */
147 		currdev.d_kind.netif.unit = 0;		/* XXX */
148 		currdev.d_type = DEVT_NET;
149 
150 	}
151 
152 
153 	/*
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...
161 	 */
162 	BS->SetWatchdogTimer(0, 0, 0, NULL);
163 
164 	env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
165 	    (ev_sethook_t *) efi_setcurrdev, env_nounset);
166 	env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
167 	    env_nounset);
168 
169 	setenv("LINES", "24", 1);	/* optional */
170 
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;
176 
177 	interact();			/* doesn't return */
178 
179 	return (EFI_SUCCESS);		/* keep compiler happy */
180 }
181 
182 COMMAND_SET(quit, "quit", "exit the loader", command_quit);
183 
184 static int
185 command_quit(int argc, char *argv[])
186 {
187 	exit(0);
188 	return (CMD_OK);
189 }
190 
191 COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
192 
193 static int
194 command_memmap(int argc, char *argv[])
195 {
196 	UINTN sz;
197 	EFI_MEMORY_DESCRIPTOR *map, *p;
198 	UINTN key, dsz;
199 	UINT32 dver;
200 	EFI_STATUS status;
201 	int i, ndesc;
202 	static char *types[] = {
203 	    "Reserved",
204 	    "LoaderCode",
205 	    "LoaderData",
206 	    "BootServicesCode",
207 	    "BootServicesData",
208 	    "RuntimeServicesCode",
209 	    "RuntimeServicesData",
210 	    "ConventionalMemory",
211 	    "UnusableMemory",
212 	    "ACPIReclaimMemory",
213 	    "ACPIMemoryNVS",
214 	    "MemoryMappedIO",
215 	    "MemoryMappedIOPortSpace",
216 	    "PalCode"
217 	};
218 
219 	sz = 0;
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");
223 		return CMD_ERROR;
224 	}
225 	map = alloc(sz);
226 	status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
227 	if (EFI_ERROR(status)) {
228 		printf("Can't read memory map\n");
229 		return CMD_ERROR;
230 	}
231 
232 	ndesc = sz / dsz;
233 	printf("%23s %12s %12s %8s %4s\n",
234 	       "Type", "Physical", "Virtual", "#Pages", "Attr");
235 
236 	for (i = 0, p = map; i < ndesc;
237 	     i++, p = NextMemoryDescriptor(p, dsz)) {
238 	    printf("%23s %012lx %012lx %08lx ",
239 		   types[p->Type],
240 		   p->PhysicalStart,
241 		   p->VirtualStart,
242 		   p->NumberOfPages);
243 	    if (p->Attribute & EFI_MEMORY_UC)
244 		printf("UC ");
245 	    if (p->Attribute & EFI_MEMORY_WC)
246 		printf("WC ");
247 	    if (p->Attribute & EFI_MEMORY_WT)
248 		printf("WT ");
249 	    if (p->Attribute & EFI_MEMORY_WB)
250 		printf("WB ");
251 	    if (p->Attribute & EFI_MEMORY_UCE)
252 		printf("UCE ");
253 	    if (p->Attribute & EFI_MEMORY_WP)
254 		printf("WP ");
255 	    if (p->Attribute & EFI_MEMORY_RP)
256 		printf("RP ");
257 	    if (p->Attribute & EFI_MEMORY_XP)
258 		printf("XP ");
259 	    if (p->Attribute & EFI_MEMORY_RUNTIME)
260 		printf("RUNTIME");
261 	    printf("\n");
262 	}
263 
264 	return CMD_OK;
265 }
266 
267 COMMAND_SET(configuration, "configuration",
268 	    "print configuration tables", command_configuration);
269 
270 static const char *
271 guid_to_string(EFI_GUID *guid)
272 {
273 	static char buf[40];
274 
275 	snprintf(buf, sizeof(buf),
276 	    "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
277 	    guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
278 	    guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
279 	    guid->Data4[5], guid->Data4[6], guid->Data4[7]);
280 	return (buf);
281 }
282 
283 static int
284 command_configuration(int argc, char *argv[])
285 {
286 	int i;
287 
288 	printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
289 	for (i = 0; i < ST->NumberOfTableEntries; i++) {
290 		EFI_GUID *guid;
291 
292 		printf("  ");
293 		guid = &ST->ConfigurationTable[i].VendorGuid;
294 		if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
295 			printf("MPS Table");
296 		else if (!memcmp(guid, &acpi, sizeof(EFI_GUID)))
297 			printf("ACPI Table");
298 		else if (!memcmp(guid, &acpi20, sizeof(EFI_GUID)))
299 			printf("ACPI 2.0 Table");
300 		else if (!memcmp(guid, &smbios, sizeof(EFI_GUID)))
301 			printf("SMBIOS Table");
302 		else if (!memcmp(guid, &sal, sizeof(EFI_GUID)))
303 			printf("SAL System Table");
304 		else if (!memcmp(guid, &hcdp, sizeof(EFI_GUID)))
305 			printf("DIG64 HCDP Table");
306 		else
307 			printf("Unknown Table (%s)", guid_to_string(guid));
308 		printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
309 	}
310 
311 	return CMD_OK;
312 }
313 
314 COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
315 
316 static int
317 command_sal(int argc, char *argv[])
318 {
319 	int i;
320 	struct sal_system_table *saltab = 0;
321 	static int sizes[6] = {
322 		48, 32, 16, 32, 16, 16
323 	};
324 	u_int8_t *p;
325 
326 	saltab = efi_get_table(&sal);
327 	if (saltab == NULL) {
328 		printf("Can't find SAL System Table\n");
329 		return CMD_ERROR;
330 	}
331 
332 	if (memcmp(saltab->sal_signature, "SST_", 4)) {
333 		printf("Bad signature for SAL System Table\n");
334 		return CMD_ERROR;
335 	}
336 
337 	printf("SAL Revision %x.%02x\n",
338 	       saltab->sal_rev[1],
339 	       saltab->sal_rev[0]);
340 	printf("SAL A Version %x.%02x\n",
341 	       saltab->sal_a_version[1],
342 	       saltab->sal_a_version[0]);
343 	printf("SAL B Version %x.%02x\n",
344 	       saltab->sal_b_version[1],
345 	       saltab->sal_b_version[0]);
346 
347 	p = (u_int8_t *) (saltab + 1);
348 	for (i = 0; i < saltab->sal_entry_count; i++) {
349 		printf("  Desc %d", *p);
350 		if (*p == 0) {
351 			struct sal_entrypoint_descriptor *dp;
352 			dp = (struct sal_entrypoint_descriptor *) p;
353 			printf("\n");
354 			printf("    PAL Proc at 0x%lx\n",
355 			       dp->sale_pal_proc);
356 			printf("    SAL Proc at 0x%lx\n",
357 			       dp->sale_sal_proc);
358 			printf("    SAL GP at 0x%lx\n",
359 			       dp->sale_sal_gp);
360 		} else if (*p == 1) {
361 			struct sal_memory_descriptor *dp;
362 			dp = (struct sal_memory_descriptor *) p;
363 			printf(" Type %d.%d, ",
364 			       dp->sale_memory_type[0],
365 			       dp->sale_memory_type[1]);
366 			printf("Address 0x%lx, ",
367 			       dp->sale_physical_address);
368 			printf("Length 0x%x\n",
369 			       dp->sale_length);
370 		} else if (*p == 5) {
371 			struct sal_ap_wakeup_descriptor *dp;
372 			dp = (struct sal_ap_wakeup_descriptor *) p;
373 			printf("\n");
374 			printf("    Mechanism %d\n", dp->sale_mechanism);
375 			printf("    Vector 0x%lx\n", dp->sale_vector);
376 		} else
377 			printf("\n");
378 
379 		p += sizes[*p];
380 	}
381 
382 	return CMD_OK;
383 }
384 
385 int
386 print_trs(int type)
387 {
388 	struct ia64_pal_result res;
389 	int i, maxtr;
390 	struct {
391 		pt_entry_t	pte;
392 		uint64_t	itir;
393 		uint64_t	ifa;
394 		struct ia64_rr	rr;
395 	} buf;
396 	static const char *psnames[] = {
397 		"1B",	"2B",	"4B",	"8B",
398 		"16B",	"32B",	"64B",	"128B",
399 		"256B",	"512B",	"1K",	"2K",
400 		"4K",	"8K",	"16K",	"32K",
401 		"64K",	"128K",	"256K",	"512K",
402 		"1M",	"2M",	"4M",	"8M",
403 		"16M",	"32M",	"64M",	"128M",
404 		"256M",	"512M",	"1G",	"2G"
405 	};
406 	static const char *manames[] = {
407 		"WB",	"bad",	"bad",	"bad",
408 		"UC",	"UCE",	"WC",	"NaT",
409 	};
410 
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");
414 		return CMD_ERROR;
415 	}
416 
417 	if (type == 0)
418 		maxtr = (res.pal_result[0] >> 40) & 0xff;
419 	else
420 		maxtr = (res.pal_result[0] >> 32) & 0xff;
421 
422 	printf("%d translation registers\n", maxtr);
423 
424 	pager_open();
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++) {
427 		char lbuf[128];
428 
429 		memset(&buf, 0, sizeof(buf));
430 		res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
431 					    (u_int64_t) &buf);
432 		if (res.pal_status != 0)
433 			break;
434 
435 		/* Only display valid translations */
436 		if ((buf.ifa & 1) == 0)
437 			continue;
438 
439 		if (!(res.pal_result[0] & 1))
440 			buf.pte &= ~PTE_AR_MASK;
441 		if (!(res.pal_result[0] & 2))
442 			buf.pte &= ~PTE_PL_MASK;
443 		if (!(res.pal_result[0] & 4))
444 			buf.pte &= ~PTE_DIRTY;
445 		if (!(res.pal_result[0] & 8))
446 			buf.pte &= ~PTE_MA_MASK;
447 		snprintf(lbuf, sizeof(lbuf),
448 		    "%03d %06x %013lx %013lx %4s %d  %d  %d  %d %d "
449 		    "%-3s %d %06x\n", i, buf.rr.rr_rid, buf.ifa >> 12,
450 		    (buf.pte & PTE_PPN_MASK) >> 12,
451 		    psnames[(buf.itir & ITIR_PS_MASK) >> 2],
452 		    (buf.pte & PTE_ED) ? 1 : 0,
453 		    (int)(buf.pte & PTE_AR_MASK) >> 9,
454 		    (int)(buf.pte & PTE_PL_MASK) >> 7,
455 		    (buf.pte & PTE_DIRTY) ? 1 : 0,
456 		    (buf.pte & PTE_ACCESSED) ? 1 : 0,
457 		    manames[(buf.pte & PTE_MA_MASK) >> 2],
458 		    (buf.pte & PTE_PRESENT) ? 1 : 0,
459 		    (int)((buf.itir & ITIR_KEY_MASK) >> 8));
460 		pager_output(lbuf);
461 	}
462 	pager_close();
463 
464 	if (res.pal_status != 0) {
465 		printf("Error while getting TR contents\n");
466 		return CMD_ERROR;
467 	}
468 	return CMD_OK;
469 }
470 
471 COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
472 
473 static int
474 command_itr(int argc, char *argv[])
475 {
476 	return print_trs(0);
477 }
478 
479 COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
480 
481 static int
482 command_dtr(int argc, char *argv[])
483 {
484 	return print_trs(1);
485 }
486 
487 COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
488 
489 static char *
490 hcdp_string(char *s, u_int len)
491 {
492 	static char buffer[256];
493 
494 	memcpy(buffer, s, len);
495 	buffer[len] = 0;
496 	return (buffer);
497 }
498 
499 static int
500 command_hcdp(int argc, char *argv[])
501 {
502 	struct dig64_hcdp_table *tbl;
503 	union dev_desc *desc;
504 	int i, m, n;
505 
506 	tbl = efi_get_table(&hcdp);
507 	if (tbl == NULL) {
508 		printf("No HCDP table present\n");
509 		return (CMD_OK);
510 	}
511 	if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
512 		printf("HCDP table has invalid signature\n");
513 		return (CMD_OK);
514 	}
515 	printf("HCDP table at 0x%lx\n", (u_long)tbl);
516 	printf("Signature  = %s\n", hcdp_string(tbl->signature, 4));
517 	printf("Length     = %u\n", tbl->length);
518 	printf("Revision   = %u\n", tbl->revision);
519 	printf("Checksum   = %u\n", tbl->checksum);
520 	printf("OEM Id     = %s\n", hcdp_string(tbl->oem_id, 6));
521 	printf("Table Id   = %s\n", hcdp_string(tbl->oem_tbl_id, 8));
522 	printf("OEM rev    = %u\n", tbl->oem_rev);
523 	printf("Creator Id = %s\n", hcdp_string(tbl->creator_id, 4));
524 	printf("Creator rev= %u\n", tbl->creator_rev);
525 	printf("Entries    = %u\n", tbl->entries);
526 	n = 0;
527 	m = tbl->length - sizeof(struct dig64_hcdp_table);
528 	i = 1;
529 	while (n < m) {
530 		printf("Entry #%d:\n", i);
531 		desc = (union dev_desc *)((char *)tbl->entry + n);
532 		printf("    Type      = %u\n", desc->type);
533 		if (desc->type == DIG64_ENTRYTYPE_TYPE0 ||
534 		    desc->type == DIG64_ENTRYTYPE_TYPE1) {
535 			struct dig64_hcdp_entry *ent = &desc->uart;
536 			struct dig64_gas *gas;
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) +
548 			    (u_long)ent->baud_low);
549 			gas = &ent->address;
550 			printf("    Addr space= %u\n", gas->addr_space);
551 			printf("    Bit width = %u\n", gas->bit_width);
552 			printf("    Bit offset= %u\n", gas->bit_offset);
553 			printf("    Address   = 0x%lx\n",
554 			    ((u_long)gas->addr_high << 32) +
555 			    (u_long)gas->addr_low);
556 			printf("    PCI type  = %u\n", ent->pci_devid);
557 			printf("    PCI vndr  = %u\n", ent->pci_vendor);
558 			printf("    IRQ       = %u\n", ent->irq);
559 			printf("    PClock    = %u\n", ent->pclock);
560 			printf("    PCI iface = %u\n", ent->pci_interface);
561 
562 			n += sizeof(struct dig64_hcdp_entry);
563 		} else {
564 			struct dig64_pcdp_entry *pcdp = &desc->pcdp;
565 
566 			if (tbl->revision < 3) {
567 				printf("PCDP not support\n");
568 				return (CMD_OK);
569 			}
570 
571 			printf("    Length    = %u\n", pcdp->length);
572 			printf("    Index EFI = %u\n", pcdp->index);
573 			printf("    Interconn = %u", pcdp->specs.type);
574 
575 			switch (pcdp->specs.type) {
576 			case DIG64_PCDP_SPEC_ACPI:
577 			{
578 				struct dig64_acpi_spec *acpi =
579 				    &pcdp->specs.acpi;
580 
581 				printf("(ACPI)\n");
582 				printf("    Length    = %u\n", acpi->length);
583 				printf("    ACPI_UID  = %x\n", acpi->uid);
584 				printf("    ACPI_HID  = %x\n", acpi->hid);
585 				printf("    ACPI GSI  = %x\n", acpi->acpi_gsi);
586 				printf("    MMIO_TRA  = %lx\n", acpi->mmio_tra);
587 				printf("    IOPort_TRA= %lx\n",
588 				    acpi->ioport_tra);
589 				printf("    Flags     = %x\n", acpi->flags);
590 				break;
591 			}
592 			case DIG64_PCDP_SPEC_PCI:
593 			{
594 				struct dig64_pci_spec *pci = &pcdp->specs.pci;
595 
596 				printf("(PCI)\n");
597 				printf("    Length    = %u\n", pci->length);
598 				printf("    Seg GrpNum= %u\n", pci->sgn);
599 				printf("    Bus       = %u\n", pci->bus);
600 				printf("    Device    = %u\n", pci->device);
601 				printf("    Function  = %u\n", pci->function);
602 				printf("    Device ID = %u\n", pci->device_id);
603 				printf("    Vendor ID = %u\n", pci->vendor_id);
604 				printf("    ACPI GSI  = %x\n", pci->acpi_gsi);
605 				printf("    MMIO_TRA  = %lx\n", pci->mmio_tra);
606 				printf("    IOPort_TRA= %lx\n",
607 				    pci->ioport_tra);
608 				printf("    Flags     = %x\n", pci->flags);
609 				break;
610 			}
611 			}
612 
613 			n += pcdp->length;
614 		}
615 	}
616 	printf("<EOT>\n");
617 	return (CMD_OK);
618 }
619 
620 struct bootblk_command commands[] = {
621         COMMON_COMMANDS,
622         { "quit",       "exit the loader",      command_quit },
623         { "memmap",	"print memory map",	command_memmap },
624         { "configuration", "print configuration tables", command_configuration },
625         { "sal",	"print SAL System Table", command_sal },
626         { "itr",	"print instruction TRs", command_itr },
627         { "dtr",	"print data TRs",	command_dtr },
628         { "hcdp",	"Dump HCDP info",	command_hcdp },
629         { NULL,         NULL,                   NULL         },
630 };
631