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

Collapse All | Expand All

(-)boot1.c (-31 / +246 lines)
Lines 28-34 Link Here
28
#include <stand.h>
28
#include <stand.h>
29
29
30
#include <efi.h>
30
#include <efi.h>
31
#include <eficonsctl.h>
31
#include <efilib.h>
32
32
33
#include "boot_module.h"
33
#include "boot_module.h"
34
#include "paths.h"
34
#include "paths.h"
Lines 47-63 Link Here
47
/* The initial number of handles used to query EFI for partitions. */
47
/* The initial number of handles used to query EFI for partitions. */
48
#define NUM_HANDLES_INIT	24
48
#define NUM_HANDLES_INIT	24
49
49
50
void efi_cons_putchar(int);
51
int efi_cons_getchar(void);
52
int efi_cons_poll(void);
53
int getchar(void);
50
void putchar(int c);
54
void putchar(int c);
55
char *humanize_number_kmgt(UINT64);
51
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
56
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
52
57
53
EFI_SYSTEM_TABLE *systab;
58
EFI_SYSTEM_TABLE *systab;
54
EFI_BOOT_SERVICES *bs;
59
EFI_BOOT_SERVICES *bs;
55
static EFI_HANDLE *image;
60
static EFI_HANDLE *image;
61
static SIMPLE_TEXT_OUTPUT_INTERFACE	*conout;
62
static SIMPLE_INPUT_INTERFACE		*conin;
56
63
57
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
64
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
58
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
65
static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
59
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
66
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
60
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
67
68
#define DEFAULT_FGCOLOR EFI_LIGHTGRAY
69
#define DEFAULT_BGCOLOR EFI_BLACK
70
71
char *humanize_number_kmgt(UINT64 size) {
72
	static char buf2[6];
73
	UINT64 size0;
74
75
	if (size < 1024)
76
		sprintf(buf2, "%luB", size);
77
	else if (size0 = (size*10+512)/1024, size0 < 100)
78
		sprintf(buf2, "%lu.%luK", size0 / 10, size0 % 10);
79
	else if (size0 = (size+512)/1024, size0 < 1024)
80
		sprintf(buf2, "%luK", size0);
81
	else if (size0 = (size*10/1024+512)/1024, size0 < 100)
82
		sprintf(buf2, "%lu.%luM", size0 / 10, size0 % 10);
83
	else if (size0 = (size/1024+512)/1024, size0 < 1024)
84
		sprintf(buf2, "%luM", size0);
85
	else if (size0 = (size*10/1024/1024+512)/1024, size0 < 100)
86
		sprintf(buf2, "%lu.%luG", size0 / 10, size0 % 10);
87
	else if (size0 = (size/1024/1024+512)/1024, size0 < 1024)
88
		sprintf(buf2, "%luG", size0);
89
	else if (size0 = (size*10/1024/1024/1024+512)/1024, size0 < 100)
90
		sprintf(buf2, "%lu.%luT", size0 / 10, size0 % 10);
91
	else
92
		sprintf(buf2, "%luT", (size/1024/1024/1024+512)/1024);
93
	return(buf2);
94
}
61
95
62
/*
96
/*
63
 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
97
 * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
Lines 151-157 Link Here
151
static int
185
static int
152
devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
186
devpath_node_str(char *buf, size_t size, EFI_DEVICE_PATH *devpath)
153
{
187
{
154
155
	switch (devpath->Type) {
188
	switch (devpath->Type) {
156
	case MESSAGING_DEVICE_PATH:
189
	case MESSAGING_DEVICE_PATH:
157
		switch (devpath->SubType) {
190
		switch (devpath->SubType) {
Lines 251-258 Link Here
251
			HARDDRIVE_DEVICE_PATH *hd;
284
			HARDDRIVE_DEVICE_PATH *hd;
252
285
253
			hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
286
			hd = (HARDDRIVE_DEVICE_PATH *)(void *)devpath;
254
			return snprintf(buf, size, "hd(%x)",
287
			return snprintf(buf, size, "hd(p%d) (%s)",
255
			    hd->PartitionNumber);
288
			    hd->PartitionNumber,
289
			    humanize_number_kmgt(hd->PartitionSize * 512));
256
		}
290
		}
257
		default:
291
		default:
258
			return snprintf(buf, size, "media(0x%02x)",
292
			return snprintf(buf, size, "media(0x%02x)",
Lines 350-355 Link Here
350
	return (EFI_NOT_FOUND);
384
	return (EFI_NOT_FOUND);
351
}
385
}
352
386
387
/* quick dirty work. */
388
#define	NUM_DEV_LIST	35
389
390
static struct dev_list_t {
391
	const boot_module_t	*modp;
392
	dev_info_t	*devinfop;
393
} dev_list[NUM_DEV_LIST];
394
395
static int
396
list_devices(void)
397
{
398
	UINTN i, j;
399
	dev_info_t *dev;
400
	const boot_module_t *mod;
401
402
	j = 0;
403
	for (i = 0; i < NUM_BOOT_MODULES; i++) {
404
		if (boot_modules[i] == NULL)
405
			continue;
406
		mod = boot_modules[i];
407
		for (dev = mod->devices(); dev != NULL; dev = dev->next) {
408
			dev_list[j].devinfop = dev;
409
			dev_list[j].modp = mod;
410
			j++;
411
			if (j >= NUM_DEV_LIST)
412
			    break;
413
		}
414
	}
415
416
	return (j);
417
}
418
419
#define	SELECT_TIMEOUT	10
420
421
static int
422
select_dev(int ndevs)
423
{
424
	int i;
425
	int c;
426
	static int timeout = TRUE;
427
428
	printf("  0: AutoSelected Partition (Default): 0\n"); 
429
	for (i = 0; i < ndevs; i++) {
430
		if (dev_list[i].devinfop->preferred == TRUE)
431
			c = '*';
432
		else
433
			c = ' ';
434
		printf(" %c%c: %s: %s: %c\n", c, i<9 ? '1'+i : 'a'+i-9,
435
		    dev_list[i].modp->name,
436
		    devpath_str(dev_list[i].devinfop->devpath),
437
			i<9 ? '1'+i : 'a'+i-9);
438
	}
439
	/* One digit selection only. Is this big enough ?? */
440
	while (1) {
441
		if (timeout)
442
			printf("Select from 0 to %c: Timeout in %2d seconds"
443
			    "\b\b\b\b\b\b\b\b\b\b",
444
			    ndevs<10 ? '0'+ndevs : 'a'+ndevs-10,
445
			    SELECT_TIMEOUT);
446
		else
447
			printf("Select from 0 to %c: Never timeout",
448
			    ndevs<10 ? '0'+ndevs : 'a'+ndevs-10);
449
		for (i = SELECT_TIMEOUT * 20; i > 0; i--) {
450
			if (timeout) {
451
				if (!(i % 20))
452
					printf("%2d\b\b", i / 20);
453
				bs->Stall(50000);
454
				if (!efi_cons_poll()) /* No Key */
455
					continue;
456
			}
457
			while (1) {
458
				if (timeout) {
459
					printf("\b\b\b\b\b\b\b\b\b\b\b"
460
					    "Never timeout        ");
461
					timeout = FALSE;
462
				}
463
				c = getchar();
464
				c = (c == 0x0d) ? 0 :
465
				    (c >= '0' && c <= '9') ? c - '0' :
466
				    (c >= 'A' && c <= 'Z') ? c - 'A' + 10 :
467
				    (c >= 'a' && c <= 'z') ? c - 'a' + 10 :
468
				    ndevs + 1;
469
				if ((c >= 0) && (c <= ndevs)) {
470
					putchar('\n');
471
					return (c);
472
				}
473
			}
474
		}
475
		printf(" 0\nTimeout. Partition is AutoSelected.\n");
476
		return (0);
477
	}
478
}
479
353
/*
480
/*
354
 * try_boot only returns if it fails to load the loader. If it succeeds
481
 * 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.
482
 * it simply boots, otherwise it returns the status of last EFI call.
Lines 358-379 Link Here
358
try_boot()
485
try_boot()
359
{
486
{
360
	size_t bufsize, loadersize, cmdsize;
487
	size_t bufsize, loadersize, cmdsize;
361
	void *buf, *loaderbuf;
488
	void *buf = NULL, *loaderbuf = NULL;
362
	char *cmd;
489
	char *cmd;
363
	dev_info_t *dev;
490
	dev_info_t *dev;
364
	const boot_module_t *mod;
491
	const boot_module_t *mod;
365
	EFI_HANDLE loaderhandle;
492
	EFI_HANDLE loaderhandle;
366
	EFI_LOADED_IMAGE *loaded_image;
493
	EFI_LOADED_IMAGE *loaded_image;
367
	EFI_STATUS status;
494
	EFI_STATUS status;
495
	int i, ndevs;
368
496
369
	status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
497
	ndevs = list_devices();
370
	if (status != EFI_SUCCESS) {
498
	if (ndevs == 0) {
371
		status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
499
		printf("Failed to load '%s'\n", PATH_LOADER_EFI);
372
		    FALSE);
500
		return (EFI_NOT_FOUND);
501
	} else if (ndevs == 1) {
502
		mod = dev_list[0].modp;
503
		dev = dev_list[0].devinfop;
504
		status = mod->load(PATH_LOADER_EFI, dev,
505
			 &loaderbuf, &loadersize);
373
		if (status != EFI_SUCCESS) {
506
		if (status != EFI_SUCCESS) {
374
			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
507
			printf("Failed to load '%s'\n", PATH_LOADER_EFI);
375
			return (status);
508
			return (status);
376
		}
509
		}
510
	} else {
511
		while (1) {
512
			i = select_dev(ndevs);	
513
			printf(" %c is selected.\n", i<10 ? '0'+i : 'a'+i-10);
514
			if (i == 0) { /* AutoSelect */
515
				status = load_loader(&mod, &dev, &loaderbuf, &loadersize, TRUE);
516
				if (status != EFI_SUCCESS) {
517
					status = load_loader(&mod, &dev, &loaderbuf, &loadersize,
518
					    FALSE);
519
					if (status != EFI_SUCCESS) {
520
						printf("Failed to load '%s'\n", PATH_LOADER_EFI);
521
						return (status);
522
					}
523
				}
524
				break;
525
			} else {
526
				mod = dev_list[i-1].modp;
527
				dev = dev_list[i-1].devinfop;
528
				status = mod->load(PATH_LOADER_EFI, dev,
529
					 &loaderbuf, &loadersize);
530
				if (status == EFI_SUCCESS) 
531
					break;
532
				printf("Failed to load '%s'\n", PATH_LOADER_EFI);
533
			}
534
			printf("Please select again.\n");
535
		}
377
	}
536
	}
378
537
379
	/*
538
	/*
Lines 423-428 Link Here
423
	loaded_image->LoadOptionsSize = cmdsize;
582
	loaded_image->LoadOptionsSize = cmdsize;
424
	loaded_image->LoadOptions = cmd;
583
	loaded_image->LoadOptions = cmd;
425
584
585
	printf("Boot from: %s in 1 second\n", devpath_str(dev->devpath));
586
	bs->Stall(1000000);
587
426
	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
588
	DPRINTF("Starting '%s' in 5 seconds...", PATH_LOADER_EFI);
427
	DSTALL(1000000);
589
	DSTALL(1000000);
428
	DPRINTF(".");
590
	DPRINTF(".");
Lines 556-591 Link Here
556
		DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
718
		DPRINTF(" error (%lu)\n", EFI_ERROR_CODE(status));
557
		break;
719
		break;
558
	}
720
	}
559
	DSTALL(500000);
721
	DSTALL(1000000);
560
}
722
}
561
723
562
EFI_STATUS
724
static EFI_STATUS
563
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
725
init_console()
564
{
726
{
565
	EFI_HANDLE *handles;
566
	EFI_LOADED_IMAGE *img;
567
	EFI_DEVICE_PATH *imgpath;
568
	EFI_STATUS status;
727
	EFI_STATUS status;
569
	EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
728
	UINTN i, max_dim, best_mode, cols, rows;
570
	SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
571
	UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
572
573
	/* Basic initialization*/
574
	systab = Xsystab;
575
	image = Ximage;
576
	bs = Xsystab->BootServices;
577
729
578
	/* Set up the console, so printf works. */
730
	/* Set up the console, so printf works. */
579
	status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
580
	    (VOID **)&ConsoleControl);
581
	if (status == EFI_SUCCESS)
582
		(void)ConsoleControl->SetMode(ConsoleControl,
583
		    EfiConsoleControlScreenText);
584
	/*
731
	/*
585
	 * Reset the console and find the best text mode.
732
	 * Reset the console and find the best text mode.
586
	 */
733
	 */
734
	conin = systab->ConIn;
587
	conout = systab->ConOut;
735
	conout = systab->ConOut;
736
	conin->Reset(conin, TRUE);
588
	conout->Reset(conout, TRUE);
737
	conout->Reset(conout, TRUE);
738
589
	max_dim = best_mode = 0;
739
	max_dim = best_mode = 0;
590
	for (i = 0; ; i++) {
740
	for (i = 0; ; i++) {
591
		status = conout->QueryMode(conout, i, &cols, &rows);
741
		status = conout->QueryMode(conout, i, &cols, &rows);
Lines 598-606 Link Here
598
	}
748
	}
599
	if (max_dim > 0)
749
	if (max_dim > 0)
600
		conout->SetMode(conout, best_mode);
750
		conout->SetMode(conout, best_mode);
751
752
	conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
753
	    DEFAULT_BGCOLOR));
601
	conout->EnableCursor(conout, TRUE);
754
	conout->EnableCursor(conout, TRUE);
602
	conout->ClearScreen(conout);
755
	conout->ClearScreen(conout);
603
756
757
	return (status);
758
}
759
760
EFI_STATUS
761
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
762
{
763
	EFI_HANDLE *handles;
764
	EFI_LOADED_IMAGE *img;
765
	EFI_DEVICE_PATH *imgpath;
766
	EFI_STATUS status;
767
	UINTN i, hsize, nhandles;
768
769
	/* Basic initialization*/
770
	systab = Xsystab;
771
	image = Ximage;
772
	bs = Xsystab->BootServices;
773
774
	init_console();
775
604
	printf("\n>> FreeBSD EFI boot block\n");
776
	printf("\n>> FreeBSD EFI boot block\n");
605
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
777
	printf("   Loader path: %s\n\n", PATH_LOADER_EFI);
606
	printf("   Initializing modules:");
778
	printf("   Initializing modules:");
Lines 715-728 Link Here
715
void
887
void
716
putchar(int c)
888
putchar(int c)
717
{
889
{
890
	efi_cons_putchar(c);
891
}
892
893
void
894
efi_cons_putchar(int c)
895
{
718
	CHAR16 buf[2];
896
	CHAR16 buf[2];
719
897
720
	if (c == '\n') {
898
	if (c == '\n') {
721
		buf[0] = '\r';
899
		buf[0] = '\r';
722
		buf[1] = 0;
900
		buf[1] = 0;
723
		systab->ConOut->OutputString(systab->ConOut, buf);
901
		conout->OutputString(conout, buf);
724
	}
902
	}
725
	buf[0] = c;
903
	buf[0] = c;
726
	buf[1] = 0;
904
	buf[1] = 0;
727
	systab->ConOut->OutputString(systab->ConOut, buf);
905
	conout->OutputString(conout, buf);
906
}
907
908
int
909
getchar(void)
910
{
911
	return efi_cons_getchar();
912
}
913
914
915
int
916
efi_cons_getchar()
917
{
918
	EFI_INPUT_KEY key;
919
	EFI_STATUS status;
920
	UINTN junk;
921
922
	/* Try to read a key stroke. We wait for one if none is pending. */
923
	status = conin->ReadKeyStroke(conin, &key);
924
	if (status == EFI_NOT_READY) {
925
		bs->WaitForEvent(1, &conin->WaitForKey, &junk);
926
		status = conin->ReadKeyStroke(conin, &key);
927
	}
928
	switch (key.ScanCode) {
929
	case 0x17: /* ESC */
930
		return (0x1b);  /* esc */
931
	}
932
933
	/* this can return  */
934
	return (key.UnicodeChar);
728
}
935
}
936
937
int
938
efi_cons_poll()
939
{
940
	/* This can clear the signaled state. */
941
	return (bs->CheckEvent(conin->WaitForKey) == EFI_SUCCESS);
942
}
943

Return to bug 207940