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

Collapse All | Expand All

(-)sys/boot/efi/boot1/boot1.c (-24 / +302 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
33
33
#include "boot_module.h"
34
#include "boot_module.h"
34
#include "paths.h"
35
#include "paths.h"
Lines 47-58 Link Here
47
/* The initial number of handles used to query EFI for partitions. */
48
/* The initial number of handles used to query EFI for partitions. */
48
#define NUM_HANDLES_INIT	24
49
#define NUM_HANDLES_INIT	24
49
50
51
void efi_cons_putchar(int);
52
int efi_cons_getchar(void);
53
int efi_cons_poll(void);
54
int getchar(void);
50
void putchar(int c);
55
void putchar(int c);
56
char *humanize_number_kmgt(UINT64);
51
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
57
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
52
58
53
EFI_SYSTEM_TABLE *systab;
59
EFI_SYSTEM_TABLE *systab;
54
EFI_BOOT_SERVICES *bs;
60
EFI_BOOT_SERVICES *bs;
55
static EFI_HANDLE *image;
61
static EFI_HANDLE *image;
62
static SIMPLE_TEXT_OUTPUT_INTERFACE	*conout;
63
static SIMPLE_INPUT_INTERFACE		*conin;
56
64
57
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
65
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
58
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
66
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
Lines 59-64 Link Here
59
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
67
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
60
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
68
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
61
69
70
71
#define DEFAULT_FGCOLOR EFI_LIGHTGRAY
72
#define DEFAULT_BGCOLOR EFI_BLACK
73
74
char *humanize_number_kmgt(UINT64 size) {
75
	static char buf2[6];
76
	UINT64 size0;
77
78
	if (size < 1024)
79
		sprintf(buf2, "%luB", size);
80
	else if (size0 = (size*10+512)/1024, size0 < 100)
81
		sprintf(buf2, "%lu.%luK", size0 / 10, size0 % 10);
82
	else if (size0 = (size+512)/1024, size0 < 1024)
83
		sprintf(buf2, "%luK", size0);
84
	else if (size0 = (size*10/1024+512)/1024, size0 < 100)
85
		sprintf(buf2, "%lu.%luM", size0 / 10, size0 % 10);
86
	else if (size0 = (size/1024+512)/1024, size0 < 1024)
87
		sprintf(buf2, "%luM", size0);
88
	else if (size0 = (size*10/1024/1024+512)/1024, size0 < 100)
89
		sprintf(buf2, "%lu.%luG", size0 / 10, size0 % 10);
90
	else if (size0 = (size/1024/1024+512)/1024, size0 < 1024)
91
		sprintf(buf2, "%luG", size0);
92
	else if (size0 = (size*10/1024/1024/1024+512)/1024, size0 < 100)
93
		sprintf(buf2, "%lu.%luT", size0 / 10, size0 % 10);
94
	else
95
		sprintf(buf2, "%luT", (size/1024/1024/1024+512)/1024);
96
	return(buf2);
97
}
98
62
/*
99
/*
63
 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
100
 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
64
 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
101
 * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
Lines 151-157 Link Here
151
static int
188
static int
152
devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
189
devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
153
{
190
{
154
155
	switch (devpath->Type) {
191
	switch (devpath->Type) {
156
	case MESSAGING_DEVICE_PATH:
192
	case MESSAGING_DEVICE_PATH:
157
		switch (devpath->SubType) {
193
		switch (devpath->SubType) {
Lines 251-258 Link Here
251
			HARDDRIVE_DEVICE_PATH *hd;
287
			HARDDRIVE_DEVICE_PATH *hd;
252
288
253
			hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
289
			hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
254
			return snprintf(buf, size, "hd(%x)",
290
			return snprintf(buf, size, "hd(p%d) (%s)",
255
			    hd->PartitionNumber);
291
			    hd->PartitionNumber,
292
			    humanize_number_kmgt(hd->PartitionSize * 512));
256
		}
293
		}
257
		default:
294
		default:
258
			return snprintf(buf, size, "media(0x%02x)",
295
			return snprintf(buf, size, "media(0x%02x)",
Lines 350-355 Link Here
350
	return (EFI_NOT_FOUND);
387
	return (EFI_NOT_FOUND);
351
}
388
}
352
389
390
/* quick dirty work. */
391
#define	NUM_DEV_LIST	35
392
393
typedef struct {
394
	const boot_module_t	*modp;
395
	dev_info_t		*devinfop;
396
} moddev_t;
397
398
static moddev_t dev_list[NUM_DEV_LIST];
399
400
static int
401
list_devices(void)
402
{
403
	UINTN i, j;
404
	dev_info_t *dev;
405
	const boot_module_t *mod;
406
407
	j = 0;
408
	for (i = 0; i < NUM_BOOT_MODULES; i++) {
409
		if (boot_modules[i] == NULL)
410
			continue;
411
		mod = boot_modules[i];
412
		for (dev = mod->devices(); dev != NULL; dev = dev->next) {
413
			dev_list[j].devinfop = dev;
414
			dev_list[j].modp = mod;
415
			j++;
416
			if (j >= NUM_DEV_LIST)
417
			    break;
418
		}
419
	}
420
421
	return (j);
422
}
423
424
#define	SELECT_TIMEOUT	10
425
426
static char
427
idx2char(int i)
428
{
429
	return (i<10 ? '0'+i : 'a'+i-10);
430
}
431
432
static int
433
char2idx(char c)
434
{
435
	return ((c >= '0' && c <= '9') ? c - '0' :
436
	    (c >= 'A' && c <= 'Z') ? c - 'A' + 10 :
437
	    (c >= 'a' && c <= 'z') ? c - 'a' + 10 :
438
	    -1 );
439
}
440
441
static void
442
move_to_tol()
443
{
444
	int x,y;
445
446
	x = conout->Mode->CursorColumn;
447
	y = conout->Mode->CursorRow;
448
	conout->SetCursorPosition(conout, 0, y);
449
}
450
451
static EFI_STATUS
452
select_bootdev(int ndevs, const boot_module_t **modp, dev_info_t **devinfop,
453
    void **bufp, size_t *bufsize)
454
{
455
	int i;
456
	int c, n;
457
	int time_left;
458
	EFI_STATUS status;
459
	EFI_EVENT timer;
460
	EFI_EVENT events[2];
461
	UINTN idx;
462
	dev_info_t *dev;
463
	const boot_module_t *mod;
464
465
	if ((ndevs <= 0) || (ndevs >= NUM_DEV_LIST)) {
466
		return (EFI_NOT_FOUND);
467
	} else if (ndevs == 1) {
468
		/* Only one condidate. */
469
		*modp = mod = dev_list[0].modp;
470
		*devinfop = dev = dev_list[0].devinfop;
471
		return (mod->load(PATH_LOADER_EFI, dev,
472
			 bufp, bufsize));
473
	}
474
	/* Two or more candidate exist. */
475
	status = bs->CreateEvent(EVT_TIMER, 0, 0, NULL, &timer);
476
	if (status != EFI_SUCCESS) {
477
		printf("Can't allocate timer event.\n");
478
		return (status);
479
	}
480
	printf("  0: AutoSelected Partition (Default): 0\n"); 
481
	for (i = 0; i < ndevs; i++) {
482
		if (dev_list[i].devinfop->preferred == TRUE)
483
			c = '*';
484
		else
485
			c = ' ';
486
		printf(" %c%c: %s: %s: %c\n", c, idx2char(i+1),
487
		    dev_list[i].modp->name,
488
		    devpath_str(dev_list[i].devinfop->devpath),
489
			idx2char(i+1));
490
	}
491
	/* One alpha-num selection only. Is this big enough ?? */
492
	bs->SetTimer(timer, TimerPeriodic, 10000000); 
493
	events[0] = timer;
494
	events[1] = conin->WaitForKey;
495
	time_left = SELECT_TIMEOUT;
496
497
	while (1) {
498
		if (time_left > 0) {
499
			printf("Select from 0 to %c. Timeout in %2d seconds,"
500
			       " [Space] to pause : ",
501
			       idx2char(ndevs), time_left);
502
		}
503
		status = bs->WaitForEvent(2, events, &idx);
504
		if (status != EFI_SUCCESS) {
505
			bs->CloseEvent(timer);
506
			return (status);
507
		}
508
		if (idx == 0) {
509
			time_left--;
510
			if (time_left <=0) {
511
				printf("\nTimeout. "
512
				       "Partition is AutoSelected.\n");
513
				n = 0;
514
				break;
515
			} else {
516
				move_to_tol();
517
			}
518
		}
519
		if (idx == 1) {
520
			c = getchar();
521
			if ((c == '\n') || (c == '\r')) {
522
				putchar('\n');
523
				n = 0;
524
				break;
525
			} else if ((time_left > 0) && (c == ' ')) {
526
				bs->SetTimer(timer, TimerCancel, 0); 
527
				time_left = -1;
528
				printf("\nTimer stopeed.\n Please Key in: ");
529
			}
530
			n = char2idx(c);
531
			if ((n >= 0) && (n <= ndevs)) {
532
				bs->SetTimer(timer, TimerCancel, 0); 
533
				time_left = -1;
534
				printf("\n %c is selected.\n", c);
535
				if (n == 0) { /* AutoSelect */
536
					break;
537
				} else {
538
					mod = dev_list[n-1].modp;
539
					dev = dev_list[n-1].devinfop;
540
					status = mod->load(PATH_LOADER_EFI,
541
							   dev, bufp, bufsize);
542
					if (status == EFI_SUCCESS) {
543
						break;
544
					}
545
					printf("Failed to load '%s'\n",
546
						 PATH_LOADER_EFI);
547
					printf("Please select again: ");
548
				}
549
			} else {
550
				/* Invalid charecter. */
551
				move_to_tol();
552
			}
553
		}
554
	};
555
	bs->CloseEvent(timer);
556
	if (n == 0) { /* AutoSelect */
557
		status = load_loader(modp, devinfop, bufp, bufsize, TRUE);
558
		if (status != EFI_SUCCESS) {
559
			status = load_loader(modp, devinfop, bufp, bufsize,
560
			    FALSE);
561
		}
562
	} else {
563
		*modp = dev_list[n-1].modp;
564
		*devinfop = dev_list[n-1].devinfop;
565
		status = EFI_SUCCESS;
566
	}
567
	return (status);
568
}
569
353
/*
570
/*
354
 * try_boot only returns if it fails to load the loader. If it succeeds
571
 * try_boot only returns if it fails to load the loader. If it succeeds
355
 * it simply boots, otherwise it returns the status of last EFI call.
572
 * it simply boots, otherwise it returns the status of last EFI call.
Lines 358-364 Link Here
358
try_boot()
575
try_boot()
359
{
576
{
360
	size_t bufsize, loadersize, cmdsize;
577
	size_t bufsize, loadersize, cmdsize;
361
	void *buf, *loaderbuf;
578
	void *buf = NULL, *loaderbuf = NULL;
362
	char *cmd;
579
	char *cmd;
363
	dev_info_t *dev;
580
	dev_info_t *dev;
364
	const boot_module_t *mod;
581
	const boot_module_t *mod;
Lines 365-379 Link Here
365
	EFI_HANDLE loaderhandle;
582
	EFI_HANDLE loaderhandle;
366
	EFI_LOADED_IMAGE *loaded_image;
583
	EFI_LOADED_IMAGE *loaded_image;
367
	EFI_STATUS status;
584
	EFI_STATUS status;
585
	int ndevs;
368
586
369
	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
587
	ndevs = list_devices();
588
	status = select_bootdev(ndevs, &mod, &dev, &loaderbuf, &loadersize);	
370
	if (status != EFI_SUCCESS) {
589
	if (status != EFI_SUCCESS) {
371
		status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
590
		printf("Failed to load '%s'\n", PATH_LOADER_EFI);
372
		    FALSE);
591
		return (EFI_NOT_FOUND);
373
		if (status != EFI_SUCCESS) {
374
			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
375
			return (status);
376
		}
377
	}
592
	}
378
593
379
	/*
594
	/*
Lines 423-428 Link Here
423
	loaded_image->LoadOptionsSize = cmdsize;
638
	loaded_image->LoadOptionsSize = cmdsize;
424
	loaded_image->LoadOptions = cmd;
639
	loaded_image->LoadOptions = cmd;
425
640
641
	printf("Boot from: %s in 1 second\n", devpath_str(dev->devpath));
642
	bs->Stall(1000000);
643
426
	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
644
	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
427
	DSTALL(1000000);
645
	DSTALL(1000000);
428
	DPRINTF(".");
646
	DPRINTF(".");
Lines 559-579 Link Here
559
	DSTALL(500000);
777
	DSTALL(500000);
560
}
778
}
561
779
562
EFI_STATUS
780
static EFI_STATUS
563
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
781
init_console()
564
{
782
{
565
	EFI_HANDLE *handles;
566
	EFI_LOADED_IMAGE *img;
567
	EFI_DEVICE_PATH *imgpath;
568
	EFI_STATUS status;
783
	EFI_STATUS status;
569
	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
784
	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
570
	SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
571
	UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
572
785
573
	/* Basic initialization*/
786
	UINTN i, max_dim, best_mode, cols, rows;
574
	systab = Xsystab;
575
	image = Ximage;
576
	bs = Xsystab->BootServices;
577
787
578
	/* Set up the console, so printf works. */
788
	/* Set up the console, so printf works. */
579
	status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
789
	status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
Lines 584-591 Link Here
584
	/*
794
	/*
585
	 * Reset the console and find the best text mode.
795
	 * Reset the console and find the best text mode.
586
	 */
796
	 */
797
	conin = systab->ConIn;
587
	conout = systab->ConOut;
798
	conout = systab->ConOut;
799
	conin->Reset(conin, TRUE);
588
	conout->Reset(conout, TRUE);
800
	conout->Reset(conout, TRUE);
801
589
	max_dim = best_mode = 0;
802
	max_dim = best_mode = 0;
590
	for (i = 0; ; i++) {
803
	for (i = 0; ; i++) {
591
		status = conout->QueryMode(conout, i, &cols, &rows);
804
		status = conout->QueryMode(conout, i, &cols, &rows);
Lines 598-606 Link Here
598
	}
811
	}
599
	if (max_dim > 0)
812
	if (max_dim > 0)
600
		conout->SetMode(conout, best_mode);
813
		conout->SetMode(conout, best_mode);
814
815
	conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
816
	    DEFAULT_BGCOLOR));
601
	conout->EnableCursor(conout, TRUE);
817
	conout->EnableCursor(conout, TRUE);
602
	conout->ClearScreen(conout);
818
	conout->ClearScreen(conout);
603
819
820
	return (status);
821
}
822
823
EFI_STATUS
824
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
825
{
826
	EFI_HANDLE *handles;
827
	EFI_LOADED_IMAGE *img;
828
	EFI_DEVICE_PATH *imgpath;
829
	EFI_STATUS status;
830
	UINTN i, hsize, nhandles;
831
832
	/* Basic initialization*/
833
	systab = Xsystab;
834
	image = Ximage;
835
	bs = Xsystab->BootServices;
836
837
	init_console();
838
604
	printf("\n>> FreeBSD EFI boot block\n");
839
	printf("\n>> FreeBSD EFI boot block\n");
605
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
840
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
606
	printf("   Initializing modules:");
841
	printf("   Initializing modules:");
Lines 715-728 Link Here
715
void
950
void
716
putchar(int c)
951
putchar(int c)
717
{
952
{
953
	efi_cons_putchar(c);
954
}
955
956
void
957
efi_cons_putchar(int c)
958
{
718
	CHAR16 buf[2];
959
	CHAR16 buf[2];
719
960
720
	if (c == '\n') {
961
	if (c == '\n') {
721
		buf[0] = '\r';
962
		buf[0] = '\r';
722
		buf[1] = 0;
963
		buf[1] = 0;
723
		systab->ConOut->OutputString(systab->ConOut, buf);
964
		conout->OutputString(conout, buf);
724
	}
965
	}
725
	buf[0] = c;
966
	buf[0] = c;
726
	buf[1] = 0;
967
	buf[1] = 0;
727
	systab->ConOut->OutputString(systab->ConOut, buf);
968
	conout->OutputString(conout, buf);
728
}
969
}
970
971
int
972
getchar(void)
973
{
974
	return efi_cons_getchar();
975
}
976
977
978
int
979
efi_cons_getchar()
980
{
981
	EFI_INPUT_KEY key;
982
	EFI_STATUS status;
983
	UINTN junk;
984
985
	/* Try to read a key stroke. We wait for one if none is pending. */
986
	status = conin->ReadKeyStroke(conin, &key);
987
	if (status == EFI_NOT_READY) {
988
		bs->WaitForEvent(1, &conin->WaitForKey, &junk);
989
		status = conin->ReadKeyStroke(conin, &key);
990
	}
991
	switch (key.ScanCode) {
992
	case 0x17: /* ESC */
993
		return (0x1b);  /* esc */
994
	}
995
996
	/* this can return  */
997
	return (key.UnicodeChar);
998
}
999
1000
int
1001
efi_cons_poll()
1002
{
1003
	/* This can clear the signaled state. */
1004
	return (bs->CheckEvent(conin->WaitForKey) == EFI_SUCCESS);
1005
}
1006

Return to bug 207940