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 |
|