diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-02-20 08:20:59 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2012-06-01 12:11:26 -0400 |
commit | 9fa7dedad3d30345c843bd82db02c4d6169e5f61 (patch) | |
tree | 8f7563d8e33e7faf4def6f58a44de664e0f106bc /arch/x86 | |
parent | 30dc0d0fe5d08396dbdaa2d70972149131340960 (diff) |
x86, efi; Add EFI boot stub console support
We need a way of printing useful messages to the user, for example
when we fail to open an initrd file, instead of just hanging the
machine without giving the user any indication of what went wrong. So
sprinkle some error messages throughout the EFI boot stub code to make
it easier for users to diagnose/report problems.
Reported-by: Keshav P R <the.ridikulus.rat@gmail.com>
Cc: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Link: http://lkml.kernel.org/r/1331907517-3985-3-git-send-email-matt@console-pimps.org
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 85 | ||||
-rw-r--r-- | arch/x86/boot/compressed/eboot.h | 6 |
2 files changed, 75 insertions, 16 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 52a4e667b258..4e85f5f85837 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -16,6 +16,26 @@ | |||
16 | 16 | ||
17 | static efi_system_table_t *sys_table; | 17 | static efi_system_table_t *sys_table; |
18 | 18 | ||
19 | static void efi_printk(char *str) | ||
20 | { | ||
21 | char *s8; | ||
22 | |||
23 | for (s8 = str; *s8; s8++) { | ||
24 | struct efi_simple_text_output_protocol *out; | ||
25 | efi_char16_t ch[2] = { 0 }; | ||
26 | |||
27 | ch[0] = *s8; | ||
28 | out = (struct efi_simple_text_output_protocol *)sys_table->con_out; | ||
29 | |||
30 | if (*s8 == '\n') { | ||
31 | efi_char16_t nl[2] = { '\r', 0 }; | ||
32 | efi_call_phys2(out->output_string, out, nl); | ||
33 | } | ||
34 | |||
35 | efi_call_phys2(out->output_string, out, ch); | ||
36 | } | ||
37 | } | ||
38 | |||
19 | static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size, | 39 | static efi_status_t __get_map(efi_memory_desc_t **map, unsigned long *map_size, |
20 | unsigned long *desc_size) | 40 | unsigned long *desc_size) |
21 | { | 41 | { |
@@ -531,8 +551,10 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, | |||
531 | EFI_LOADER_DATA, | 551 | EFI_LOADER_DATA, |
532 | nr_initrds * sizeof(*initrds), | 552 | nr_initrds * sizeof(*initrds), |
533 | &initrds); | 553 | &initrds); |
534 | if (status != EFI_SUCCESS) | 554 | if (status != EFI_SUCCESS) { |
555 | efi_printk("Failed to alloc mem for initrds\n"); | ||
535 | goto fail; | 556 | goto fail; |
557 | } | ||
536 | 558 | ||
537 | str = (char *)(unsigned long)hdr->cmd_line_ptr; | 559 | str = (char *)(unsigned long)hdr->cmd_line_ptr; |
538 | for (i = 0; i < nr_initrds; i++) { | 560 | for (i = 0; i < nr_initrds; i++) { |
@@ -575,32 +597,42 @@ static efi_status_t handle_ramdisks(efi_loaded_image_t *image, | |||
575 | 597 | ||
576 | status = efi_call_phys3(boottime->handle_protocol, | 598 | status = efi_call_phys3(boottime->handle_protocol, |
577 | image->device_handle, &fs_proto, &io); | 599 | image->device_handle, &fs_proto, &io); |
578 | if (status != EFI_SUCCESS) | 600 | if (status != EFI_SUCCESS) { |
601 | efi_printk("Failed to handle fs_proto\n"); | ||
579 | goto free_initrds; | 602 | goto free_initrds; |
603 | } | ||
580 | 604 | ||
581 | status = efi_call_phys2(io->open_volume, io, &fh); | 605 | status = efi_call_phys2(io->open_volume, io, &fh); |
582 | if (status != EFI_SUCCESS) | 606 | if (status != EFI_SUCCESS) { |
607 | efi_printk("Failed to open volume\n"); | ||
583 | goto free_initrds; | 608 | goto free_initrds; |
609 | } | ||
584 | } | 610 | } |
585 | 611 | ||
586 | status = efi_call_phys5(fh->open, fh, &h, filename_16, | 612 | status = efi_call_phys5(fh->open, fh, &h, filename_16, |
587 | EFI_FILE_MODE_READ, (u64)0); | 613 | EFI_FILE_MODE_READ, (u64)0); |
588 | if (status != EFI_SUCCESS) | 614 | if (status != EFI_SUCCESS) { |
615 | efi_printk("Failed to open initrd file\n"); | ||
589 | goto close_handles; | 616 | goto close_handles; |
617 | } | ||
590 | 618 | ||
591 | initrd->handle = h; | 619 | initrd->handle = h; |
592 | 620 | ||
593 | info_sz = 0; | 621 | info_sz = 0; |
594 | status = efi_call_phys4(h->get_info, h, &info_guid, | 622 | status = efi_call_phys4(h->get_info, h, &info_guid, |
595 | &info_sz, NULL); | 623 | &info_sz, NULL); |
596 | if (status != EFI_BUFFER_TOO_SMALL) | 624 | if (status != EFI_BUFFER_TOO_SMALL) { |
625 | efi_printk("Failed to get initrd info size\n"); | ||
597 | goto close_handles; | 626 | goto close_handles; |
627 | } | ||
598 | 628 | ||
599 | grow: | 629 | grow: |
600 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | 630 | status = efi_call_phys3(sys_table->boottime->allocate_pool, |
601 | EFI_LOADER_DATA, info_sz, &info); | 631 | EFI_LOADER_DATA, info_sz, &info); |
602 | if (status != EFI_SUCCESS) | 632 | if (status != EFI_SUCCESS) { |
633 | efi_printk("Failed to alloc mem for initrd info\n"); | ||
603 | goto close_handles; | 634 | goto close_handles; |
635 | } | ||
604 | 636 | ||
605 | status = efi_call_phys4(h->get_info, h, &info_guid, | 637 | status = efi_call_phys4(h->get_info, h, &info_guid, |
606 | &info_sz, info); | 638 | &info_sz, info); |
@@ -612,8 +644,10 @@ grow: | |||
612 | file_sz = info->file_size; | 644 | file_sz = info->file_size; |
613 | efi_call_phys1(sys_table->boottime->free_pool, info); | 645 | efi_call_phys1(sys_table->boottime->free_pool, info); |
614 | 646 | ||
615 | if (status != EFI_SUCCESS) | 647 | if (status != EFI_SUCCESS) { |
648 | efi_printk("Failed to get initrd info\n"); | ||
616 | goto close_handles; | 649 | goto close_handles; |
650 | } | ||
617 | 651 | ||
618 | initrd->size = file_sz; | 652 | initrd->size = file_sz; |
619 | initrd_total += file_sz; | 653 | initrd_total += file_sz; |
@@ -629,11 +663,14 @@ grow: | |||
629 | */ | 663 | */ |
630 | status = high_alloc(initrd_total, 0x1000, | 664 | status = high_alloc(initrd_total, 0x1000, |
631 | &initrd_addr, hdr->initrd_addr_max); | 665 | &initrd_addr, hdr->initrd_addr_max); |
632 | if (status != EFI_SUCCESS) | 666 | if (status != EFI_SUCCESS) { |
667 | efi_printk("Failed to alloc highmem for initrds\n"); | ||
633 | goto close_handles; | 668 | goto close_handles; |
669 | } | ||
634 | 670 | ||
635 | /* We've run out of free low memory. */ | 671 | /* We've run out of free low memory. */ |
636 | if (initrd_addr > hdr->initrd_addr_max) { | 672 | if (initrd_addr > hdr->initrd_addr_max) { |
673 | efi_printk("We've run out of free low memory\n"); | ||
637 | status = EFI_INVALID_PARAMETER; | 674 | status = EFI_INVALID_PARAMETER; |
638 | goto free_initrd_total; | 675 | goto free_initrd_total; |
639 | } | 676 | } |
@@ -652,8 +689,10 @@ grow: | |||
652 | status = efi_call_phys3(fh->read, | 689 | status = efi_call_phys3(fh->read, |
653 | initrds[j].handle, | 690 | initrds[j].handle, |
654 | &chunksize, addr); | 691 | &chunksize, addr); |
655 | if (status != EFI_SUCCESS) | 692 | if (status != EFI_SUCCESS) { |
693 | efi_printk("Failed to read initrd\n"); | ||
656 | goto free_initrd_total; | 694 | goto free_initrd_total; |
695 | } | ||
657 | addr += chunksize; | 696 | addr += chunksize; |
658 | size -= chunksize; | 697 | size -= chunksize; |
659 | } | 698 | } |
@@ -732,8 +771,10 @@ static efi_status_t make_boot_params(struct boot_params *boot_params, | |||
732 | options_size++; /* NUL termination */ | 771 | options_size++; /* NUL termination */ |
733 | 772 | ||
734 | status = low_alloc(options_size, 1, &cmdline); | 773 | status = low_alloc(options_size, 1, &cmdline); |
735 | if (status != EFI_SUCCESS) | 774 | if (status != EFI_SUCCESS) { |
775 | efi_printk("Failed to alloc mem for cmdline\n"); | ||
736 | goto fail; | 776 | goto fail; |
777 | } | ||
737 | 778 | ||
738 | s1 = (u8 *)(unsigned long)cmdline; | 779 | s1 = (u8 *)(unsigned long)cmdline; |
739 | s2 = (u16 *)options; | 780 | s2 = (u16 *)options; |
@@ -895,12 +936,16 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) | |||
895 | 936 | ||
896 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | 937 | status = efi_call_phys3(sys_table->boottime->handle_protocol, |
897 | handle, &proto, (void *)&image); | 938 | handle, &proto, (void *)&image); |
898 | if (status != EFI_SUCCESS) | 939 | if (status != EFI_SUCCESS) { |
940 | efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); | ||
899 | goto fail; | 941 | goto fail; |
942 | } | ||
900 | 943 | ||
901 | status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); | 944 | status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); |
902 | if (status != EFI_SUCCESS) | 945 | if (status != EFI_SUCCESS) { |
946 | efi_printk("Failed to alloc lowmem for boot params\n"); | ||
903 | goto fail; | 947 | goto fail; |
948 | } | ||
904 | 949 | ||
905 | memset(boot_params, 0x0, 0x4000); | 950 | memset(boot_params, 0x0, 0x4000); |
906 | 951 | ||
@@ -933,8 +978,10 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) | |||
933 | if (status != EFI_SUCCESS) { | 978 | if (status != EFI_SUCCESS) { |
934 | status = low_alloc(hdr->init_size, hdr->kernel_alignment, | 979 | status = low_alloc(hdr->init_size, hdr->kernel_alignment, |
935 | &start); | 980 | &start); |
936 | if (status != EFI_SUCCESS) | 981 | if (status != EFI_SUCCESS) { |
982 | efi_printk("Failed to alloc mem for kernel\n"); | ||
937 | goto fail; | 983 | goto fail; |
984 | } | ||
938 | } | 985 | } |
939 | 986 | ||
940 | hdr->code32_start = (__u32)start; | 987 | hdr->code32_start = (__u32)start; |
@@ -945,19 +992,25 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) | |||
945 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | 992 | status = efi_call_phys3(sys_table->boottime->allocate_pool, |
946 | EFI_LOADER_DATA, sizeof(*gdt), | 993 | EFI_LOADER_DATA, sizeof(*gdt), |
947 | (void **)&gdt); | 994 | (void **)&gdt); |
948 | if (status != EFI_SUCCESS) | 995 | if (status != EFI_SUCCESS) { |
996 | efi_printk("Failed to alloc mem for gdt structure\n"); | ||
949 | goto fail; | 997 | goto fail; |
998 | } | ||
950 | 999 | ||
951 | gdt->size = 0x800; | 1000 | gdt->size = 0x800; |
952 | status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address); | 1001 | status = low_alloc(gdt->size, 8, (unsigned long *)&gdt->address); |
953 | if (status != EFI_SUCCESS) | 1002 | if (status != EFI_SUCCESS) { |
1003 | efi_printk("Failed to alloc mem for gdt\n"); | ||
954 | goto fail; | 1004 | goto fail; |
1005 | } | ||
955 | 1006 | ||
956 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | 1007 | status = efi_call_phys3(sys_table->boottime->allocate_pool, |
957 | EFI_LOADER_DATA, sizeof(*idt), | 1008 | EFI_LOADER_DATA, sizeof(*idt), |
958 | (void **)&idt); | 1009 | (void **)&idt); |
959 | if (status != EFI_SUCCESS) | 1010 | if (status != EFI_SUCCESS) { |
1011 | efi_printk("Failed to alloc mem for idt structure\n"); | ||
960 | goto fail; | 1012 | goto fail; |
1013 | } | ||
961 | 1014 | ||
962 | idt->size = 0; | 1015 | idt->size = 0; |
963 | idt->address = 0; | 1016 | idt->address = 0; |
diff --git a/arch/x86/boot/compressed/eboot.h b/arch/x86/boot/compressed/eboot.h index 39251663e65b..3b6e15627c55 100644 --- a/arch/x86/boot/compressed/eboot.h +++ b/arch/x86/boot/compressed/eboot.h | |||
@@ -58,4 +58,10 @@ struct efi_uga_draw_protocol { | |||
58 | void *blt; | 58 | void *blt; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | struct efi_simple_text_output_protocol { | ||
62 | void *reset; | ||
63 | void *output_string; | ||
64 | void *test_string; | ||
65 | }; | ||
66 | |||
61 | #endif /* BOOT_COMPRESSED_EBOOT_H */ | 67 | #endif /* BOOT_COMPRESSED_EBOOT_H */ |