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

Collapse All | Expand All

(-)stand/efi/boot1/boot1.c (-26 / +491 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
}
219
}
178
220
179
/*
221
/*
222
 * Put back for boot partition menu support.
223
 * devpath_node_str is a basic output method for a devpath node which
224
 * only understands a subset of the available sub types.
225
 *
226
 * If we switch to UEFI 2.x then we should update it to use:
227
 * EFI_DEVICE_PATH_TO_TEXT_PROTOCOL.
228
 */
229
static int
230
devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
231
{
232
	switch (devpath->Type) {
233
	case MESSAGING_DEVICE_PATH:
234
		switch (devpath->SubType) {
235
		case MSG_ATAPI_DP: {
236
			ATAPI_DEVICE_PATH *atapi;
237
238
			atapi = (ATAPI_DEVICE_PATH *)(void *)devpath;
239
			return snprintf(buf, size, "ata(%s,%s,0x%x)",
240
			    (atapi->PrimarySecondary == 1) ?  "Sec" : "Pri",
241
			    (atapi->SlaveMaster == 1) ?  "Slave" : "Master",
242
			    atapi->Lun);
243
		}
244
		case MSG_USB_DP: {
245
			USB_DEVICE_PATH *usb;
246
247
			usb = (USB_DEVICE_PATH *)devpath;
248
			return snprintf(buf, size, "usb(0x%02x,0x%02x)",
249
			    usb->ParentPortNumber, usb->InterfaceNumber);
250
		}
251
		case MSG_SCSI_DP: {
252
			SCSI_DEVICE_PATH *scsi;
253
254
			scsi = (SCSI_DEVICE_PATH *)(void *)devpath;
255
			return snprintf(buf, size, "scsi(0x%02x,0x%02x)",
256
			    scsi->Pun, scsi->Lun);
257
		}
258
		case MSG_SATA_DP: {
259
			SATA_DEVICE_PATH *sata;
260
261
			sata = (SATA_DEVICE_PATH *)(void *)devpath;
262
			return snprintf(buf, size, "sata(0x%x,0x%x,0x%x)",
263
			    sata->HBAPortNumber, sata->PortMultiplierPortNumber,
264
			    sata->Lun);
265
		}
266
		default:
267
			return snprintf(buf, size, "msg(0x%02x)",
268
			    devpath->SubType);
269
		}
270
		break;
271
	case HARDWARE_DEVICE_PATH:
272
		switch (devpath->SubType) {
273
		case HW_PCI_DP: {
274
			PCI_DEVICE_PATH *pci;
275
276
			pci = (PCI_DEVICE_PATH *)devpath;
277
			return snprintf(buf, size, "pci(0x%02x,0x%02x)",
278
			    pci->Device, pci->Function);
279
		}
280
		default:
281
			return snprintf(buf, size, "hw(0x%02x)",
282
			    devpath->SubType);
283
		}
284
		break;
285
	case ACPI_DEVICE_PATH: {
286
		ACPI_HID_DEVICE_PATH *acpi;
287
288
		acpi = (ACPI_HID_DEVICE_PATH *)(void *)devpath;
289
		if ((acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
290
			switch (EISA_ID_TO_NUM(acpi->HID)) {
291
			case 0x0a03:
292
				return snprintf(buf, size, "pciroot(0x%x)",
293
				    acpi->UID);
294
			case 0x0a08:
295
				return snprintf(buf, size, "pcieroot(0x%x)",
296
				    acpi->UID);
297
			case 0x0604:
298
				return snprintf(buf, size, "floppy(0x%x)",
299
				    acpi->UID);
300
			case 0x0301:
301
				return snprintf(buf, size, "keyboard(0x%x)",
302
				    acpi->UID);
303
			case 0x0501:
304
				return snprintf(buf, size, "serial(0x%x)",
305
				    acpi->UID);
306
			case 0x0401:
307
				return snprintf(buf, size, "parallelport(0x%x)",
308
				    acpi->UID);
309
			default:
310
				return snprintf(buf, size, "acpi(pnp%04x,0x%x)",
311
				    EISA_ID_TO_NUM(acpi->HID), acpi->UID);
312
			}
313
		}
314
315
		return snprintf(buf, size, "acpi(0x%08x,0x%x)", acpi->HID,
316
		    acpi->UID);
317
	}
318
	case MEDIA_DEVICE_PATH:
319
		switch (devpath->SubType) {
320
		case MEDIA_CDROM_DP: {
321
			CDROM_DEVICE_PATH *cdrom;
322
323
			cdrom = (CDROM_DEVICE_PATH *)(void *)devpath;
324
			return snprintf(buf, size, "cdrom(%x)",
325
			    cdrom->BootEntry);
326
		}
327
		case MEDIA_HARDDRIVE_DP: {
328
			HARDDRIVE_DEVICE_PATH *hd;
329
330
			hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
331
			return snprintf(buf, size, "hd(p%d) (%s)",
332
			    hd->PartitionNumber,
333
			    humanize_number_kmgt(hd->PartitionSize * 512));
334
		}
335
		default:
336
			return snprintf(buf, size, "media(0x%02x)",
337
			    devpath->SubType);
338
		}
339
	case BBS_DEVICE_PATH:
340
		return snprintf(buf, size, "bbs(0x%02x)", devpath->SubType);
341
	case END_DEVICE_PATH_TYPE:
342
		return (0);
343
	}
344
345
	return snprintf(buf, size, "type(0x%02x, 0x%02x)", devpath->Type,
346
	    devpath->SubType);
347
}
348
349
/*
350
 * devpath_strlcat appends a text description of devpath to buf but not more
351
 * than size - 1 characters followed by NUL-terminator.
352
 */
353
int
354
devpath_strlcat(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
355
{
356
	size_t len, used;
357
	const char *sep;
358
359
	sep = "";
360
	used = 0;
361
	while (!IsDevicePathEnd(devpath)) {
362
		len = snprintf(buf, size - used, "%s", sep);
363
		used += len;
364
		if (used > size)
365
			return (used);
366
		buf += len;
367
368
		len = devpath_node_str(buf, size - used, devpath);
369
		used += len;
370
		if (used > size)
371
			return (used);
372
		buf += len;
373
		devpath = NextDevicePathNode(devpath);
374
		sep = ":";
375
	}
376
377
	return (used);
378
}
379
380
/*
381
 * devpath_str is convenience method which returns the text description of
382
 * devpath using a static buffer, so it isn't thread safe!
383
 */
384
char *
385
devpath_str(EFI_DEVICE_PATH *devpath)
386
{
387
	static char buf[256];
388
389
	devpath_strlcat(buf, sizeof(buf), devpath);
390
391
	return buf;
392
}
393
394
395
396
/*
180
 * load_loader attempts to load the loader image data.
397
 * load_loader attempts to load the loader image data.
181
 *
398
 *
182
 * It tries each module and its respective devices, identified by mod->probe,
399
 * 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)
627
try_boot(void)
220
{
628
{
221
	size_t bufsize, loadersize, cmdsize;
629
	size_t bufsize, loadersize, cmdsize;
222
	void *buf, *loaderbuf;
630
	void *buf = NULL, *loaderbuf = NULL;	/* For boot partition menu */
223
	char *cmd;
631
	char *cmd;
224
	dev_info_t *dev;
632
	dev_info_t *dev;
225
	const boot_module_t *mod;
633
	const boot_module_t *mod;
226
	EFI_HANDLE loaderhandle;
634
	EFI_HANDLE loaderhandle;
227
	EFI_LOADED_IMAGE *loaded_image;
635
	EFI_LOADED_IMAGE *loaded_image;
228
	EFI_STATUS status;
636
	EFI_STATUS status;
637
	int ndevs;	/* For boot partition menu */
638
639
	/* For boot partition menu */
640
	ndevs = list_devices();
641
	status = select_bootdev(ndevs, &mod, &dev, &loaderbuf, &loadersize);	
229
642
230
	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
231
	if (status != EFI_SUCCESS) {
643
	if (status != EFI_SUCCESS) {
232
		status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
644
	/* For boot partition menu */
233
		    FALSE);
645
		printf("Failed to load '%s'\n", PATH_LOADER_EFI);
234
		if (status != EFI_SUCCESS) {
646
		return (EFI_NOT_FOUND);
235
			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
236
			return (status);
237
		}
238
	}
647
	}
239
648
240
	/*
649
	/*
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, 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, 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 451-463 efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_T Link Here
451
	 * Reset the console enable the cursor. Later we'll choose a bette
845
	 * Reset the console enable the cursor. Later we'll choose a bette
452
	 * console size through GOP/UGA.
846
	 * console size through GOP/UGA.
453
	 */
847
	 */
848
	conin = ST->ConIn;
454
	conout = ST->ConOut;
849
	conout = ST->ConOut;
850
	conin->Reset(conin, TRUE);
455
	conout->Reset(conout, TRUE);
851
	conout->Reset(conout, TRUE);
456
	/* Explicitly set conout to mode 0, 80x25 */
852
	/* Explicitly set conout to mode 0, 80x25 */
457
	conout->SetMode(conout, 0);
853
	conout->SetMode(conout, 0);
854
855
	conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
856
	    DEFAULT_BGCOLOR));
458
	conout->EnableCursor(conout, TRUE);
857
	conout->EnableCursor(conout, TRUE);
459
	conout->ClearScreen(conout);
858
	conout->ClearScreen(conout);
460
859
860
	return (status);
861
}
862
863
EFI_STATUS
864
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
865
{
866
	EFI_HANDLE *handles;
867
	EFI_LOADED_IMAGE *img;
868
	EFI_DEVICE_PATH *imgpath;
869
	EFI_STATUS status;
870
	UINTN i, hsize, nhandles;
871
	CHAR16 *text;
872
	UINT16 boot_current;
873
	size_t sz;
874
	UINT16 boot_order[100];
875
876
	/* Basic initialization*/
877
	ST = Xsystab;
878
	IH = Ximage;
879
	BS = Xsystab->BootServices;
880
	RS = ST->RuntimeServices;
881
882
	init_console();
883
461
	printf("\n>> FreeBSD EFI boot block\n");
884
	printf("\n>> FreeBSD EFI boot block\n");
462
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
885
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
463
	printf("   Initializing modules:");
886
	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
}
1091

Return to bug 207940