00001 #include <console/console.h>
00002 #include <ip_checksum.h>
00003 #include <boot/elf.h>
00004 #include <boot/elf_boot.h>
00005 #include <string.h>
00006 #include <cpu/x86/multiboot.h>
00007
00008
00009 #ifndef CMD_LINE
00010 #define CMD_LINE ""
00011 #endif
00012
00013
00014
00015 #define UPSZ(X) ((sizeof(X) + 3) &~3)
00016
00017 static struct {
00018 Elf_Bhdr hdr;
00019 Elf_Nhdr ft_hdr;
00020 unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)];
00021 Elf_Nhdr bl_hdr;
00022 unsigned char bl_desc[UPSZ(BOOTLOADER)];
00023 Elf_Nhdr blv_hdr;
00024 unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
00025 Elf_Nhdr cmd_hdr;
00026 unsigned char cmd_desc[UPSZ(CMD_LINE)];
00027 } elf_boot_notes = {
00028 .hdr = {
00029 .b_signature = 0x0E1FB007,
00030 .b_size = sizeof(elf_boot_notes),
00031 .b_checksum = 0,
00032 .b_records = 4,
00033 },
00034 .ft_hdr = {
00035 .n_namesz = 0,
00036 .n_descsz = sizeof(FIRMWARE_TYPE),
00037 .n_type = EBN_FIRMWARE_TYPE,
00038 },
00039 .ft_desc = FIRMWARE_TYPE,
00040 .bl_hdr = {
00041 .n_namesz = 0,
00042 .n_descsz = sizeof(BOOTLOADER),
00043 .n_type = EBN_BOOTLOADER_NAME,
00044 },
00045 .bl_desc = BOOTLOADER,
00046 .blv_hdr = {
00047 .n_namesz = 0,
00048 .n_descsz = sizeof(BOOTLOADER_VERSION),
00049 .n_type = EBN_BOOTLOADER_VERSION,
00050 },
00051 .blv_desc = BOOTLOADER_VERSION,
00052 .cmd_hdr = {
00053 .n_namesz = 0,
00054 .n_descsz = sizeof(CMD_LINE),
00055 .n_type = EBN_COMMAND_LINE,
00056 },
00057 .cmd_desc = CMD_LINE,
00058 };
00059
00060
00061 int elf_check_arch(Elf_ehdr *ehdr)
00062 {
00063 return (
00064 ((ehdr->e_machine == EM_386) || (ehdr->e_machine == EM_486)) &&
00065 (ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
00066 (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
00067 );
00068
00069 }
00070
00071 void jmp_to_elf_entry(void *entry, unsigned long buffer)
00072 {
00073 extern unsigned char _ram_seg, _eram_seg;
00074 unsigned long lb_start, lb_size;
00075 unsigned long adjust, adjusted_boot_notes;
00076 unsigned long type;
00077
00078 elf_boot_notes.hdr.b_checksum =
00079 compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes));
00080
00081 type = 0x0E1FB007;
00082 lb_start = (unsigned long)&_ram_seg;
00083 lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
00084 adjust = buffer + lb_size - lb_start;
00085
00086 adjusted_boot_notes = (unsigned long)&elf_boot_notes;
00087 adjusted_boot_notes += adjust;
00088
00089 printk_spew("entry = 0x%08lx\n", (unsigned long)entry);
00090 printk_spew("lb_start = 0x%08lx\n", lb_start);
00091 printk_spew("lb_size = 0x%08lx\n", lb_size);
00092 printk_spew("adjust = 0x%08lx\n", adjust);
00093 printk_spew("buffer = 0x%08lx\n", buffer);
00094 printk_spew(" elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes);
00095 printk_spew("adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes);
00096
00097
00098 __asm__ __volatile__(
00099 " cld \n\t"
00100
00101 " pushl %%esi\n\t"
00102 " pushl %%edi\n\t"
00103 " pushl %%ebx\n\t"
00104
00105 " pushl $0\n\t"
00106 " pushl %0\n\t"
00107 " pushl %1\n\t"
00108 " pushl %2\n\t"
00109 " pushl %3\n\t"
00110 " pushl %4\n\t"
00111
00112 " xorl %%eax, %%eax\n\t"
00113 " subl 16(%%esp), %%eax\n\t"
00114 " addl 12(%%esp), %%eax\n\t"
00115 " addl 8(%%esp), %%eax\n\t"
00116 " movl %%eax, 20(%%esp)\n\t"
00117
00118
00119 " movl 12(%%esp), %%edi\n\t"
00120 " addl 8(%%esp), %%edi\n\t"
00121 " movl 16(%%esp), %%esi\n\t"
00122 " movl 8(%%esp), %%ecx\n\n"
00123 " shrl $2, %%ecx\n\t"
00124 " rep movsl\n\t"
00125
00126
00127 " addl 20(%%esp), %%esp\n\t"
00128
00129 " movl $1f, %%eax\n\t"
00130 " addl 20(%%esp), %%eax\n\t"
00131 " jmp *%%eax\n\t"
00132 "1: \n\t"
00133
00134
00135
00136 " movl 16(%%esp), %%edi\n\t"
00137 " movl 12(%%esp), %%esi\n\t"
00138 " movl 8(%%esp), %%ecx\n\t"
00139 " shrl $2, %%ecx\n\t"
00140 " rep movsl\n\t"
00141
00142
00143 " movl %5, %%eax\n\t"
00144 " movl 0(%%esp), %%ebx\n\t"
00145 " call *4(%%esp)\n\t"
00146
00147
00148 " cli \n\t"
00149 " cld \n\t"
00150
00151
00152
00153 " movl 16(%%esp), %%edi\n\t"
00154 " movl 12(%%esp), %%esi\n\t"
00155 " addl 8(%%esp), %%esi\n\t"
00156 " movl 8(%%esp), %%ecx\n\t"
00157 " shrl $2, %%ecx\n\t"
00158 " rep movsl\n\t"
00159
00160
00161 " subl 20(%%esp), %%esp\n\t"
00162
00163
00164 " movl $1f, %%eax\n\t"
00165 " subl 20(%%esp), %%eax\n\t"
00166 " jmp *%%eax\n\t"
00167 "1: \n\t"
00168
00169
00170 " addl $24, %%esp\n\t"
00171
00172
00173 " popl %%ebx\n\t"
00174 " popl %%edi\n\t"
00175 " popl %%esi\n\t"
00176
00177 ::
00178 "g" (lb_start), "g" (buffer), "g" (lb_size),
00179 "g" (entry),
00180 #if CONFIG_MULTIBOOT
00181 "g"(mbi), "g" (MB_MAGIC2)
00182 #else
00183 "g"(adjusted_boot_notes), "g" (0x0E1FB007)
00184 #endif
00185 );
00186 }
00187
00188