diff options
Diffstat (limited to 'arch/x86/boot')
-rw-r--r-- | arch/x86/boot/compressed/eboot.c | 198 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_32.S | 10 | ||||
-rw-r--r-- | arch/x86/boot/compressed/head_64.S | 10 | ||||
-rw-r--r-- | arch/x86/boot/header.S | 4 |
4 files changed, 143 insertions, 79 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 4e85f5f85837..b3e0227df2c9 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -729,32 +729,68 @@ fail: | |||
729 | * need to create one ourselves (usually the bootloader would create | 729 | * need to create one ourselves (usually the bootloader would create |
730 | * one for us). | 730 | * one for us). |
731 | */ | 731 | */ |
732 | static efi_status_t make_boot_params(struct boot_params *boot_params, | 732 | struct boot_params *make_boot_params(void *handle, efi_system_table_t *_table) |
733 | efi_loaded_image_t *image, | ||
734 | void *handle) | ||
735 | { | 733 | { |
736 | struct efi_info *efi = &boot_params->efi_info; | 734 | struct boot_params *boot_params; |
737 | struct apm_bios_info *bi = &boot_params->apm_bios_info; | 735 | struct sys_desc_table *sdt; |
738 | struct sys_desc_table *sdt = &boot_params->sys_desc_table; | 736 | struct apm_bios_info *bi; |
739 | struct e820entry *e820_map = &boot_params->e820_map[0]; | 737 | struct setup_header *hdr; |
740 | struct e820entry *prev = NULL; | 738 | struct efi_info *efi; |
741 | struct setup_header *hdr = &boot_params->hdr; | 739 | efi_loaded_image_t *image; |
742 | unsigned long size, key, desc_size, _size; | 740 | void *options; |
743 | efi_memory_desc_t *mem_map; | 741 | u32 load_options_size; |
744 | void *options = image->load_options; | 742 | efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; |
745 | u32 load_options_size = image->load_options_size / 2; /* ASCII */ | ||
746 | int options_size = 0; | 743 | int options_size = 0; |
747 | efi_status_t status; | 744 | efi_status_t status; |
748 | __u32 desc_version; | ||
749 | unsigned long cmdline; | 745 | unsigned long cmdline; |
750 | u8 nr_entries; | ||
751 | u16 *s2; | 746 | u16 *s2; |
752 | u8 *s1; | 747 | u8 *s1; |
753 | int i; | 748 | int i; |
754 | 749 | ||
750 | sys_table = _table; | ||
751 | |||
752 | /* Check if we were booted by the EFI firmware */ | ||
753 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | ||
754 | return NULL; | ||
755 | |||
756 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | ||
757 | handle, &proto, (void *)&image); | ||
758 | if (status != EFI_SUCCESS) { | ||
759 | efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); | ||
760 | return NULL; | ||
761 | } | ||
762 | |||
763 | status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); | ||
764 | if (status != EFI_SUCCESS) { | ||
765 | efi_printk("Failed to alloc lowmem for boot params\n"); | ||
766 | return NULL; | ||
767 | } | ||
768 | |||
769 | memset(boot_params, 0x0, 0x4000); | ||
770 | |||
771 | hdr = &boot_params->hdr; | ||
772 | efi = &boot_params->efi_info; | ||
773 | bi = &boot_params->apm_bios_info; | ||
774 | sdt = &boot_params->sys_desc_table; | ||
775 | |||
776 | /* Copy the second sector to boot_params */ | ||
777 | memcpy(&hdr->jump, image->image_base + 512, 512); | ||
778 | |||
779 | /* | ||
780 | * Fill out some of the header fields ourselves because the | ||
781 | * EFI firmware loader doesn't load the first sector. | ||
782 | */ | ||
783 | hdr->root_flags = 1; | ||
784 | hdr->vid_mode = 0xffff; | ||
785 | hdr->boot_flag = 0xAA55; | ||
786 | |||
787 | hdr->code32_start = (__u64)(unsigned long)image->image_base; | ||
788 | |||
755 | hdr->type_of_loader = 0x21; | 789 | hdr->type_of_loader = 0x21; |
756 | 790 | ||
757 | /* Convert unicode cmdline to ascii */ | 791 | /* Convert unicode cmdline to ascii */ |
792 | options = image->load_options; | ||
793 | load_options_size = image->load_options_size / 2; /* ASCII */ | ||
758 | cmdline = 0; | 794 | cmdline = 0; |
759 | s2 = (u16 *)options; | 795 | s2 = (u16 *)options; |
760 | 796 | ||
@@ -791,18 +827,36 @@ static efi_status_t make_boot_params(struct boot_params *boot_params, | |||
791 | hdr->ramdisk_image = 0; | 827 | hdr->ramdisk_image = 0; |
792 | hdr->ramdisk_size = 0; | 828 | hdr->ramdisk_size = 0; |
793 | 829 | ||
794 | status = handle_ramdisks(image, hdr); | ||
795 | if (status != EFI_SUCCESS) | ||
796 | goto free_cmdline; | ||
797 | |||
798 | setup_graphics(boot_params); | ||
799 | |||
800 | /* Clear APM BIOS info */ | 830 | /* Clear APM BIOS info */ |
801 | memset(bi, 0, sizeof(*bi)); | 831 | memset(bi, 0, sizeof(*bi)); |
802 | 832 | ||
803 | memset(sdt, 0, sizeof(*sdt)); | 833 | memset(sdt, 0, sizeof(*sdt)); |
804 | 834 | ||
805 | memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); | 835 | status = handle_ramdisks(image, hdr); |
836 | if (status != EFI_SUCCESS) | ||
837 | goto fail2; | ||
838 | |||
839 | return boot_params; | ||
840 | fail2: | ||
841 | if (options_size) | ||
842 | low_free(options_size, hdr->cmd_line_ptr); | ||
843 | fail: | ||
844 | low_free(0x4000, (unsigned long)boot_params); | ||
845 | return NULL; | ||
846 | } | ||
847 | |||
848 | static efi_status_t exit_boot(struct boot_params *boot_params, | ||
849 | void *handle) | ||
850 | { | ||
851 | struct efi_info *efi = &boot_params->efi_info; | ||
852 | struct e820entry *e820_map = &boot_params->e820_map[0]; | ||
853 | struct e820entry *prev = NULL; | ||
854 | unsigned long size, key, desc_size, _size; | ||
855 | efi_memory_desc_t *mem_map; | ||
856 | efi_status_t status; | ||
857 | __u32 desc_version; | ||
858 | u8 nr_entries; | ||
859 | int i; | ||
806 | 860 | ||
807 | size = sizeof(*mem_map) * 32; | 861 | size = sizeof(*mem_map) * 32; |
808 | 862 | ||
@@ -811,7 +865,7 @@ again: | |||
811 | _size = size; | 865 | _size = size; |
812 | status = low_alloc(size, 1, (unsigned long *)&mem_map); | 866 | status = low_alloc(size, 1, (unsigned long *)&mem_map); |
813 | if (status != EFI_SUCCESS) | 867 | if (status != EFI_SUCCESS) |
814 | goto free_cmdline; | 868 | return status; |
815 | 869 | ||
816 | status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, | 870 | status = efi_call_phys5(sys_table->boottime->get_memory_map, &size, |
817 | mem_map, &key, &desc_size, &desc_version); | 871 | mem_map, &key, &desc_size, &desc_version); |
@@ -823,6 +877,7 @@ again: | |||
823 | if (status != EFI_SUCCESS) | 877 | if (status != EFI_SUCCESS) |
824 | goto free_mem_map; | 878 | goto free_mem_map; |
825 | 879 | ||
880 | memcpy(&efi->efi_loader_signature, EFI_LOADER_SIGNATURE, sizeof(__u32)); | ||
826 | efi->efi_systab = (unsigned long)sys_table; | 881 | efi->efi_systab = (unsigned long)sys_table; |
827 | efi->efi_memdesc_size = desc_size; | 882 | efi->efi_memdesc_size = desc_size; |
828 | efi->efi_memdesc_version = desc_version; | 883 | efi->efi_memdesc_version = desc_version; |
@@ -906,61 +961,13 @@ again: | |||
906 | 961 | ||
907 | free_mem_map: | 962 | free_mem_map: |
908 | low_free(_size, (unsigned long)mem_map); | 963 | low_free(_size, (unsigned long)mem_map); |
909 | free_cmdline: | ||
910 | if (options_size) | ||
911 | low_free(options_size, hdr->cmd_line_ptr); | ||
912 | fail: | ||
913 | return status; | 964 | return status; |
914 | } | 965 | } |
915 | 966 | ||
916 | /* | 967 | static efi_status_t relocate_kernel(struct setup_header *hdr) |
917 | * On success we return a pointer to a boot_params structure, and NULL | ||
918 | * on failure. | ||
919 | */ | ||
920 | struct boot_params *efi_main(void *handle, efi_system_table_t *_table) | ||
921 | { | 968 | { |
922 | struct boot_params *boot_params; | ||
923 | unsigned long start, nr_pages; | 969 | unsigned long start, nr_pages; |
924 | struct desc_ptr *gdt, *idt; | ||
925 | efi_loaded_image_t *image; | ||
926 | struct setup_header *hdr; | ||
927 | efi_status_t status; | 970 | efi_status_t status; |
928 | efi_guid_t proto = LOADED_IMAGE_PROTOCOL_GUID; | ||
929 | struct desc_struct *desc; | ||
930 | |||
931 | sys_table = _table; | ||
932 | |||
933 | /* Check if we were booted by the EFI firmware */ | ||
934 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | ||
935 | goto fail; | ||
936 | |||
937 | status = efi_call_phys3(sys_table->boottime->handle_protocol, | ||
938 | handle, &proto, (void *)&image); | ||
939 | if (status != EFI_SUCCESS) { | ||
940 | efi_printk("Failed to get handle for LOADED_IMAGE_PROTOCOL\n"); | ||
941 | goto fail; | ||
942 | } | ||
943 | |||
944 | status = low_alloc(0x4000, 1, (unsigned long *)&boot_params); | ||
945 | if (status != EFI_SUCCESS) { | ||
946 | efi_printk("Failed to alloc lowmem for boot params\n"); | ||
947 | goto fail; | ||
948 | } | ||
949 | |||
950 | memset(boot_params, 0x0, 0x4000); | ||
951 | |||
952 | hdr = &boot_params->hdr; | ||
953 | |||
954 | /* Copy the second sector to boot_params */ | ||
955 | memcpy(&hdr->jump, image->image_base + 512, 512); | ||
956 | |||
957 | /* | ||
958 | * Fill out some of the header fields ourselves because the | ||
959 | * EFI firmware loader doesn't load the first sector. | ||
960 | */ | ||
961 | hdr->root_flags = 1; | ||
962 | hdr->vid_mode = 0xffff; | ||
963 | hdr->boot_flag = 0xAA55; | ||
964 | 971 | ||
965 | /* | 972 | /* |
966 | * The EFI firmware loader could have placed the kernel image | 973 | * The EFI firmware loader could have placed the kernel image |
@@ -978,16 +985,40 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) | |||
978 | if (status != EFI_SUCCESS) { | 985 | if (status != EFI_SUCCESS) { |
979 | status = low_alloc(hdr->init_size, hdr->kernel_alignment, | 986 | status = low_alloc(hdr->init_size, hdr->kernel_alignment, |
980 | &start); | 987 | &start); |
981 | if (status != EFI_SUCCESS) { | 988 | if (status != EFI_SUCCESS) |
982 | efi_printk("Failed to alloc mem for kernel\n"); | 989 | efi_printk("Failed to alloc mem for kernel\n"); |
983 | goto fail; | ||
984 | } | ||
985 | } | 990 | } |
986 | 991 | ||
992 | if (status == EFI_SUCCESS) | ||
993 | memcpy((void *)start, (void *)(unsigned long)hdr->code32_start, | ||
994 | hdr->init_size); | ||
995 | |||
996 | hdr->pref_address = hdr->code32_start; | ||
987 | hdr->code32_start = (__u32)start; | 997 | hdr->code32_start = (__u32)start; |
988 | hdr->pref_address = (__u64)(unsigned long)image->image_base; | ||
989 | 998 | ||
990 | memcpy((void *)start, image->image_base, image->image_size); | 999 | return status; |
1000 | } | ||
1001 | |||
1002 | /* | ||
1003 | * On success we return a pointer to a boot_params structure, and NULL | ||
1004 | * on failure. | ||
1005 | */ | ||
1006 | struct boot_params *efi_main(void *handle, efi_system_table_t *_table, | ||
1007 | struct boot_params *boot_params) | ||
1008 | { | ||
1009 | struct desc_ptr *gdt, *idt; | ||
1010 | efi_loaded_image_t *image; | ||
1011 | struct setup_header *hdr = &boot_params->hdr; | ||
1012 | efi_status_t status; | ||
1013 | struct desc_struct *desc; | ||
1014 | |||
1015 | sys_table = _table; | ||
1016 | |||
1017 | /* Check if we were booted by the EFI firmware */ | ||
1018 | if (sys_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) | ||
1019 | goto fail; | ||
1020 | |||
1021 | setup_graphics(boot_params); | ||
991 | 1022 | ||
992 | status = efi_call_phys3(sys_table->boottime->allocate_pool, | 1023 | status = efi_call_phys3(sys_table->boottime->allocate_pool, |
993 | EFI_LOADER_DATA, sizeof(*gdt), | 1024 | EFI_LOADER_DATA, sizeof(*gdt), |
@@ -1015,7 +1046,18 @@ struct boot_params *efi_main(void *handle, efi_system_table_t *_table) | |||
1015 | idt->size = 0; | 1046 | idt->size = 0; |
1016 | idt->address = 0; | 1047 | idt->address = 0; |
1017 | 1048 | ||
1018 | status = make_boot_params(boot_params, image, handle); | 1049 | /* |
1050 | * If the kernel isn't already loaded at the preferred load | ||
1051 | * address, relocate it. | ||
1052 | */ | ||
1053 | if (hdr->pref_address != hdr->code32_start) { | ||
1054 | status = relocate_kernel(hdr); | ||
1055 | |||
1056 | if (status != EFI_SUCCESS) | ||
1057 | goto fail; | ||
1058 | } | ||
1059 | |||
1060 | status = exit_boot(boot_params, handle); | ||
1019 | if (status != EFI_SUCCESS) | 1061 | if (status != EFI_SUCCESS) |
1020 | goto fail; | 1062 | goto fail; |
1021 | 1063 | ||
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index c85e3ac99bba..aa4aaf1b2380 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S | |||
@@ -42,6 +42,16 @@ ENTRY(startup_32) | |||
42 | */ | 42 | */ |
43 | add $0x4, %esp | 43 | add $0x4, %esp |
44 | 44 | ||
45 | call make_boot_params | ||
46 | cmpl $0, %eax | ||
47 | je 1f | ||
48 | movl 0x4(%esp), %esi | ||
49 | movl (%esp), %ecx | ||
50 | pushl %eax | ||
51 | pushl %esi | ||
52 | pushl %ecx | ||
53 | |||
54 | .org 0x30,0x90 | ||
45 | call efi_main | 55 | call efi_main |
46 | cmpl $0, %eax | 56 | cmpl $0, %eax |
47 | movl %eax, %esi | 57 | movl %eax, %esi |
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 87e03a13d8e3..2c4b171eec33 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S | |||
@@ -209,6 +209,16 @@ ENTRY(startup_64) | |||
209 | .org 0x210 | 209 | .org 0x210 |
210 | mov %rcx, %rdi | 210 | mov %rcx, %rdi |
211 | mov %rdx, %rsi | 211 | mov %rdx, %rsi |
212 | pushq %rdi | ||
213 | pushq %rsi | ||
214 | call make_boot_params | ||
215 | cmpq $0,%rax | ||
216 | je 1f | ||
217 | mov %rax, %rdx | ||
218 | popq %rsi | ||
219 | popq %rdi | ||
220 | |||
221 | .org 0x230,0x90 | ||
212 | call efi_main | 222 | call efi_main |
213 | movq %rax,%rsi | 223 | movq %rax,%rsi |
214 | cmpq $0,%rax | 224 | cmpq $0,%rax |
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 8bbea6aa40d9..097f4760faea 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S | |||
@@ -263,7 +263,7 @@ _start: | |||
263 | # Part 2 of the header, from the old setup.S | 263 | # Part 2 of the header, from the old setup.S |
264 | 264 | ||
265 | .ascii "HdrS" # header signature | 265 | .ascii "HdrS" # header signature |
266 | .word 0x020a # header version number (>= 0x0105) | 266 | .word 0x020b # header version number (>= 0x0105) |
267 | # or else old loadlin-1.5 will fail) | 267 | # or else old loadlin-1.5 will fail) |
268 | .globl realmode_swtch | 268 | .globl realmode_swtch |
269 | realmode_swtch: .word 0, 0 # default_switch, SETUPSEG | 269 | realmode_swtch: .word 0, 0 # default_switch, SETUPSEG |
@@ -381,6 +381,8 @@ pref_address: .quad LOAD_PHYSICAL_ADDR # preferred load addr | |||
381 | #define INIT_SIZE VO_INIT_SIZE | 381 | #define INIT_SIZE VO_INIT_SIZE |
382 | #endif | 382 | #endif |
383 | init_size: .long INIT_SIZE # kernel initialization size | 383 | init_size: .long INIT_SIZE # kernel initialization size |
384 | handover_offset: .long 0x30 # offset to the handover | ||
385 | # protocol entry point | ||
384 | 386 | ||
385 | # End of setup header ##################################################### | 387 | # End of setup header ##################################################### |
386 | 388 | ||