1191783Srmacklem/*-
2191783Srmacklem * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3191783Srmacklem * Copyright (c) 1998,2000 Doug Rabson <dfr@freebsd.org>
4191783Srmacklem * All rights reserved.
5191783Srmacklem *
6191783Srmacklem * Redistribution and use in source and binary forms, with or without
7191783Srmacklem * modification, are permitted provided that the following conditions
8191783Srmacklem * are met:
9191783Srmacklem * 1. Redistributions of source code must retain the above copyright
10191783Srmacklem *    notice, this list of conditions and the following disclaimer.
11191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright
12191783Srmacklem *    notice, this list of conditions and the following disclaimer in the
13191783Srmacklem *    documentation and/or other materials provided with the distribution.
14191783Srmacklem *
15191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18191783Srmacklem * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25191783Srmacklem * SUCH DAMAGE.
26191783Srmacklem */
27191783Srmacklem
28191783Srmacklem#include <sys/cdefs.h>
29191783Srmacklem__FBSDID("$FreeBSD$");
30191783Srmacklem
31191783Srmacklem#include <stand.h>
32191783Srmacklem#include <string.h>
33191783Srmacklem#include <setjmp.h>
34191783Srmacklem#include <machine/sal.h>
35191783Srmacklem#include <machine/pal.h>
36191783Srmacklem#include <machine/pte.h>
37191783Srmacklem#include <machine/dig64.h>
38191783Srmacklem
39191783Srmacklem#include <efi.h>
40191783Srmacklem#include <efilib.h>
41191783Srmacklem
42191783Srmacklem#include <libia64.h>
43191783Srmacklem
44191783Srmacklem/* DIG64 Headless Console & Debug Port Table. */
45191783Srmacklem#define	HCDP_TABLE_GUID		\
46191783Srmacklem    {0xf951938d,0x620b,0x42ef,{0x82,0x79,0xa8,0x4b,0x79,0x61,0x78,0x98}}
47191783Srmacklem
48244042Srmacklemextern char bootprog_name[];
49191783Srmacklemextern char bootprog_rev[];
50191783Srmacklemextern char bootprog_date[];
51191783Srmacklemextern char bootprog_maker[];
52191783Srmacklem
53191783Srmacklemstruct arch_switch archsw;	/* MI/MD interface boundary */
54244042Srmacklem
55191783Srmacklemextern u_int64_t	ia64_pal_entry;
56191783Srmacklem
57191783SrmacklemEFI_GUID acpi = ACPI_TABLE_GUID;
58191783SrmacklemEFI_GUID acpi20 = ACPI_20_TABLE_GUID;
59191783SrmacklemEFI_GUID devid = DEVICE_PATH_PROTOCOL;
60191783SrmacklemEFI_GUID hcdp = HCDP_TABLE_GUID;
61191783SrmacklemEFI_GUID imgid = LOADED_IMAGE_PROTOCOL;
62191783SrmacklemEFI_GUID mps = MPS_TABLE_GUID;
63191783SrmacklemEFI_GUID netid = EFI_SIMPLE_NETWORK_PROTOCOL;
64191783SrmacklemEFI_GUID sal = SAL_SYSTEM_TABLE_GUID;
65191783SrmacklemEFI_GUID smbios = SMBIOS_TABLE_GUID;
66191783Srmacklem
67192121Srmacklemstatic void
68191783Srmacklemfind_pal_proc(void)
69191783Srmacklem{
70191783Srmacklem	int i;
71191783Srmacklem	struct sal_system_table *saltab = 0;
72191783Srmacklem	static int sizes[6] = {
73191783Srmacklem		48, 32, 16, 32, 16, 16
74191783Srmacklem	};
75191783Srmacklem	u_int8_t *p;
76191783Srmacklem
77191783Srmacklem	saltab = efi_get_table(&sal);
78191783Srmacklem	if (saltab == NULL) {
79191783Srmacklem		printf("Can't find SAL System Table\n");
80191783Srmacklem		return;
81191783Srmacklem	}
82191783Srmacklem
83191783Srmacklem	if (memcmp(saltab->sal_signature, "SST_", 4)) {
84191783Srmacklem		printf("Bad signature for SAL System Table\n");
85191783Srmacklem		return;
86249592Sken	}
87191783Srmacklem
88191783Srmacklem	p = (u_int8_t *) (saltab + 1);
89191783Srmacklem	for (i = 0; i < saltab->sal_entry_count; i++) {
90191783Srmacklem		if (*p == 0) {
91191783Srmacklem			struct sal_entrypoint_descriptor *dp;
92191783Srmacklem			dp = (struct sal_entrypoint_descriptor *) p;
93191783Srmacklem			ia64_pal_entry = dp->sale_pal_proc;
94244042Srmacklem			return;
95191783Srmacklem		}
96192121Srmacklem		p += sizes[*p];
97191783Srmacklem	}
98191783Srmacklem
99191783Srmacklem	printf("Can't find PAL proc\n");
100191783Srmacklem	return;
101191783Srmacklem}
102192121Srmacklem
103192121Srmacklemstatic int
104191783Srmacklemusc2cmp(CHAR16 *s1, CHAR16 *s2)
105191783Srmacklem{
106191783Srmacklem
107191783Srmacklem	while (*s1 == *s2++) {
108191783Srmacklem		if (*s1++ == 0)
109191783Srmacklem			return (0);
110191783Srmacklem	}
111191783Srmacklem	return (*s1 - *(s2 - 1));
112191783Srmacklem}
113191783Srmacklem
114191783Srmacklemstatic char *
115191783Srmacklemget_dev_option(int argc, CHAR16 *argv[])
116191783Srmacklem{
117191783Srmacklem	static char dev[32];
118191783Srmacklem	CHAR16 *arg;
119191783Srmacklem	char *devp;
120191783Srmacklem	int i, j;
121191783Srmacklem
122191783Srmacklem	devp = NULL;
123191783Srmacklem	for (i = 0; i < argc; i++) {
124191783Srmacklem		if (usc2cmp(argv[i], L"-dev") == 0 && i < argc - 1) {
125191783Srmacklem			arg = argv[i + 1];
126191783Srmacklem			j = 0;
127191783Srmacklem			while (j < sizeof(dev) && *arg != 0)
128191783Srmacklem				dev[j++] = *arg++;
129191783Srmacklem			if (j == sizeof(dev))
130191783Srmacklem				j--;
131191783Srmacklem			dev[j] = '\0';
132191783Srmacklem			devp = dev;
133191783Srmacklem			break;
134191783Srmacklem		}
135191783Srmacklem	}
136191783Srmacklem
137191783Srmacklem	return (devp);
138244042Srmacklem}
139191783Srmacklem
140244042SrmacklemEFI_STATUS
141244042Srmacklemmain(int argc, CHAR16 *argv[])
142191783Srmacklem{
143191783Srmacklem	struct devdesc currdev;
144191783Srmacklem	EFI_LOADED_IMAGE *img;
145191783Srmacklem	char *dev;
146191783Srmacklem	int i;
147191783Srmacklem
148191783Srmacklem	/*
149191783Srmacklem	 * XXX Chicken-and-egg problem; we want to have console output
150191783Srmacklem	 * early, but some console attributes may depend on reading from
151191783Srmacklem	 * eg. the boot device, which we can't do yet.  We can use
152191783Srmacklem	 * printf() etc. once this is done.
153191783Srmacklem	 */
154191783Srmacklem	cons_probe();
155191783Srmacklem
156191783Srmacklem	printf("\n%s, Revision %s\n", bootprog_name, bootprog_rev);
157191783Srmacklem
158191783Srmacklem	find_pal_proc();
159191783Srmacklem
160191783Srmacklem	/*
161191783Srmacklem	 * March through the device switch probing for things.
162191783Srmacklem	 */
163191783Srmacklem	for (i = 0; devsw[i] != NULL; i++)
164191783Srmacklem		if (devsw[i]->dv_init != NULL)
165191783Srmacklem			(devsw[i]->dv_init)();
166191783Srmacklem
167191783Srmacklem	/*
168191783Srmacklem	 * Disable the watchdog timer. By default the boot manager sets
169191783Srmacklem	 * the timer to 5 minutes before invoking a boot option. If we
170191783Srmacklem	 * want to return to the boot manager, we have to disable the
171191783Srmacklem	 * watchdog timer and since we're an interactive program, we don't
172191783Srmacklem	 * want to wait until the user types "quit". The timer may have
173191783Srmacklem	 * fired by then. We don't care if this fails. It does not prevent
174191783Srmacklem	 * normal functioning in any way...
175191783Srmacklem	 */
176191783Srmacklem	BS->SetWatchdogTimer(0, 0, 0, NULL);
177191783Srmacklem
178191783Srmacklem	/* Get our loaded image protocol interface structure. */
179191783Srmacklem	BS->HandleProtocol(IH, &imgid, (VOID**)&img);
180191783Srmacklem
181191783Srmacklem	bzero(&currdev, sizeof(currdev));
182191783Srmacklem	efi_handle_lookup(img->DeviceHandle, &currdev.d_dev,
183191783Srmacklem	    &currdev.d_unit, NULL);
184191783Srmacklem	currdev.d_type = currdev.d_dev->dv_type;
185191783Srmacklem
186191783Srmacklem	env_setenv("loaddev", EV_VOLATILE, ia64_fmtdev(&currdev), env_noset,
187191783Srmacklem	    env_nounset);
188191783Srmacklem
189191783Srmacklem	dev = get_dev_option(argc, argv);
190191783Srmacklem	if (dev == NULL)
191191783Srmacklem		dev = ia64_fmtdev(&currdev);
192191783Srmacklem
193191783Srmacklem	env_setenv("currdev", EV_VOLATILE, dev, ia64_setcurrdev, env_nounset);
194191783Srmacklem
195191783Srmacklem	setenv("LINES", "24", 1);	/* optional */
196191783Srmacklem
197194408Srmacklem	archsw.arch_autoload = ia64_autoload;
198191783Srmacklem	archsw.arch_copyin = ia64_copyin;
199191783Srmacklem	archsw.arch_copyout = ia64_copyout;
200191783Srmacklem	archsw.arch_getdev = ia64_getdev;
201191783Srmacklem	archsw.arch_loadaddr = ia64_loadaddr;
202191783Srmacklem	archsw.arch_loadseg = ia64_loadseg;
203191783Srmacklem	archsw.arch_readin = ia64_readin;
204191783Srmacklem
205191783Srmacklem	interact();			/* doesn't return */
206191783Srmacklem
207191783Srmacklem	return (EFI_SUCCESS);		/* keep compiler happy */
208191783Srmacklem}
209191783Srmacklem
210191783SrmacklemCOMMAND_SET(quit, "quit", "exit the loader", command_quit);
211191783Srmacklem
212191783Srmacklemstatic int
213191783Srmacklemcommand_quit(int argc, char *argv[])
214191783Srmacklem{
215191783Srmacklem	exit(0);
216191783Srmacklem	/* NOTREACHED */
217191783Srmacklem	return (CMD_OK);
218191783Srmacklem}
219191783Srmacklem
220191783SrmacklemCOMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
221191783Srmacklem
222191783Srmacklemstatic int
223191783Srmacklemcommand_reboot(int argc, char *argv[])
224191783Srmacklem{
225191783Srmacklem
226191783Srmacklem	RS->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
227191783Srmacklem	/* NOTREACHED */
228191783Srmacklem	return (CMD_OK);
229191783Srmacklem}
230191783Srmacklem
231191783SrmacklemCOMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
232191783Srmacklem
233191783Srmacklemstatic int
234191783Srmacklemcommand_memmap(int argc, char *argv[])
235191783Srmacklem{
236191783Srmacklem	UINTN sz;
237191783Srmacklem	EFI_MEMORY_DESCRIPTOR *map, *p;
238191783Srmacklem	UINTN key, dsz;
239191783Srmacklem	UINT32 dver;
240191783Srmacklem	EFI_STATUS status;
241191783Srmacklem	int i, ndesc;
242191783Srmacklem	static char *types[] = {
243191783Srmacklem	    "Reserved",
244191783Srmacklem	    "LoaderCode",
245191783Srmacklem	    "LoaderData",
246223309Srmacklem	    "BootServicesCode",
247191783Srmacklem	    "BootServicesData",
248191783Srmacklem	    "RuntimeServicesCode",
249191783Srmacklem	    "RuntimeServicesData",
250191783Srmacklem	    "ConventionalMemory",
251191783Srmacklem	    "UnusableMemory",
252191783Srmacklem	    "ACPIReclaimMemory",
253191783Srmacklem	    "ACPIMemoryNVS",
254223309Srmacklem	    "MemoryMappedIO",
255191783Srmacklem	    "MemoryMappedIOPortSpace",
256191783Srmacklem	    "PalCode"
257191783Srmacklem	};
258191783Srmacklem
259191783Srmacklem	sz = 0;
260191783Srmacklem	status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
261191783Srmacklem	if (status != EFI_BUFFER_TOO_SMALL) {
262191783Srmacklem		printf("Can't determine memory map size\n");
263191783Srmacklem		return CMD_ERROR;
264191783Srmacklem	}
265191783Srmacklem	map = malloc(sz);
266191783Srmacklem	status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
267191783Srmacklem	if (EFI_ERROR(status)) {
268191783Srmacklem		printf("Can't read memory map\n");
269191783Srmacklem		return CMD_ERROR;
270191783Srmacklem	}
271191783Srmacklem
272191783Srmacklem	ndesc = sz / dsz;
273191783Srmacklem	printf("%23s %12s %12s %8s %4s\n",
274191783Srmacklem	       "Type", "Physical", "Virtual", "#Pages", "Attr");
275191783Srmacklem
276191783Srmacklem	for (i = 0, p = map; i < ndesc;
277244042Srmacklem	     i++, p = NextMemoryDescriptor(p, dsz)) {
278244042Srmacklem	    printf("%23s %012lx %012lx %08lx ",
279244042Srmacklem		   types[p->Type],
280244042Srmacklem		   p->PhysicalStart,
281317524Srmacklem		   p->VirtualStart,
282317524Srmacklem		   p->NumberOfPages);
283317524Srmacklem	    if (p->Attribute & EFI_MEMORY_UC)
284317524Srmacklem		printf("UC ");
285317524Srmacklem	    if (p->Attribute & EFI_MEMORY_WC)
286255216Srmacklem		printf("WC ");
287255216Srmacklem	    if (p->Attribute & EFI_MEMORY_WT)
288255216Srmacklem		printf("WT ");
289191783Srmacklem	    if (p->Attribute & EFI_MEMORY_WB)
290255216Srmacklem		printf("WB ");
291255216Srmacklem	    if (p->Attribute & EFI_MEMORY_UCE)
292255216Srmacklem		printf("UCE ");
293255216Srmacklem	    if (p->Attribute & EFI_MEMORY_WP)
294255216Srmacklem		printf("WP ");
295255216Srmacklem	    if (p->Attribute & EFI_MEMORY_RP)
296191783Srmacklem		printf("RP ");
297191783Srmacklem	    if (p->Attribute & EFI_MEMORY_XP)
298		printf("XP ");
299	    if (p->Attribute & EFI_MEMORY_RUNTIME)
300		printf("RUNTIME");
301	    printf("\n");
302	}
303
304	return CMD_OK;
305}
306
307COMMAND_SET(configuration, "configuration",
308	    "print configuration tables", command_configuration);
309
310static const char *
311guid_to_string(EFI_GUID *guid)
312{
313	static char buf[40];
314
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]);
319	return (buf);
320}
321
322static int
323command_configuration(int argc, char *argv[])
324{
325	int i;
326
327	printf("NumberOfTableEntries=%ld\n", ST->NumberOfTableEntries);
328	for (i = 0; i < ST->NumberOfTableEntries; i++) {
329		EFI_GUID *guid;
330
331		printf("  ");
332		guid = &ST->ConfigurationTable[i].VendorGuid;
333		if (!memcmp(guid, &mps, sizeof(EFI_GUID)))
334			printf("MPS Table");
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");
345		else
346			printf("Unknown Table (%s)", guid_to_string(guid));
347		printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
348	}
349
350	return CMD_OK;
351}
352
353COMMAND_SET(sal, "sal", "print SAL System Table", command_sal);
354
355static int
356command_sal(int argc, char *argv[])
357{
358	int i;
359	struct sal_system_table *saltab = 0;
360	static int sizes[6] = {
361		48, 32, 16, 32, 16, 16
362	};
363	u_int8_t *p;
364
365	saltab = efi_get_table(&sal);
366	if (saltab == NULL) {
367		printf("Can't find SAL System Table\n");
368		return CMD_ERROR;
369	}
370
371	if (memcmp(saltab->sal_signature, "SST_", 4)) {
372		printf("Bad signature for SAL System Table\n");
373		return CMD_ERROR;
374	}
375
376	printf("SAL Revision %x.%02x\n",
377	       saltab->sal_rev[1],
378	       saltab->sal_rev[0]);
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]);
385
386	p = (u_int8_t *) (saltab + 1);
387	for (i = 0; i < saltab->sal_entry_count; i++) {
388		printf("  Desc %d", *p);
389		if (*p == 0) {
390			struct sal_entrypoint_descriptor *dp;
391			dp = (struct sal_entrypoint_descriptor *) p;
392			printf("\n");
393			printf("    PAL Proc at 0x%lx\n",
394			       dp->sale_pal_proc);
395			printf("    SAL Proc at 0x%lx\n",
396			       dp->sale_sal_proc);
397			printf("    SAL GP at 0x%lx\n",
398			       dp->sale_sal_gp);
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",
408			       dp->sale_length);
409		} else if (*p == 5) {
410			struct sal_ap_wakeup_descriptor *dp;
411			dp = (struct sal_ap_wakeup_descriptor *) p;
412			printf("\n");
413			printf("    Mechanism %d\n", dp->sale_mechanism);
414			printf("    Vector 0x%lx\n", dp->sale_vector);
415		} else
416			printf("\n");
417
418		p += sizes[*p];
419	}
420
421	return CMD_OK;
422}
423
424int
425print_trs(int type)
426{
427	struct ia64_pal_result res;
428	int i, maxtr;
429	struct {
430		pt_entry_t	pte;
431		uint64_t	itir;
432		uint64_t	ifa;
433		struct ia64_rr	rr;
434	} buf;
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"
444	};
445	static const char *manames[] = {
446		"WB",	"bad",	"bad",	"bad",
447		"UC",	"UCE",	"WC",	"NaT",
448	};
449
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");
453		return CMD_ERROR;
454	}
455
456	if (type == 0)
457		maxtr = (res.pal_result[0] >> 40) & 0xff;
458	else
459		maxtr = (res.pal_result[0] >> 32) & 0xff;
460
461	printf("%d translation registers\n", maxtr);
462
463	pager_open();
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++) {
466		char lbuf[128];
467
468		bzero(&buf, sizeof(buf));
469		res = ia64_call_pal_stacked(PAL_VM_TR_READ, i, type,
470					    (u_int64_t) &buf);
471		if (res.pal_status != 0)
472			break;
473
474		/* Only display valid translations */
475		if ((buf.ifa & 1) == 0)
476			continue;
477
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));
498		pager_output(lbuf);
499	}
500	pager_close();
501
502	if (res.pal_status != 0) {
503		printf("Error while getting TR contents\n");
504		return CMD_ERROR;
505	}
506	return CMD_OK;
507}
508
509COMMAND_SET(itr, "itr", "print instruction TRs", command_itr);
510
511static int
512command_itr(int argc, char *argv[])
513{
514	return print_trs(0);
515}
516
517COMMAND_SET(dtr, "dtr", "print data TRs", command_dtr);
518
519static int
520command_dtr(int argc, char *argv[])
521{
522	return print_trs(1);
523}
524
525COMMAND_SET(hcdp, "hcdp", "Dump HCDP info", command_hcdp);
526
527static char *
528hcdp_string(char *s, u_int len)
529{
530	static char buffer[256];
531
532	memcpy(buffer, s, len);
533	buffer[len] = 0;
534	return (buffer);
535}
536
537static int
538command_hcdp(int argc, char *argv[])
539{
540	struct dig64_hcdp_table *tbl;
541	struct dig64_hcdp_entry *ent;
542	struct dig64_gas *gas;
543	int i;
544
545	tbl = efi_get_table(&hcdp);
546	if (tbl == NULL) {
547		printf("No HCDP table present\n");
548		return (CMD_OK);
549	}
550	if (memcmp(tbl->signature, HCDP_SIGNATURE, sizeof(tbl->signature))) {
551		printf("HCDP table has invalid signature\n");
552		return (CMD_OK);
553	}
554	if (tbl->length < sizeof(*tbl) - sizeof(*tbl->entry)) {
555		printf("HCDP table too short\n");
556		return (CMD_OK);
557	}
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);
584		gas = &ent->address;
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);
595	}
596	printf("<EOT>\n");
597	return (CMD_OK);
598}
599
600COMMAND_SET(about, "about", "about the loader", command_about);
601
602extern uint64_t _start_plabel[];
603
604static int
605command_about(int argc, char *argv[])
606{
607	EFI_LOADED_IMAGE *img;
608
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);
613
614	printf("\n");
615
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]);
619}
620