Home | History | Annotate | Line # | Download | only in efi
      1 /*	$NetBSD: main.c,v 1.12 2018/08/18 06:52:57 kre Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 Michael Smith <msmith (at) freebsd.org>
      5  * Copyright (c) 1998,2000 Doug Rabson <dfr (at) 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