Home | History | Annotate | Line # | Download | only in efiboot
boot.c revision 1.17.12.1
      1  1.17.12.1  thorpej /*	$NetBSD: boot.c,v 1.17.12.1 2021/06/17 04:46:21 thorpej Exp $	*/
      2        1.1   nonaka 
      3        1.1   nonaka /*-
      4        1.1   nonaka  * Copyright (c) 2016 Kimihiro Nonaka <nonaka (at) netbsd.org>
      5        1.1   nonaka  * All rights reserved.
      6        1.1   nonaka  *
      7        1.1   nonaka  * Redistribution and use in source and binary forms, with or without
      8        1.1   nonaka  * modification, are permitted provided that the following conditions
      9        1.1   nonaka  * are met:
     10        1.1   nonaka  * 1. Redistributions of source code must retain the above copyright
     11        1.1   nonaka  *    notice, this list of conditions and the following disclaimer.
     12        1.1   nonaka  * 2. Redistributions in binary form must reproduce the above copyright
     13        1.1   nonaka  *    notice, this list of conditions and the following disclaimer in the
     14        1.1   nonaka  *    documentation and/or other materials provided with the distribution.
     15        1.1   nonaka  *
     16        1.1   nonaka  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     17        1.1   nonaka  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18        1.1   nonaka  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19        1.1   nonaka  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     20        1.1   nonaka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21        1.1   nonaka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22        1.1   nonaka  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23        1.1   nonaka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24        1.1   nonaka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25        1.1   nonaka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26        1.1   nonaka  * SUCH DAMAGE.
     27        1.1   nonaka  */
     28        1.1   nonaka 
     29        1.1   nonaka #include "efiboot.h"
     30        1.1   nonaka 
     31        1.1   nonaka #include <sys/bootblock.h>
     32        1.1   nonaka #include <sys/boot_flag.h>
     33        1.5   nonaka #include <machine/limits.h>
     34        1.1   nonaka 
     35        1.4   nonaka #include "bootcfg.h"
     36        1.4   nonaka #include "bootmod.h"
     37        1.4   nonaka #include "bootmenu.h"
     38       1.14     manu #include "biosdisk.h"
     39        1.1   nonaka #include "devopen.h"
     40        1.1   nonaka 
     41  1.17.12.1  thorpej #ifdef _STANDALONE
     42  1.17.12.1  thorpej #include <bootinfo.h>
     43  1.17.12.1  thorpej #endif
     44  1.17.12.1  thorpej 
     45        1.1   nonaka int errno;
     46        1.1   nonaka int boot_biosdev;
     47        1.1   nonaka daddr_t boot_biossector;
     48        1.1   nonaka 
     49        1.1   nonaka extern const char bootprog_name[], bootprog_rev[], bootprog_kernrev[];
     50        1.1   nonaka 
     51        1.1   nonaka extern struct x86_boot_params boot_params;
     52        1.1   nonaka extern char twiddle_toggle;
     53        1.1   nonaka 
     54        1.1   nonaka static const char * const names[][2] = {
     55        1.1   nonaka 	{ "netbsd", "netbsd.gz" },
     56        1.1   nonaka 	{ "onetbsd", "onetbsd.gz" },
     57        1.1   nonaka 	{ "netbsd.old", "netbsd.old.gz" },
     58        1.1   nonaka };
     59        1.1   nonaka 
     60        1.1   nonaka #define NUMNAMES	__arraycount(names)
     61        1.1   nonaka #define DEFFILENAME	names[0][0]
     62        1.1   nonaka 
     63        1.9   nonaka #ifndef	EFIBOOTCFG_FILENAME
     64        1.9   nonaka #define	EFIBOOTCFG_FILENAME	"esp:/EFI/NetBSD/boot.cfg"
     65        1.9   nonaka #endif
     66        1.1   nonaka 
     67        1.1   nonaka void	command_help(char *);
     68        1.1   nonaka void	command_quit(char *);
     69        1.1   nonaka void	command_boot(char *);
     70       1.11     maxv void	command_pkboot(char *);
     71        1.1   nonaka void	command_consdev(char *);
     72  1.17.12.1  thorpej void	command_root(char *);
     73        1.1   nonaka void	command_dev(char *);
     74        1.1   nonaka void	command_devpath(char *);
     75        1.1   nonaka void	command_efivar(char *);
     76        1.1   nonaka void	command_gop(char *);
     77        1.1   nonaka #if LIBSA_ENABLE_LS_OP
     78        1.1   nonaka void	command_ls(char *);
     79        1.1   nonaka #endif
     80        1.1   nonaka void	command_memmap(char *);
     81        1.1   nonaka #ifndef SMALL
     82        1.1   nonaka void	command_menu(char *);
     83        1.1   nonaka #endif
     84        1.1   nonaka void	command_modules(char *);
     85        1.1   nonaka void	command_multiboot(char *);
     86        1.1   nonaka void	command_text(char *);
     87        1.1   nonaka void	command_version(char *);
     88        1.1   nonaka 
     89        1.1   nonaka const struct bootblk_command commands[] = {
     90        1.1   nonaka 	{ "help",	command_help },
     91        1.1   nonaka 	{ "?",		command_help },
     92        1.1   nonaka 	{ "quit",	command_quit },
     93        1.1   nonaka 	{ "boot",	command_boot },
     94       1.11     maxv 	{ "pkboot",	command_pkboot },
     95        1.1   nonaka 	{ "consdev",	command_consdev },
     96  1.17.12.1  thorpej 	{ "root",	command_root },
     97        1.1   nonaka 	{ "dev",	command_dev },
     98        1.1   nonaka 	{ "devpath",	command_devpath },
     99        1.1   nonaka 	{ "efivar",	command_efivar },
    100        1.1   nonaka 	{ "fs",		fs_add },
    101        1.1   nonaka 	{ "gop",	command_gop },
    102        1.1   nonaka 	{ "load",	module_add },
    103        1.1   nonaka #if LIBSA_ENABLE_LS_OP
    104        1.1   nonaka 	{ "ls",		command_ls },
    105        1.1   nonaka #endif
    106        1.1   nonaka 	{ "memmap",	command_memmap },
    107        1.1   nonaka #ifndef SMALL
    108        1.1   nonaka 	{ "menu",	command_menu },
    109        1.1   nonaka #endif
    110        1.1   nonaka 	{ "modules",	command_modules },
    111        1.1   nonaka 	{ "multiboot",	command_multiboot },
    112        1.1   nonaka 	{ "rndseed",	rnd_add },
    113        1.1   nonaka 	{ "splash",	splash_add },
    114        1.1   nonaka 	{ "text",	command_text },
    115        1.1   nonaka 	{ "userconf",	userconf_add },
    116        1.1   nonaka 	{ "version",	command_version },
    117        1.1   nonaka 	{ NULL,		NULL },
    118        1.1   nonaka };
    119        1.1   nonaka 
    120       1.17   nonaka static char *default_fsname;
    121        1.1   nonaka static char *default_devname;
    122        1.1   nonaka static int default_unit, default_partition;
    123        1.1   nonaka static const char *default_filename;
    124       1.14     manu static const char *default_part_name;
    125        1.1   nonaka 
    126        1.1   nonaka static char *sprint_bootsel(const char *);
    127        1.1   nonaka static void bootit(const char *, int);
    128        1.1   nonaka 
    129        1.1   nonaka int
    130        1.1   nonaka parsebootfile(const char *fname, char **fsname, char **devname, int *unit,
    131        1.1   nonaka     int *partition, const char **file)
    132        1.1   nonaka {
    133        1.1   nonaka 	const char *col;
    134       1.14     manu 	static char savedevname[MAXDEVNAME+1];
    135       1.17   nonaka #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
    136       1.17   nonaka 	const struct netboot_fstab *nf;
    137       1.17   nonaka #endif
    138        1.1   nonaka 
    139       1.17   nonaka 	*fsname = default_fsname;
    140       1.14     manu 	if (default_part_name == NULL) {
    141       1.14     manu 		*devname = default_devname;
    142       1.14     manu 	} else {
    143       1.15     manu 		snprintf(savedevname, sizeof(savedevname),
    144       1.15     manu 		    "NAME=%s", default_part_name);
    145       1.14     manu 		*devname = savedevname;
    146       1.14     manu 	}
    147        1.1   nonaka 	*unit = default_unit;
    148        1.1   nonaka 	*partition = default_partition;
    149        1.1   nonaka 	*file = default_filename;
    150        1.1   nonaka 
    151        1.1   nonaka 	if (fname == NULL)
    152        1.1   nonaka 		return 0;
    153        1.1   nonaka 
    154        1.1   nonaka 	if ((col = strchr(fname, ':')) != NULL) {	/* device given */
    155        1.1   nonaka 		int devlen;
    156        1.1   nonaka 		int u = 0, p = 0;
    157        1.1   nonaka 		int i = 0;
    158        1.1   nonaka 
    159        1.1   nonaka 		devlen = col - fname;
    160        1.1   nonaka 		if (devlen > MAXDEVNAME)
    161        1.1   nonaka 			return EINVAL;
    162        1.1   nonaka 
    163       1.14     manu 		if (strstr(fname, "NAME=") == fname) {
    164       1.14     manu 			strlcpy(savedevname, fname, devlen + 1);
    165       1.17   nonaka 			*fsname = "ufs";
    166       1.14     manu 			*devname = savedevname;
    167       1.14     manu 			*unit = -1;
    168       1.14     manu 			*partition = -1;
    169       1.14     manu 			fname = col + 1;
    170       1.14     manu 			goto out;
    171       1.14     manu 		}
    172       1.14     manu 
    173        1.1   nonaka #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
    174        1.1   nonaka 		if (!isvalidname(fname[i]))
    175        1.1   nonaka 			return EINVAL;
    176        1.1   nonaka 		do {
    177        1.1   nonaka 			savedevname[i] = fname[i];
    178        1.1   nonaka 			i++;
    179        1.1   nonaka 		} while (isvalidname(fname[i]));
    180        1.1   nonaka 		savedevname[i] = '\0';
    181        1.1   nonaka 
    182        1.1   nonaka #define isnum(c) ((c) >= '0' && (c) <= '9')
    183        1.1   nonaka 		if (i < devlen) {
    184        1.1   nonaka 			if (!isnum(fname[i]))
    185        1.1   nonaka 				return EUNIT;
    186        1.1   nonaka 			do {
    187        1.1   nonaka 				u *= 10;
    188        1.1   nonaka 				u += fname[i++] - '0';
    189        1.1   nonaka 			} while (isnum(fname[i]));
    190        1.1   nonaka 		}
    191        1.1   nonaka 
    192        1.1   nonaka #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
    193        1.1   nonaka 		if (i < devlen) {
    194        1.1   nonaka 			if (!isvalidpart(fname[i]))
    195        1.1   nonaka 				return EPART;
    196        1.1   nonaka 			p = fname[i++] - 'a';
    197        1.1   nonaka 		}
    198        1.1   nonaka 
    199        1.1   nonaka 		if (i != devlen)
    200        1.1   nonaka 			return ENXIO;
    201        1.1   nonaka 
    202       1.17   nonaka #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
    203       1.17   nonaka 		nf = netboot_fstab_find(savedevname);
    204       1.17   nonaka 		if (nf != NULL)
    205       1.17   nonaka 			*fsname = (char *)nf->name;
    206       1.17   nonaka 		else
    207       1.17   nonaka #endif
    208       1.17   nonaka 		*fsname = "ufs";
    209        1.1   nonaka 		*devname = savedevname;
    210        1.1   nonaka 		*unit = u;
    211        1.1   nonaka 		*partition = p;
    212        1.1   nonaka 		fname = col + 1;
    213        1.1   nonaka 	}
    214        1.1   nonaka 
    215       1.14     manu out:
    216        1.1   nonaka 	if (*fname)
    217        1.1   nonaka 		*file = fname;
    218        1.1   nonaka 
    219        1.1   nonaka 	return 0;
    220        1.1   nonaka }
    221        1.1   nonaka 
    222        1.1   nonaka static char *
    223       1.10   nonaka snprint_bootdev(char *buf, size_t bufsize, const char *devname, int unit,
    224       1.10   nonaka     int partition)
    225       1.10   nonaka {
    226       1.10   nonaka 	static const char *no_partition_devs[] = { "esp", "net", "nfs", "tftp" };
    227       1.10   nonaka 	int i;
    228       1.10   nonaka 
    229       1.10   nonaka 	for (i = 0; i < __arraycount(no_partition_devs); i++)
    230       1.10   nonaka 		if (strcmp(devname, no_partition_devs[i]) == 0)
    231       1.10   nonaka 			break;
    232       1.14     manu 	if (strstr(devname, "NAME=") == devname)
    233       1.14     manu 		strlcpy(buf, devname, bufsize);
    234       1.14     manu 	else
    235       1.14     manu 		snprintf(buf, bufsize, "%s%d%c", devname, unit,
    236       1.14     manu 		  i < __arraycount(no_partition_devs) ? '\0' : 'a' + partition);
    237       1.10   nonaka 	return buf;
    238       1.10   nonaka }
    239       1.10   nonaka 
    240       1.10   nonaka static char *
    241        1.1   nonaka sprint_bootsel(const char *filename)
    242        1.1   nonaka {
    243        1.1   nonaka 	char *fsname, *devname;
    244        1.1   nonaka 	int unit, partition;
    245        1.1   nonaka 	const char *file;
    246        1.1   nonaka 	static char buf[80];
    247        1.1   nonaka 
    248        1.1   nonaka 	if (parsebootfile(filename, &fsname, &devname, &unit,
    249        1.1   nonaka 			  &partition, &file) == 0) {
    250       1.10   nonaka 		snprintf(buf, sizeof(buf), "%s:%s", snprint_bootdev(buf,
    251       1.10   nonaka 		    sizeof(buf), devname, unit, partition), file);
    252        1.1   nonaka 		return buf;
    253        1.1   nonaka 	}
    254        1.1   nonaka 	return "(invalid)";
    255        1.1   nonaka }
    256        1.1   nonaka 
    257        1.1   nonaka void
    258        1.1   nonaka clearit(void)
    259        1.1   nonaka {
    260        1.1   nonaka 
    261        1.1   nonaka 	if (bootcfg_info.clear)
    262        1.1   nonaka 		clear_pc_screen();
    263        1.1   nonaka }
    264        1.1   nonaka 
    265        1.1   nonaka static void
    266        1.1   nonaka bootit(const char *filename, int howto)
    267        1.1   nonaka {
    268        1.1   nonaka 
    269        1.1   nonaka 	if (howto & AB_VERBOSE)
    270        1.1   nonaka 		printf("booting %s (howto 0x%x)\n", sprint_bootsel(filename),
    271        1.1   nonaka 		    howto);
    272        1.1   nonaka 
    273       1.12   nonaka 	if (exec_netbsd(filename, efi_loadaddr, howto, 0, efi_cleanup) < 0)
    274        1.1   nonaka 		printf("boot: %s: %s\n", sprint_bootsel(filename),
    275        1.1   nonaka 		       strerror(errno));
    276        1.1   nonaka 	else
    277        1.1   nonaka 		printf("boot returned\n");
    278        1.1   nonaka }
    279        1.1   nonaka 
    280        1.1   nonaka void
    281        1.1   nonaka print_banner(void)
    282        1.1   nonaka {
    283        1.1   nonaka 	int n;
    284        1.1   nonaka 
    285        1.1   nonaka 	clearit();
    286        1.1   nonaka 	if (bootcfg_info.banner[0]) {
    287        1.1   nonaka 		for (n = 0; n < BOOTCFG_MAXBANNER && bootcfg_info.banner[n];
    288        1.1   nonaka 		    n++)
    289        1.1   nonaka 			printf("%s\n", bootcfg_info.banner[n]);
    290        1.1   nonaka 	} else
    291        1.1   nonaka 		command_version("short");
    292        1.1   nonaka }
    293        1.1   nonaka 
    294        1.1   nonaka void
    295        1.1   nonaka boot(void)
    296        1.1   nonaka {
    297        1.1   nonaka 	int currname;
    298        1.1   nonaka 	int c;
    299       1.17   nonaka #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
    300       1.17   nonaka 	const struct netboot_fstab *nf;
    301       1.17   nonaka #endif
    302        1.1   nonaka 
    303        1.1   nonaka 	boot_modules_enabled = !(boot_params.bp_flags & X86_BP_FLAGS_NOMODULES);
    304        1.1   nonaka 
    305        1.1   nonaka 	/* try to set default device to what BIOS tells us */
    306        1.1   nonaka 	bios2dev(boot_biosdev, boot_biossector, &default_devname, &default_unit,
    307       1.14     manu 	    &default_partition, &default_part_name);
    308        1.1   nonaka 
    309        1.1   nonaka 	/* if the user types "boot" without filename */
    310        1.1   nonaka 	default_filename = DEFFILENAME;
    311        1.1   nonaka 
    312       1.17   nonaka #if defined(SUPPORT_NFS) || defined(SUPPORT_TFTP)
    313       1.17   nonaka 	nf = netboot_fstab_find(default_devname);
    314       1.17   nonaka 	if (nf != NULL)
    315       1.17   nonaka 		default_fsname = (char *)nf->name;
    316       1.17   nonaka 	else
    317       1.17   nonaka #endif
    318       1.17   nonaka 	default_fsname = "ufs";
    319       1.17   nonaka 
    320        1.1   nonaka 	if (!(boot_params.bp_flags & X86_BP_FLAGS_NOBOOTCONF)) {
    321        1.9   nonaka #ifdef EFIBOOTCFG_FILENAME
    322       1.10   nonaka 		int rv = EINVAL;
    323       1.10   nonaka 		if (efi_bootdp_type != BOOT_DEVICE_TYPE_NET)
    324       1.10   nonaka 			rv = parsebootconf(EFIBOOTCFG_FILENAME);
    325        1.9   nonaka 		if (rv)
    326        1.9   nonaka #endif
    327        1.1   nonaka 		parsebootconf(BOOTCFG_FILENAME);
    328        1.1   nonaka 	} else {
    329        1.1   nonaka 		bootcfg_info.timeout = boot_params.bp_timeout;
    330        1.1   nonaka 	}
    331        1.1   nonaka 
    332        1.1   nonaka 	/*
    333        1.1   nonaka 	 * If console set in boot.cfg, switch to it.
    334        1.1   nonaka 	 * This will print the banner, so we don't need to explicitly do it
    335        1.1   nonaka 	 */
    336        1.1   nonaka 	if (bootcfg_info.consdev)
    337        1.1   nonaka 		command_consdev(bootcfg_info.consdev);
    338        1.1   nonaka 	else
    339        1.1   nonaka 		print_banner();
    340        1.1   nonaka 
    341        1.1   nonaka 	/* Display the menu, if applicable */
    342        1.1   nonaka 	twiddle_toggle = 0;
    343        1.1   nonaka 	if (bootcfg_info.nummenu > 0) {
    344        1.1   nonaka 		/* Does not return */
    345        1.1   nonaka 		doboottypemenu();
    346        1.1   nonaka 	}
    347        1.1   nonaka 
    348        1.1   nonaka 	printf("Press return to boot now, any other key for boot menu\n");
    349        1.1   nonaka 	for (currname = 0; currname < NUMNAMES; currname++) {
    350        1.1   nonaka 		printf("booting %s - starting in ",
    351        1.1   nonaka 		       sprint_bootsel(names[currname][0]));
    352        1.1   nonaka 
    353        1.1   nonaka 		c = awaitkey((bootcfg_info.timeout < 0) ? 0
    354        1.1   nonaka 		    : bootcfg_info.timeout, 1);
    355        1.1   nonaka 		if ((c != '\r') && (c != '\n') && (c != '\0')) {
    356        1.1   nonaka 		    if ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0) {
    357        1.1   nonaka 			/* do NOT ask for password */
    358        1.1   nonaka 			bootmenu(); /* does not return */
    359        1.1   nonaka 		    } else {
    360        1.1   nonaka 			/* DO ask for password */
    361        1.1   nonaka 			if (check_password((char *)boot_params.bp_password)) {
    362        1.1   nonaka 			    /* password ok */
    363        1.1   nonaka 			    printf("type \"?\" or \"help\" for help.\n");
    364        1.1   nonaka 			    bootmenu(); /* does not return */
    365        1.1   nonaka 			} else {
    366        1.1   nonaka 			    /* bad password */
    367        1.1   nonaka 			    printf("Wrong password.\n");
    368        1.1   nonaka 			    currname = 0;
    369        1.1   nonaka 			    continue;
    370        1.1   nonaka 			}
    371        1.1   nonaka 		    }
    372        1.1   nonaka 		}
    373        1.1   nonaka 
    374        1.1   nonaka 		/*
    375        1.1   nonaka 		 * try pairs of names[] entries, foo and foo.gz
    376        1.1   nonaka 		 */
    377        1.1   nonaka 		/* don't print "booting..." again */
    378        1.1   nonaka 		bootit(names[currname][0], 0);
    379        1.1   nonaka 		/* since it failed, try compressed bootfile. */
    380        1.1   nonaka 		bootit(names[currname][1], AB_VERBOSE);
    381        1.1   nonaka 	}
    382        1.1   nonaka 
    383        1.1   nonaka 	bootmenu();	/* does not return */
    384        1.1   nonaka }
    385        1.1   nonaka 
    386        1.1   nonaka /* ARGSUSED */
    387        1.1   nonaka void
    388        1.1   nonaka command_help(char *arg)
    389        1.1   nonaka {
    390        1.1   nonaka 
    391        1.1   nonaka 	printf("commands are:\n"
    392       1.14     manu 	       "boot [dev:][filename] [-12acdqsvxz]\n"
    393       1.14     manu #ifndef NO_RAIDFRAME
    394       1.14     manu 	       "     dev syntax is (hd|fd|cd|raid)[N[x]]\n"
    395       1.14     manu #else
    396       1.14     manu 	       "     dev syntax is (hd|fd|cd)[N[x]]\n"
    397       1.14     manu #endif
    398       1.14     manu #ifndef NO_GPT
    399       1.14     manu 	       "                or NAME=gpt_label\n"
    400       1.14     manu #endif
    401       1.11     maxv 	       "     (ex. \"hd0a:netbsd.old -s\")\n"
    402       1.14     manu 	       "pkboot [dev:][filename] [-12acdqsvxz]\n"
    403       1.14     manu 	       "dev [dev:]\n"
    404        1.5   nonaka 	       "consdev {pc|com[0123][,{speed}]|com,{ioport}[,{speed}]}\n"
    405  1.17.12.1  thorpej 	       "root    {spec}\n"
    406  1.17.12.1  thorpej 	       "     spec can be disk, e.g. wd0, sd0\n"
    407  1.17.12.1  thorpej 	       "     or string like wedge:name\n"
    408        1.1   nonaka 	       "devpath\n"
    409        1.1   nonaka 	       "efivar\n"
    410        1.1   nonaka 	       "gop [{modenum|list}]\n"
    411        1.1   nonaka 	       "load {path_to_module}\n"
    412        1.1   nonaka #if LIBSA_ENABLE_LS_OP
    413       1.14     manu 	       "ls [dev:][path]\n"
    414        1.1   nonaka #endif
    415       1.13   nonaka 	       "memmap [{sorted|unsorted|compact}]\n"
    416        1.1   nonaka #ifndef SMALL
    417        1.1   nonaka 	       "menu (reenters boot menu, if defined in boot.cfg)\n"
    418        1.1   nonaka #endif
    419        1.1   nonaka 	       "modules {on|off|enabled|disabled}\n"
    420       1.14     manu 	       "multiboot [dev:][filename] [<args>]\n"
    421        1.1   nonaka 	       "rndseed {path_to_rndseed_file}\n"
    422        1.1   nonaka 	       "splash {path_to_image_file}\n"
    423        1.1   nonaka 	       "text [{modenum|list}]\n"
    424        1.1   nonaka 	       "userconf {command}\n"
    425        1.1   nonaka 	       "version\n"
    426        1.1   nonaka 	       "help|?\n"
    427        1.1   nonaka 	       "quit\n");
    428        1.1   nonaka }
    429        1.1   nonaka 
    430        1.1   nonaka #if LIBSA_ENABLE_LS_OP
    431        1.1   nonaka void
    432        1.1   nonaka command_ls(char *arg)
    433        1.1   nonaka {
    434        1.1   nonaka 	const char *save = default_filename;
    435        1.1   nonaka 
    436        1.1   nonaka 	default_filename = "/";
    437        1.1   nonaka 	ls(arg);
    438        1.1   nonaka 	default_filename = save;
    439        1.1   nonaka }
    440        1.1   nonaka #endif
    441        1.1   nonaka 
    442        1.1   nonaka /* ARGSUSED */
    443        1.1   nonaka void
    444        1.1   nonaka command_quit(char *arg)
    445        1.1   nonaka {
    446        1.1   nonaka 
    447        1.1   nonaka 	printf("Exiting...\n");
    448        1.1   nonaka 	delay(1 * 1000 * 1000);
    449        1.1   nonaka 	reboot();
    450        1.1   nonaka 	/* Note: we shouldn't get to this point! */
    451        1.1   nonaka 	panic("Could not reboot!");
    452        1.1   nonaka }
    453        1.1   nonaka 
    454        1.1   nonaka void
    455        1.1   nonaka command_boot(char *arg)
    456        1.1   nonaka {
    457        1.1   nonaka 	char *filename;
    458        1.1   nonaka 	int howto;
    459        1.1   nonaka 
    460        1.1   nonaka 	if (!parseboot(arg, &filename, &howto))
    461        1.1   nonaka 		return;
    462        1.1   nonaka 
    463        1.1   nonaka 	if (filename != NULL) {
    464        1.1   nonaka 		bootit(filename, howto);
    465        1.1   nonaka 	} else {
    466        1.1   nonaka 		int i;
    467        1.1   nonaka 
    468        1.1   nonaka 		if (howto == 0)
    469        1.1   nonaka 			bootdefault();
    470        1.1   nonaka 		for (i = 0; i < NUMNAMES; i++) {
    471        1.1   nonaka 			bootit(names[i][0], howto);
    472        1.1   nonaka 			bootit(names[i][1], howto);
    473        1.1   nonaka 		}
    474        1.1   nonaka 	}
    475        1.1   nonaka }
    476        1.1   nonaka 
    477        1.1   nonaka void
    478       1.11     maxv command_pkboot(char *arg)
    479       1.11     maxv {
    480       1.11     maxv 	extern int has_prekern;
    481       1.11     maxv 	has_prekern = 1;
    482       1.11     maxv 	command_boot(arg);
    483       1.11     maxv 	has_prekern = 0;
    484       1.11     maxv }
    485       1.11     maxv 
    486       1.11     maxv void
    487        1.1   nonaka command_dev(char *arg)
    488        1.1   nonaka {
    489        1.1   nonaka 	static char savedevname[MAXDEVNAME + 1];
    490       1.10   nonaka 	char buf[80];
    491       1.17   nonaka 	char *devname;
    492        1.1   nonaka 	const char *file; /* dummy */
    493        1.1   nonaka 
    494        1.1   nonaka 	if (*arg == '\0') {
    495        1.6   nonaka 		efi_disk_show();
    496       1.10   nonaka 		efi_net_show();
    497       1.14     manu 
    498       1.14     manu 		if (default_part_name != NULL)
    499       1.14     manu 			printf("default NAME=%s\n", default_part_name);
    500       1.14     manu 		else
    501       1.14     manu 			printf("default %s\n",
    502       1.14     manu 			       snprint_bootdev(buf, sizeof(buf),
    503       1.14     manu 					       default_devname, default_unit,
    504       1.14     manu 					       default_partition));
    505        1.1   nonaka 		return;
    506        1.1   nonaka 	}
    507        1.1   nonaka 
    508        1.1   nonaka 	if (strchr(arg, ':') == NULL ||
    509       1.17   nonaka 	    parsebootfile(arg, &default_fsname, &devname, &default_unit,
    510        1.1   nonaka 	      &default_partition, &file)) {
    511        1.1   nonaka 		command_help(NULL);
    512        1.1   nonaka 		return;
    513        1.1   nonaka 	}
    514        1.1   nonaka 
    515        1.1   nonaka 	/* put to own static storage */
    516        1.1   nonaka 	strncpy(savedevname, devname, MAXDEVNAME + 1);
    517        1.1   nonaka 	default_devname = savedevname;
    518       1.14     manu 
    519       1.14     manu 	/* +5 to skip leading NAME= */
    520       1.14     manu 	if (strstr(devname, "NAME=") == devname)
    521       1.14     manu 		default_part_name = default_devname + 5;
    522        1.1   nonaka }
    523        1.1   nonaka 
    524        1.5   nonaka static const struct cons_devs {
    525        1.5   nonaka 	const char	*name;
    526        1.5   nonaka 	u_int		tag;
    527        1.5   nonaka 	int		ioport;
    528        1.5   nonaka } cons_devs[] = {
    529        1.5   nonaka 	{ "pc",		CONSDEV_PC,   0 },
    530        1.5   nonaka 	{ "com0",	CONSDEV_COM0, 0 },
    531        1.5   nonaka 	{ "com1",	CONSDEV_COM1, 0 },
    532        1.5   nonaka 	{ "com2",	CONSDEV_COM2, 0 },
    533        1.5   nonaka 	{ "com3",	CONSDEV_COM3, 0 },
    534        1.5   nonaka 	{ "com0kbd",	CONSDEV_COM0KBD, 0 },
    535        1.5   nonaka 	{ "com1kbd",	CONSDEV_COM1KBD, 0 },
    536        1.5   nonaka 	{ "com2kbd",	CONSDEV_COM2KBD, 0 },
    537        1.5   nonaka 	{ "com3kbd",	CONSDEV_COM3KBD, 0 },
    538        1.5   nonaka 	{ "com",	CONSDEV_COM0, -1 },
    539        1.5   nonaka 	{ "auto",	CONSDEV_AUTO, 0 },
    540        1.5   nonaka 	{ NULL,		0 }
    541        1.5   nonaka };
    542        1.5   nonaka 
    543        1.1   nonaka void
    544        1.1   nonaka command_consdev(char *arg)
    545        1.1   nonaka {
    546        1.5   nonaka 	const struct cons_devs *cdp;
    547        1.5   nonaka 	char *sep, *sep2 = NULL;
    548        1.5   nonaka 	int ioport, speed = 0;
    549        1.5   nonaka 
    550        1.8   nonaka 	if (*arg == '\0') {
    551        1.8   nonaka 		efi_cons_show();
    552        1.8   nonaka 		return;
    553        1.8   nonaka 	}
    554        1.8   nonaka 
    555        1.5   nonaka 	sep = strchr(arg, ',');
    556        1.5   nonaka 	if (sep != NULL) {
    557        1.5   nonaka 		*sep++ = '\0';
    558        1.5   nonaka 		sep2 = strchr(sep, ',');
    559        1.8   nonaka 		if (sep2 != NULL)
    560        1.5   nonaka 			*sep2++ = '\0';
    561        1.5   nonaka 	}
    562        1.5   nonaka 
    563        1.5   nonaka 	for (cdp = cons_devs; cdp->name; cdp++) {
    564        1.5   nonaka 		if (strcmp(arg, cdp->name) == 0) {
    565        1.5   nonaka 			ioport = cdp->ioport;
    566        1.5   nonaka 			if (cdp->tag == CONSDEV_PC || cdp->tag == CONSDEV_AUTO) {
    567        1.5   nonaka 				if (sep != NULL || sep2 != NULL)
    568        1.5   nonaka 					goto error;
    569        1.5   nonaka 			} else {
    570        1.5   nonaka 				/* com? */
    571        1.5   nonaka 				if (ioport == -1) {
    572        1.5   nonaka 					if (sep != NULL) {
    573        1.5   nonaka 						u_long t = strtoul(sep, NULL, 0);
    574        1.5   nonaka 						if (t > INT_MAX)
    575        1.5   nonaka 							goto error;
    576        1.5   nonaka 						ioport = (int)t;
    577        1.5   nonaka 					}
    578        1.5   nonaka 					if (sep2 != NULL) {
    579        1.5   nonaka 						speed = atoi(sep2);
    580        1.5   nonaka 						if (speed < 0)
    581        1.5   nonaka 							goto error;
    582        1.5   nonaka 					}
    583        1.5   nonaka 				} else {
    584        1.5   nonaka 					if (sep != NULL) {
    585        1.5   nonaka 						speed = atoi(sep);
    586        1.5   nonaka 						if (speed < 0)
    587        1.5   nonaka 							goto error;
    588        1.5   nonaka 					}
    589        1.5   nonaka 					if (sep2 != NULL)
    590        1.5   nonaka 						goto error;
    591        1.5   nonaka 				}
    592        1.5   nonaka 			}
    593       1.16     manu 			efi_consinit(cdp->tag, ioport, speed);
    594        1.5   nonaka 			print_banner();
    595        1.5   nonaka 			return;
    596        1.5   nonaka 		}
    597        1.5   nonaka 	}
    598        1.5   nonaka error:
    599        1.5   nonaka 	printf("invalid console device.\n");
    600        1.1   nonaka }
    601        1.1   nonaka 
    602  1.17.12.1  thorpej void
    603  1.17.12.1  thorpej command_root(char *arg)
    604  1.17.12.1  thorpej {
    605  1.17.12.1  thorpej 	struct btinfo_rootdevice *biv = &bi_root;
    606  1.17.12.1  thorpej 
    607  1.17.12.1  thorpej 	strncpy(biv->devname, arg, sizeof(biv->devname));
    608  1.17.12.1  thorpej 	if (biv->devname[sizeof(biv->devname)-1] != '\0') {
    609  1.17.12.1  thorpej 		biv->devname[sizeof(biv->devname)-1] = '\0';
    610  1.17.12.1  thorpej 		printf("truncated to %s\n",biv->devname);
    611  1.17.12.1  thorpej 	}
    612  1.17.12.1  thorpej }
    613  1.17.12.1  thorpej 
    614  1.17.12.1  thorpej 
    615        1.1   nonaka #ifndef SMALL
    616        1.1   nonaka /* ARGSUSED */
    617        1.1   nonaka void
    618        1.1   nonaka command_menu(char *arg)
    619        1.1   nonaka {
    620        1.1   nonaka 
    621        1.1   nonaka 	if (bootcfg_info.nummenu > 0) {
    622        1.1   nonaka 		/* Does not return */
    623        1.1   nonaka 		doboottypemenu();
    624        1.1   nonaka 	} else
    625        1.1   nonaka 		printf("No menu defined in boot.cfg\n");
    626        1.1   nonaka }
    627        1.1   nonaka #endif /* !SMALL */
    628        1.1   nonaka 
    629        1.1   nonaka void
    630        1.1   nonaka command_modules(char *arg)
    631        1.1   nonaka {
    632        1.1   nonaka 
    633        1.1   nonaka 	if (strcmp(arg, "enabled") == 0 ||
    634        1.1   nonaka 	    strcmp(arg, "on") == 0)
    635        1.1   nonaka 		boot_modules_enabled = true;
    636        1.1   nonaka 	else if (strcmp(arg, "disabled") == 0 ||
    637        1.1   nonaka 	    strcmp(arg, "off") == 0)
    638        1.1   nonaka 		boot_modules_enabled = false;
    639        1.1   nonaka 	else
    640        1.1   nonaka 		printf("invalid flag, must be 'enabled' or 'disabled'.\n");
    641        1.1   nonaka }
    642        1.1   nonaka 
    643        1.1   nonaka void
    644        1.1   nonaka command_multiboot(char *arg)
    645        1.1   nonaka {
    646        1.1   nonaka 	char *filename;
    647        1.1   nonaka 
    648        1.1   nonaka 	filename = arg;
    649        1.1   nonaka 	if (exec_multiboot(filename, gettrailer(arg)) < 0)
    650        1.1   nonaka 		printf("multiboot: %s: %s\n", sprint_bootsel(filename),
    651        1.1   nonaka 		       strerror(errno));
    652        1.1   nonaka 	else
    653        1.1   nonaka 		printf("boot returned\n");
    654        1.1   nonaka }
    655        1.1   nonaka 
    656        1.1   nonaka void
    657        1.1   nonaka command_version(char *arg)
    658        1.1   nonaka {
    659        1.6   nonaka 	CHAR16 *path;
    660        1.8   nonaka 	char *upath, *ufirmware;
    661        1.8   nonaka 	int rv;
    662        1.1   nonaka 
    663        1.1   nonaka 	if (strcmp(arg, "full") == 0) {
    664        1.1   nonaka 		printf("ImageBase: 0x%" PRIxPTR "\n",
    665        1.1   nonaka 		    (uintptr_t)efi_li->ImageBase);
    666        1.1   nonaka 		printf("Stack: 0x%" PRIxPTR "\n", efi_main_sp);
    667        1.1   nonaka 		printf("EFI version: %d.%02d\n",
    668        1.1   nonaka 		    ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
    669        1.8   nonaka 		ufirmware = NULL;
    670        1.8   nonaka 		rv = ucs2_to_utf8(ST->FirmwareVendor, &ufirmware);
    671        1.8   nonaka 		if (rv == 0) {
    672        1.8   nonaka 			printf("EFI Firmware: %s (rev %d.%02d)\n", ufirmware,
    673        1.8   nonaka 			    ST->FirmwareRevision >> 16,
    674        1.8   nonaka 			    ST->FirmwareRevision & 0xffff);
    675        1.8   nonaka 			FreePool(ufirmware);
    676        1.8   nonaka 		}
    677        1.6   nonaka 		path = DevicePathToStr(efi_bootdp);
    678        1.8   nonaka 		upath = NULL;
    679        1.8   nonaka 		rv = ucs2_to_utf8(path, &upath);
    680        1.6   nonaka 		FreePool(path);
    681        1.8   nonaka 		if (rv == 0) {
    682        1.8   nonaka 			printf("Boot DevicePath: %d:%d:%s\n",
    683        1.8   nonaka 			    DevicePathType(efi_bootdp),
    684        1.8   nonaka 			    DevicePathSubType(efi_bootdp), upath);
    685        1.8   nonaka 			FreePool(upath);
    686        1.8   nonaka 		}
    687        1.1   nonaka 	}
    688        1.1   nonaka 
    689        1.1   nonaka 	printf("\n"
    690        1.1   nonaka 	    ">> %s, Revision %s (from NetBSD %s)\n"
    691        1.1   nonaka 	    ">> Memory: %d/%d k\n",
    692        1.1   nonaka 	    bootprog_name, bootprog_rev, bootprog_kernrev,
    693        1.1   nonaka 	    getbasemem(), getextmem());
    694        1.1   nonaka }
    695        1.1   nonaka 
    696        1.1   nonaka void
    697        1.1   nonaka command_memmap(char *arg)
    698        1.1   nonaka {
    699        1.1   nonaka 	bool sorted = true;
    700       1.13   nonaka 	bool compact = false;
    701        1.1   nonaka 
    702        1.1   nonaka 	if (*arg == '\0' || strcmp(arg, "sorted") == 0)
    703        1.1   nonaka 		/* Already sorted is true. */;
    704        1.1   nonaka 	else if (strcmp(arg, "unsorted") == 0)
    705        1.1   nonaka 		sorted = false;
    706       1.13   nonaka 	else if (strcmp(arg, "compact") == 0)
    707       1.13   nonaka 		compact = true;
    708        1.1   nonaka 	else {
    709        1.1   nonaka 		printf("invalid flag, "
    710       1.13   nonaka 		    "must be 'sorted', 'unsorted' or 'compact'.\n");
    711        1.1   nonaka 		return;
    712        1.1   nonaka 	}
    713        1.1   nonaka 
    714       1.13   nonaka 	efi_memory_show_map(sorted, compact);
    715        1.1   nonaka }
    716        1.1   nonaka 
    717        1.1   nonaka void
    718        1.1   nonaka command_devpath(char *arg)
    719        1.1   nonaka {
    720        1.1   nonaka 	EFI_STATUS status;
    721        1.1   nonaka 	UINTN i, nhandles;
    722        1.1   nonaka 	EFI_HANDLE *handles;
    723        1.1   nonaka 	EFI_DEVICE_PATH *dp0, *dp;
    724        1.1   nonaka 	CHAR16 *path;
    725        1.8   nonaka 	char *upath;
    726        1.1   nonaka 	UINTN cols, rows, row = 0;
    727        1.8   nonaka 	int rv;
    728        1.1   nonaka 
    729        1.1   nonaka 	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
    730        1.1   nonaka 	    ST->ConOut->Mode->Mode, &cols, &rows);
    731        1.1   nonaka 	if (EFI_ERROR(status) || rows <= 2)
    732        1.1   nonaka 		rows = 0;
    733        1.1   nonaka 	else
    734        1.1   nonaka 		rows -= 2;
    735        1.1   nonaka 
    736        1.1   nonaka 	/*
    737        1.1   nonaka 	 * all devices.
    738        1.1   nonaka 	 */
    739        1.1   nonaka 	status = LibLocateHandle(ByProtocol, &DevicePathProtocol, NULL,
    740        1.1   nonaka 	    &nhandles, &handles);
    741        1.1   nonaka 	if (EFI_ERROR(status))
    742        1.1   nonaka 		return;
    743        1.1   nonaka 
    744        1.1   nonaka 	for (i = 0; i < nhandles; i++) {
    745        1.1   nonaka 		status = uefi_call_wrapper(BS->HandleProtocol, 3, handles[i],
    746        1.1   nonaka 		    &DevicePathProtocol, (void **)&dp0);
    747        1.1   nonaka 		if (EFI_ERROR(status))
    748        1.1   nonaka 			break;
    749        1.1   nonaka 
    750        1.8   nonaka 		printf("DevicePathType %d\n", DevicePathType(dp0));
    751        1.7   nonaka 		if (++row >= rows) {
    752        1.7   nonaka 			row = 0;
    753        1.8   nonaka 			printf("Press Any Key to continue :");
    754        1.7   nonaka 			(void) awaitkey(-1, 0);
    755        1.8   nonaka 			printf("\n");
    756        1.7   nonaka 		}
    757        1.1   nonaka 		for (dp = dp0;
    758        1.1   nonaka 		     !IsDevicePathEnd(dp);
    759        1.1   nonaka 		     dp = NextDevicePathNode(dp)) {
    760        1.8   nonaka 
    761        1.1   nonaka 			path = DevicePathToStr(dp);
    762        1.8   nonaka 			upath = NULL;
    763        1.8   nonaka 			rv = ucs2_to_utf8(path, &upath);
    764        1.1   nonaka 			FreePool(path);
    765        1.8   nonaka 			if (rv) {
    766        1.8   nonaka 				printf("convert failed\n");
    767        1.8   nonaka 				break;
    768        1.8   nonaka 			}
    769        1.8   nonaka 
    770        1.8   nonaka 			printf("%d:%d:%s\n", DevicePathType(dp),
    771        1.8   nonaka 			    DevicePathSubType(dp), upath);
    772        1.8   nonaka 			FreePool(upath);
    773        1.1   nonaka 
    774        1.2      roy 			if (++row >= rows) {
    775        1.1   nonaka 				row = 0;
    776        1.8   nonaka 				printf("Press Any Key to continue :");
    777        1.1   nonaka 				(void) awaitkey(-1, 0);
    778        1.8   nonaka 				printf("\n");
    779        1.1   nonaka 			}
    780        1.1   nonaka 		}
    781        1.1   nonaka 	}
    782        1.1   nonaka }
    783        1.1   nonaka 
    784        1.8   nonaka 
    785        1.1   nonaka void
    786        1.1   nonaka command_efivar(char *arg)
    787        1.1   nonaka {
    788        1.8   nonaka 	static const char header[] =
    789        1.8   nonaka 	 "GUID                                 Variable Name        Value\n"
    790        1.8   nonaka 	 "==================================== ==================== ========\n";
    791        1.1   nonaka 	EFI_STATUS status;
    792        1.3   nonaka 	UINTN sz = 64, osz;
    793        1.8   nonaka 	CHAR16 *name = NULL, *tmp, *val, guid[128];
    794        1.8   nonaka 	char *uname, *uval, *uguid;
    795        1.1   nonaka 	EFI_GUID vendor;
    796        1.1   nonaka 	UINTN cols, rows, row = 0;
    797        1.8   nonaka 	int rv;
    798        1.1   nonaka 
    799        1.1   nonaka 	status = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut,
    800        1.1   nonaka 	    ST->ConOut->Mode->Mode, &cols, &rows);
    801        1.1   nonaka 	if (EFI_ERROR(status) || rows <= 2)
    802        1.1   nonaka 		rows = 0;
    803        1.1   nonaka 	else
    804        1.1   nonaka 		rows -= 2;
    805        1.1   nonaka 
    806        1.1   nonaka 	name = AllocatePool(sz);
    807        1.1   nonaka 	if (name == NULL) {
    808        1.8   nonaka 		printf("memory allocation failed: %" PRIuMAX" bytes\n",
    809        1.8   nonaka 		    (uintmax_t)sz);
    810        1.1   nonaka 		return;
    811        1.1   nonaka 	}
    812        1.1   nonaka 
    813        1.3   nonaka 	SetMem(name, sz, 0);
    814        1.1   nonaka 	vendor = NullGuid;
    815        1.1   nonaka 
    816        1.8   nonaka 	printf("%s", header);
    817        1.1   nonaka 	for (;;) {
    818        1.3   nonaka 		osz = sz;
    819        1.1   nonaka 		status = uefi_call_wrapper(RT->GetNextVariableName, 3,
    820        1.1   nonaka 		    &sz, name, &vendor);
    821        1.1   nonaka 		if (EFI_ERROR(status)) {
    822        1.1   nonaka 			if (status == EFI_NOT_FOUND)
    823        1.1   nonaka 				break;
    824        1.1   nonaka 			if (status != EFI_BUFFER_TOO_SMALL) {
    825        1.8   nonaka 				printf("GetNextVariableName failed: %" PRIxMAX "\n",
    826        1.8   nonaka 				    (uintmax_t)status);
    827        1.1   nonaka 				break;
    828        1.1   nonaka 			}
    829        1.1   nonaka 
    830        1.1   nonaka 			tmp = AllocatePool(sz);
    831        1.1   nonaka 			if (tmp == NULL) {
    832        1.8   nonaka 				printf("memory allocation failed: %" PRIuMAX
    833        1.8   nonaka 				    "bytes\n", (uintmax_t)sz);
    834        1.1   nonaka 				break;
    835        1.1   nonaka 			}
    836        1.3   nonaka 			SetMem(tmp, sz, 0);
    837        1.3   nonaka 			CopyMem(tmp, name, osz);
    838        1.1   nonaka 			FreePool(name);
    839        1.1   nonaka 			name = tmp;
    840        1.3   nonaka 			continue;
    841        1.1   nonaka 		}
    842        1.1   nonaka 
    843        1.1   nonaka 		val = LibGetVariable(name, &vendor);
    844        1.8   nonaka 		if (val != NULL) {
    845        1.8   nonaka 			uval = NULL;
    846        1.8   nonaka 			rv = ucs2_to_utf8(val, &uval);
    847        1.8   nonaka 			FreePool(val);
    848        1.8   nonaka 			if (rv) {
    849        1.8   nonaka 				printf("value convert failed\n");
    850        1.8   nonaka 				break;
    851        1.8   nonaka 			}
    852        1.8   nonaka 		} else
    853        1.8   nonaka 			uval = NULL;
    854        1.8   nonaka 		uname = NULL;
    855        1.8   nonaka 		rv = ucs2_to_utf8(name, &uname);
    856        1.8   nonaka 		if (rv) {
    857        1.8   nonaka 			printf("name convert failed\n");
    858        1.8   nonaka 			FreePool(uval);
    859        1.8   nonaka 			break;
    860        1.8   nonaka 		}
    861        1.8   nonaka 		GuidToString(guid, &vendor);
    862        1.8   nonaka 		uguid = NULL;
    863        1.8   nonaka 		rv = ucs2_to_utf8(guid, &uguid);
    864        1.8   nonaka 		if (rv) {
    865        1.8   nonaka 			printf("GUID convert failed\n");
    866        1.8   nonaka 			FreePool(uval);
    867        1.8   nonaka 			FreePool(uname);
    868        1.8   nonaka 			break;
    869        1.8   nonaka 		}
    870        1.8   nonaka 		printf("%-35s %-20s %s\n", uguid, uname, uval ? uval : "(null)");
    871        1.8   nonaka 		FreePool(uguid);
    872        1.8   nonaka 		FreePool(uname);
    873        1.8   nonaka 		if (uval != NULL)
    874        1.8   nonaka 			FreePool(uval);
    875        1.1   nonaka 
    876        1.2      roy 		if (++row >= rows) {
    877        1.1   nonaka 			row = 0;
    878        1.8   nonaka 			printf("Press Any Key to continue :");
    879        1.1   nonaka 			(void) awaitkey(-1, 0);
    880        1.8   nonaka 			printf("\n");
    881        1.1   nonaka 		}
    882        1.1   nonaka 	}
    883        1.1   nonaka 
    884        1.1   nonaka 	FreePool(name);
    885        1.1   nonaka }
    886