View | Details | Raw Unified | Return to bug 207940 | Differences between
and this patch

Collapse All | Expand All

(-)stand/efi/boot1/boot1.c (-26 / +493 lines)
Lines 29-34 Link Here
29
29
30
#include <efi.h>
30
#include <efi.h>
31
#include <eficonsctl.h>
31
#include <eficonsctl.h>
32
#include <efilib.h>
32
#include <efichar.h>
33
#include <efichar.h>
33
34
34
#include "boot_module.h"
35
#include "boot_module.h"
Lines 50-60 static const boot_module_t *boot_modules Link Here
50
/* The initial number of handles used to query EFI for partitions. */
51
/* The initial number of handles used to query EFI for partitions. */
51
#define NUM_HANDLES_INIT	24
52
#define NUM_HANDLES_INIT	24
52
53
54
/* For boot partition menu */
55
static int devpath_node_str(char *, size_t, EFI_DEVICE_PATH *);
56
int devpath_strlcat(char *, size_t, EFI_DEVICE_PATH *);
57
char *devpath_str(EFI_DEVICE_PATH *);
58
void efi_cons_putchar(int);
59
int efi_cons_getchar(void);
60
int efi_cons_poll(void);
61
int getchar(void);
62
char *humanize_number_kmgt(UINT64);
63
static SIMPLE_TEXT_OUTPUT_INTERFACE	*conout;
64
static SIMPLE_INPUT_INTERFACE		*conin;
65
53
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
66
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
54
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
67
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
55
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
68
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
56
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
69
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
57
70
71
#define DEFAULT_FGCOLOR EFI_LIGHTGRAY
72
#define DEFAULT_BGCOLOR EFI_BLACK
73
74
/* For boot partition menu */
75
char *humanize_number_kmgt(UINT64 size) {
76
	static char buf2[6];
77
	UINT64 size0;
78
79
	if (size < 1024)
80
		sprintf(buf2, "%luB", size);
81
	else if (size0 = (size*10+512)/1024, size0 < 100)
82
		sprintf(buf2, "%lu.%luK", size0 / 10, size0 % 10);
83
	else if (size0 = (size+512)/1024, size0 < 1024)
84
		sprintf(buf2, "%luK", size0);
85
	else if (size0 = (size*10/1024+512)/1024, size0 < 100)
86
		sprintf(buf2, "%lu.%luM", size0 / 10, size0 % 10);
87
	else if (size0 = (size/1024+512)/1024, size0 < 1024)
88
		sprintf(buf2, "%luM", size0);
89
	else if (size0 = (size*10/1024/1024+512)/1024, size0 < 100)
90
		sprintf(buf2, "%lu.%luG", size0 / 10, size0 % 10);
91
	else if (size0 = (size/1024/1024+512)/1024, size0 < 1024)
92
		sprintf(buf2, "%luG", size0);
93
	else if (size0 = (size*10/1024/1024/1024+512)/1024, size0 < 100)
94
		sprintf(buf2, "%lu.%luT", size0 / 10, size0 % 10);
95
	else
96
		sprintf(buf2, "%luT", (size/1024/1024/1024+512)/1024);
97
	return(buf2);
98
}
99
58
/*
100
/*
59
 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
101
 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
60
 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
102
 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
Lines 177-182 devpath_last(EFI_DEVICE_PATH *devpath) Link Here
177
}
218
}
178
219
179
/*
220
/*
221
 * Put back for boot partition menu support.
222
 * devpath_node_str is a basic output method for a devpath node which
223
 * only understands a subset of the available sub types.
224
 *
225
 * If we switch to UEFI 2.x then we should update it to use:
226
 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
227
 */
228
static int
229
devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
230
{
231
	switch (devpath->Type) {
232
	case MESSAGING_DEVICE_PATH:
233
		switch (devpath->SubType) {
234
		case MSG_ATAPI_DP: {
235
			ATAPI_DEVICE_PATH *atapi;
236
237
			atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
238
			return snprintf(buf, size, "ata(%s,%s,0x%x)",
239
			    (atapi->PrimarySecondary == 1) ?  "Sec" : "Pri",
240
			    (atapi->SlaveMaster == 1) ?  "Slave" : "Master",
241
			    atapi->Lun);
242
		}
243
		case MSG_USB_DP: {
244
			USB_DEVICE_PATH *usb;
245
246
			usb = (USB_DEVICE_PATH *)devpath;
247
			return snprintf(buf, size, "usb(0x%02x,0x%02x)",
248
			    usb->ParentPortNumber, usb->InterfaceNumber);
249
		}
250
		case MSG_SCSI_DP: {
251
			SCSI_DEVICE_PATH *scsi;
252
253
			scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
254
			return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
255
			    scsi->Pun, scsi->Lun);
256
		}
257
		case MSG_SATA_DP: {
258
			SATA_DEVICE_PATH *sata;
259
260
			sata = (SATA_DEVICE_PATH *)(void *)devpath;
261
			return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
262
			    sata->HBAPortNumber, sata->PortMultiplierPortNumber,
263
			    sata->Lun);
264
		}
265
		default:
266
			return snprintf(buf, size, "msg(0x%02x)",
267
			    devpath->SubType);
268
		}
269
		break;
270
	case HARDWARE_DEVICE_PATH:
271
		switch (devpath->SubType) {
272
		case HW_PCI_DP: {
273
			PCI_DEVICE_PATH *pci;
274
275
			pci = (PCI_DEVICE_PATH *)devpath;
276
			return snprintf(buf, size, "pci(0x%02x,0x%02x)",
277
			    pci->Device, pci->Function);
278
		}
279
		default:
280
			return snprintf(buf, size, "hw(0x%02x)",
281
			    devpath->SubType);
282
		}
283
		break;
284
	case ACPI_DEVICE_PATH: {
285
		ACPI_HID_DEVICE_PATH *acpi;
286
287
		acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
288
		if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
289
			switch (EISA_ID_TO_NUM(acpi->HID)) {
290
			case 0x0a03:
291
				return snprintf(buf, size, "pciroot(0x%x)",
292
				    acpi->UID);
293
			case 0x0a08:
294
				return snprintf(buf, size, "pcieroot(0x%x)",
295
				    acpi->UID);
296
			case 0x0604:
297
				return snprintf(buf, size, "floppy(0x%x)",
298
				    acpi->UID);
299
			case 0x0301:
300
				return snprintf(buf, size, "keyboard(0x%x)",
301
				    acpi->UID);
302
			case 0x0501:
303
				return snprintf(buf, size, "serial(0x%x)",
304
				    acpi->UID);
305
			case 0x0401:
306
				return snprintf(buf, size, "parallelport(0x%x)",
307
				    acpi->UID);
308
			default:
309
				return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
310
				    EISA_ID_TO_NUM(acpi->HID), acpi->UID);
311
			}
312
		}
313
314
		return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
315
		    acpi->UID);
316
	}
317
	case MEDIA_DEVICE_PATH:
318
		switch (devpath->SubType) {
319
		case MEDIA_CDROM_DP: {
320
			CDROM_DEVICE_PATH *cdrom;
321
322
			cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
323
			return snprintf(buf, size, "cdrom(%x)",
324
			    cdrom->BootEntry);
325
		}
326
		case MEDIA_HARDDRIVE_DP: {
327
			HARDDRIVE_DEVICE_PATH *hd;
328
329
			hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
330
			return snprintf(buf, size, "hd(p%d) (%s)",
331
			    hd->PartitionNumber,
332
			    humanize_number_kmgt(hd->PartitionSize * 512));
333
		}
334
		default:
335
			return snprintf(buf, size, "media(0x%02x)",
336
			    devpath->SubType);
337
		}
338
	case BBS_DEVICE_PATH:
339
		return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
340
	case END_DEVICE_PATH_TYPE:
341
		return (0);
342
	}
343
344
	return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
345
	    devpath->SubType);
346
}
347
348
/*
349
 * devpath_strlcat appends a text description of devpath to buf but not more
350
 * than size - 1 characters followed by NUL-terminator.
351
 */
352
int
353
devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
354
{
355
	size_t len, used;
356
	const char *sep;
357
358
	sep = "";
359
	used = 0;
360
	while (!IsDevicePathEnd(devpath)) {
361
		len = snprintf(buf, size - used, "%s", sep);
362
		used += len;
363
		if (used > size)
364
			return (used);
365
		buf += len;
366
367
		len = devpath_node_str(buf, size - used, devpath);
368
		used += len;
369
		if (used > size)
370
			return (used);
371
		buf += len;
372
		devpath = NextDevicePathNode(devpath);
373
		sep = ":";
374
	}
375
376
	return (used);
377
}
378
379
/*
380
 * devpath_str is convenience method which returns the text description of
381
 * devpath using a static buffer, so it isn't thread safe!
382
 */
383
char *
384
devpath_str(EFI_DEVICE_PATH *devpath)
385
{
386
	static char buf[256];
387
388
	devpath_strlcat(buf, sizeof(buf), devpath);
389
390
	return buf;
391
}
392
393
394
395
/*
180
 * load_loader attempts to load the loader image data.
396
 * load_loader attempts to load the loader image data.
181
 *
397
 *
182
 * It tries each module and its respective devices, identified by mod->probe,
398
 * It tries each module and its respective devices, identified by mod->probe,
Lines 211-216 load_loader(const boot_module_t **modp, Link Here
211
	return (EFI_NOT_FOUND);
428
	return (EFI_NOT_FOUND);
212
}
429
}
213
430
431
/* For boot partition menu */
432
/* quick dirty work. */
433
#define	NUM_DEV_LIST	35
434
435
typedef struct {
436
	const boot_module_t	*modp;
437
	dev_info_t		*devinfop;
438
} moddev_t;
439
440
static moddev_t dev_list[NUM_DEV_LIST];
441
442
static int
443
list_devices(void)
444
{
445
	UINTN i, j;
446
	dev_info_t *dev;
447
	const boot_module_t *mod;
448
449
	j = 0;
450
	for (i = 0; i < NUM_BOOT_MODULES; i++) {
451
		if (boot_modules[i] == NULL)
452
			continue;
453
		mod = boot_modules[i];
454
		for (dev = mod->devices(); dev != NULL; dev = dev->next) {
455
			dev_list[j].devinfop = dev;
456
			dev_list[j].modp = mod;
457
			j++;
458
			if (j >= NUM_DEV_LIST)
459
			    break;
460
		}
461
	}
462
463
	return (j);
464
}
465
466
#define	SELECT_TIMEOUT	10
467
468
static char
469
idx2char(int i)
470
{
471
	return (i<10 ? '0'+i : 'a'+i-10);
472
}
473
474
static int
475
char2idx(char c)
476
{
477
	return ((c >= '0' && c <= '9') ? c - '0' :
478
	    (c >= 'A' && c <= 'Z') ? c - 'A' + 10 :
479
	    (c >= 'a' && c <= 'z') ? c - 'a' + 10 :
480
	    -1 );
481
}
482
483
static void
484
move_to_tol()
485
{
486
	int x,y;
487
488
	x = conout->Mode->CursorColumn;
489
	y = conout->Mode->CursorRow;
490
	conout->SetCursorPosition(conout, 0, y);
491
}
492
493
static EFI_STATUS
494
select_bootdev(int ndevs, const boot_module_t **modp, dev_info_t **devinfop,
495
    void **bufp, size_t *bufsize)
496
{
497
	int i;
498
	int c, n;
499
	int time_left;
500
	EFI_STATUS status;
501
	EFI_EVENT timer;
502
	EFI_EVENT events[2];
503
	UINTN idx;
504
	dev_info_t *dev;
505
	const boot_module_t *mod;
506
507
	if ((ndevs <= 0) || (ndevs >= NUM_DEV_LIST)) {
508
		return (EFI_NOT_FOUND);
509
	} else if (ndevs == 1) {
510
		/* Only one condidate. */
511
		*modp = mod = dev_list[0].modp;
512
		*devinfop = dev = dev_list[0].devinfop;
513
		return (mod->load(PATH_LOADER_EFI, dev,
514
			 bufp, bufsize));
515
	}
516
	/* Two or more candidate exist. */
517
	status = BS->CreateEvent(EVT_TIMER, 0, 0, NULL, &timer);
518
	if (status != EFI_SUCCESS) {
519
		printf("Can't allocate timer event.\n");
520
		return (status);
521
	}
522
	printf("  0: AutoSelected Partition (Default): 0\n"); 
523
	for (i = 0; i < ndevs; i++) {
524
		if (dev_list[i].devinfop->preferred == TRUE)
525
			c = '*';
526
		else
527
			c = ' ';
528
		printf(" %c%c: %s: %s: %c\n", c, idx2char(i+1),
529
		    dev_list[i].modp->name,
530
		    devpath_str(dev_list[i].devinfop->devpath),
531
			idx2char(i+1));
532
	}
533
	/* One alpha-num selection only. Is this big enough ?? */
534
	BS->SetTimer(timer, TimerPeriodic, 10000000); 
535
	events[0] = timer;
536
	events[1] = conin->WaitForKey;
537
	time_left = SELECT_TIMEOUT;
538
539
	while (1) {
540
		if (time_left > 0) {
541
			printf("Select from 0 to %c. Timeout in %2d seconds,"
542
			       " [Space] to pause : ",
543
			       idx2char(ndevs), time_left);
544
		}
545
		status = BS->WaitForEvent(2, events, &idx);
546
		if (status != EFI_SUCCESS) {
547
			BS->CloseEvent(timer);
548
			return (status);
549
		}
550
		if (idx == 0) {
551
			time_left--;
552
			if (time_left <=0) {
553
				printf("\nTimeout. "
554
				       "Partition is AutoSelected.\n");
555
				n = 0;
556
				break;
557
			} else {
558
				move_to_tol();
559
			}
560
		}
561
		if (idx == 1) {
562
			c = getchar();
563
			if ((c == '\n') || (c == '\r')) {
564
				putchar('\n');
565
				n = 0;
566
				break;
567
			} else if ((time_left > 0) && (c == ' ')) {
568
				BS->SetTimer(timer, TimerCancel, 0); 
569
				time_left = -1;
570
				printf("\nTimer stopeed.\n Please Key in: ");
571
			}
572
			n = char2idx(c);
573
			if ((n >= 0) && (n <= ndevs)) {
574
				BS->SetTimer(timer, TimerCancel, 0); 
575
				time_left = -1;
576
				printf("\n %c is selected.\n", c);
577
				if (n == 0) { /* AutoSelect */
578
					break;
579
				} else {
580
					mod = dev_list[n-1].modp;
581
					dev = dev_list[n-1].devinfop;
582
					status = mod->load(PATH_LOADER_EFI,
583
							   dev, bufp, bufsize);
584
					if (status == EFI_SUCCESS) {
585
						break;
586
					}
587
					printf("Failed to load '%s'\n",
588
						 PATH_LOADER_EFI);
589
					printf("Please select again: ");
590
				}
591
			} else {
592
				/* Invalid charecter. */
593
				move_to_tol();
594
			}
595
		}
596
	};
597
	BS->CloseEvent(timer);
598
	if (n == 0) { /* AutoSelect */
599
		status = load_loader(modp, devinfop, bufp, bufsize, TRUE);
600
		if (status != EFI_SUCCESS) {
601
			status = load_loader(modp, devinfop, bufp, bufsize,
602
			    FALSE);
603
		}
604
	} else {
605
		*modp = dev_list[n-1].modp;
606
		*devinfop = dev_list[n-1].devinfop;
607
		status = EFI_SUCCESS;
608
	}
609
	return (status);
610
}
611
214
/*
612
/*
215
 * try_boot only returns if it fails to load the loader. If it succeeds
613
 * try_boot only returns if it fails to load the loader. If it succeeds
216
 * it simply boots, otherwise it returns the status of last EFI call.
614
 * it simply boots, otherwise it returns the status of last EFI call.
Lines 219-240 static EFI_STATUS Link Here
219
try_boot(void)
617
try_boot(void)
220
{
618
{
221
	size_t bufsize, loadersize, cmdsize;
619
	size_t bufsize, loadersize, cmdsize;
222
	void *buf, *loaderbuf;
620
	void *buf = NULL, *loaderbuf = NULL;	/* For boot partition menu */
223
	char *cmd;
621
	char *cmd;
224
	dev_info_t *dev;
622
	dev_info_t *dev;
225
	const boot_module_t *mod;
623
	const boot_module_t *mod;
226
	EFI_HANDLE loaderhandle;
624
	EFI_HANDLE loaderhandle;
227
	EFI_LOADED_IMAGE *loaded_image;
625
	EFI_LOADED_IMAGE *loaded_image;
228
	EFI_STATUS status;
626
	EFI_STATUS status;
627
	int ndevs;	/* For boot partition menu */
628
629
	/* For boot partition menu */
630
	ndevs = list_devices();
631
	status = select_bootdev(ndevs, &mod, &dev, &loaderbuf, &loadersize);	
229
632
230
	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
231
	if (status != EFI_SUCCESS) {
633
	if (status != EFI_SUCCESS) {
232
		status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
634
	/* For boot partition menu */
233
		    FALSE);
635
		printf("Failed to load '%s'\n", PATH_LOADER_EFI);
234
		if (status != EFI_SUCCESS) {
636
		return (EFI_NOT_FOUND);
235
			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
236
			return (status);
237
		}
238
	}
637
	}
239
638
240
	/*
639
	/*
Lines 284-289 try_boot(void) Link Here
284
	loaded_image->LoadOptionsSize = cmdsize;
683
	loaded_image->LoadOptionsSize = cmdsize;
285
	loaded_image->LoadOptions = cmd;
684
	loaded_image->LoadOptions = cmd;
286
685
686
	/* For boot partition menu */
687
	printf("Boot from: %s in 1 second\n", devpath_str(dev->devpath));
688
	BS->Stall(1000000);
689
287
	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
690
	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
288
	DSTALL(1000000);
691
	DSTALL(1000000);
289
	DPRINTF(".");
692
	DPRINTF(".");
Lines 420-445 probe_handle_status(EFI_HANDLE h, EFI_DE Link Here
420
	DSTALL(500000);
823
	DSTALL(500000);
421
}
824
}
422
825
423
EFI_STATUS
826
424
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
827
/* Divide efi_main into two for boot partition menu */
828
static EFI_STATUS
829
init_console()
425
{
830
{
426
	EFI_HANDLE *handles;
427
	EFI_LOADED_IMAGE *img;
428
	EFI_DEVICE_PATH *imgpath;
429
	EFI_STATUS status;
831
	EFI_STATUS status;
430
	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
832
	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
431
	SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
432
	UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
433
	CHAR16 *text;
434
	UINT16 boot_current;
435
	size_t sz;
436
	UINT16 boot_order[100];
437
833
438
	/* Basic initialization*/
834
	UINTN i, max_dim, best_mode, cols, rows;
439
	ST = Xsystab;
440
	IH = Ximage;
441
	BS = ST->BootServices;
442
	RS = ST->RuntimeServices;
443
835
444
	/* Set up the console, so printf works. */
836
	/* Set up the console, so printf works. */
445
	status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
837
	status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
Lines 450-457 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_T Link Here
450
	/*
845
	/*
451
	 * Reset the console and find the best text mode.
846
	 * Reset the console and find the best text mode.
452
	 */
847
	 */
848
	conin = ST->ConIn;
453
	conout = ST->ConOut;
849
	conout = ST->ConOut;
850
	conin->Reset(conin, TRUE);
454
	conout->Reset(conout, TRUE);
851
	conout->Reset(conout, TRUE);
852
	/* Explicitly set conout to mode 0, 80x25 */
853
	conout->SetMode(conout, 0);
854
455
	max_dim = best_mode = 0;
855
	max_dim = best_mode = 0;
456
	for (i = 0; ; i++) {
856
	for (i = 0; ; i++) {
457
		status = conout->QueryMode(conout, i, &cols, &rows);
857
		status = conout->QueryMode(conout, i, &cols, &rows);
Lines 464-472 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_T Link Here
464
	}
862
	}
465
	if (max_dim > 0)
863
	if (max_dim > 0)
466
		conout->SetMode(conout, best_mode);
864
		conout->SetMode(conout, best_mode);
865
866
	conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
867
	    DEFAULT_BGCOLOR));
467
	conout->EnableCursor(conout, TRUE);
868
	conout->EnableCursor(conout, TRUE);
468
	conout->ClearScreen(conout);
869
	conout->ClearScreen(conout);
469
870
871
	return (status);
872
}
873
874
EFI_STATUS
875
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
876
{
877
	EFI_HANDLE *handles;
878
	EFI_LOADED_IMAGE *img;
879
	EFI_DEVICE_PATH *imgpath;
880
	EFI_STATUS status;
881
	UINTN i, hsize, nhandles;
882
	CHAR16 *text;
883
	UINT16 boot_current;
884
	size_t sz;
885
	UINT16 boot_order[100];
886
887
	/* Basic initialization*/
888
	ST = Xsystab;
889
	IH = Ximage;
890
	BS = Xsystab->BootServices;
891
	RS = ST->RuntimeServices;
892
893
	init_console();
894
470
	printf("\n>> FreeBSD EFI boot block\n");
895
	printf("\n>> FreeBSD EFI boot block\n");
471
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
896
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
472
	printf("   Initializing modules:");
897
	printf("   Initializing modules:");
Lines 609-625 efi_panic(EFI_STATUS s, const char *fmt, Link Here
609
	BS->Exit(IH, s, 0, NULL);
1031
	BS->Exit(IH, s, 0, NULL);
610
}
1032
}
611
1033
1034
/* Make putchar as wrapper for newly added efi_cons_putchar() for boot partition menu */
612
void
1035
void
613
putchar(int c)
1036
putchar(int c)
614
{
1037
{
1038
	efi_cons_putchar(c);
1039
}
1040
1041
void
1042
efi_cons_putchar(int c)
1043
{
615
	CHAR16 buf[2];
1044
	CHAR16 buf[2];
616
1045
617
	if (c == '\n') {
1046
	if (c == '\n') {
618
		buf[0] = '\r';
1047
		buf[0] = '\r';
619
		buf[1] = 0;
1048
		buf[1] = 0;
620
		ST->ConOut->OutputString(ST->ConOut, buf);
1049
		conout->OutputString(conout, buf);
621
	}
1050
	}
622
	buf[0] = c;
1051
	buf[0] = c;
623
	buf[1] = 0;
1052
	buf[1] = 0;
624
	ST->ConOut->OutputString(ST->ConOut, buf);
1053
	conout->OutputString(conout, buf);
1054
}
1055
1056
int
1057
getchar(void)
1058
{
1059
	return efi_cons_getchar();
625
}
1060
}
1061
1062
1063
int
1064
efi_cons_getchar()
1065
{
1066
	EFI_INPUT_KEY key;
1067
	EFI_STATUS status;
1068
	UINTN junk;
1069
1070
	/* Try to read a key stroke. We wait for one if none is pending. */
1071
	status = conin->ReadKeyStroke(conin, &key);
1072
	if (status == EFI_NOT_READY) {
1073
		BS->WaitForEvent(1, &conin->WaitForKey, &junk);
1074
		status = conin->ReadKeyStroke(conin, &key);
1075
	}
1076
	switch (key.ScanCode) {
1077
	case 0x17: /* ESC */
1078
		return (0x1b);  /* esc */
1079
	}
1080
1081
	/* this can return  */
1082
	return (key.UnicodeChar);
1083
}
1084
1085
int
1086
efi_cons_poll()
1087
{
1088
	/* This can clear the signaled state. */
1089
	return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS);
1090
}

Return to bug 207940