blob: 4892c5e0095adef5376a34bd7945bc66521f2045 [file] [log] [blame]
Eric Biederman8ca8d762003-04-22 19:02:15 +00001#include <console/console.h>
2#include <ip_checksum.h>
3#include <boot/elf.h>
4#include <boot/elf_boot.h>
5#include <string.h>
Robert Millan81af3d42008-11-11 20:20:54 +00006#include <cpu/x86/multiboot.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00007
8
9#ifndef CMD_LINE
10#define CMD_LINE ""
11#endif
12
13
14
15#define UPSZ(X) ((sizeof(X) + 3) &~3)
16
17static struct {
18 Elf_Bhdr hdr;
19 Elf_Nhdr ft_hdr;
20 unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)];
21 Elf_Nhdr bl_hdr;
22 unsigned char bl_desc[UPSZ(BOOTLOADER)];
23 Elf_Nhdr blv_hdr;
24 unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
25 Elf_Nhdr cmd_hdr;
26 unsigned char cmd_desc[UPSZ(CMD_LINE)];
27} elf_boot_notes = {
28 .hdr = {
29 .b_signature = 0x0E1FB007,
30 .b_size = sizeof(elf_boot_notes),
31 .b_checksum = 0,
32 .b_records = 4,
33 },
34 .ft_hdr = {
35 .n_namesz = 0,
36 .n_descsz = sizeof(FIRMWARE_TYPE),
37 .n_type = EBN_FIRMWARE_TYPE,
38 },
39 .ft_desc = FIRMWARE_TYPE,
40 .bl_hdr = {
41 .n_namesz = 0,
42 .n_descsz = sizeof(BOOTLOADER),
43 .n_type = EBN_BOOTLOADER_NAME,
44 },
45 .bl_desc = BOOTLOADER,
46 .blv_hdr = {
47 .n_namesz = 0,
48 .n_descsz = sizeof(BOOTLOADER_VERSION),
49 .n_type = EBN_BOOTLOADER_VERSION,
50 },
51 .blv_desc = BOOTLOADER_VERSION,
52 .cmd_hdr = {
53 .n_namesz = 0,
54 .n_descsz = sizeof(CMD_LINE),
55 .n_type = EBN_COMMAND_LINE,
56 },
57 .cmd_desc = CMD_LINE,
58};
59
60
61int elf_check_arch(Elf_ehdr *ehdr)
62{
63 return (
64 ((ehdr->e_machine == EM_386) || (ehdr->e_machine == EM_486)) &&
65 (ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
Stefan Reinauer14e22772010-04-27 06:56:47 +000066 (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
Eric Biederman8ca8d762003-04-22 19:02:15 +000067 );
Stefan Reinauer14e22772010-04-27 06:56:47 +000068
Eric Biederman8ca8d762003-04-22 19:02:15 +000069}
70
Aaron Durbin8e4a3552013-02-08 17:28:04 -060071#if CONFIG_RELOCATABLE_RAMSTAGE
72/* When the ramstage is relocatable the elf loading ensures an elf image cannot
73 * be loaded over the ramstage code. */
74void jmp_to_elf_entry(void *entry, unsigned long unused1, unsigned long unused2)
75{
76 elf_boot_notes.hdr.b_checksum =
77 compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes));
78
79 /* Jump to kernel */
80 __asm__ __volatile__(
81 " cld \n\t"
82 /* Now jump to the loaded image */
83 " call *%0\n\t"
84
85 /* The loaded image returned? */
86 " cli \n\t"
87 " cld \n\t"
88
89 ::
90 "r" (entry),
91#if CONFIG_MULTIBOOT
92 "b"(mbi), "a" (MB_MAGIC2)
93#else
94 "b"(&elf_boot_notes), "a" (0x0E1FB007)
95#endif
96 );
97}
98#else
Myles Watson92027982009-09-23 20:32:21 +000099void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000100{
101 extern unsigned char _ram_seg, _eram_seg;
102 unsigned long lb_start, lb_size;
103 unsigned long adjust, adjusted_boot_notes;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000104
Stefan Reinauer14e22772010-04-27 06:56:47 +0000105 elf_boot_notes.hdr.b_checksum =
Eric Biederman8ca8d762003-04-22 19:02:15 +0000106 compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes));
107
Eric Biederman8ca8d762003-04-22 19:02:15 +0000108 lb_start = (unsigned long)&_ram_seg;
109 lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
Myles Watson92027982009-09-23 20:32:21 +0000110 adjust = buffer + size - lb_start;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000111
112 adjusted_boot_notes = (unsigned long)&elf_boot_notes;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000113 adjusted_boot_notes += adjust;
Eric Biederman8ca8d762003-04-22 19:02:15 +0000114
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000115 printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry);
116 printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start);
117 printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size);
118 printk(BIOS_SPEW, "adjust = 0x%08lx\n", adjust);
119 printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer);
120 printk(BIOS_SPEW, " elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes);
121 printk(BIOS_SPEW, "adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000122
Eric Biederman8ca8d762003-04-22 19:02:15 +0000123 /* Jump to kernel */
124 __asm__ __volatile__(
125 " cld \n\t"
126 /* Save the callee save registers... */
127 " pushl %%esi\n\t"
128 " pushl %%edi\n\t"
129 " pushl %%ebx\n\t"
130 /* Save the parameters I was passed */
131 " pushl $0\n\t" /* 20 adjust */
132 " pushl %0\n\t" /* 16 lb_start */
133 " pushl %1\n\t" /* 12 buffer */
134 " pushl %2\n\t" /* 8 lb_size */
135 " pushl %3\n\t" /* 4 entry */
136 " pushl %4\n\t" /* 0 elf_boot_notes */
137 /* Compute the adjustment */
138 " xorl %%eax, %%eax\n\t"
139 " subl 16(%%esp), %%eax\n\t"
140 " addl 12(%%esp), %%eax\n\t"
141 " addl 8(%%esp), %%eax\n\t"
142 " movl %%eax, 20(%%esp)\n\t"
Stefan Reinauerf834e202009-03-31 17:17:30 +0000143 /* Place a copy of coreboot in its new location */
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000144 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000145 " movl 12(%%esp), %%edi\n\t"
146 " addl 8(%%esp), %%edi\n\t"
147 " movl 16(%%esp), %%esi\n\t"
148 " movl 8(%%esp), %%ecx\n\n"
149 " shrl $2, %%ecx\n\t"
150 " rep movsl\n\t"
151
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000152 /* Adjust the stack pointer to point into the new coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000153 " addl 20(%%esp), %%esp\n\t"
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000154 /* Adjust the instruction pointer to point into the new coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000155 " movl $1f, %%eax\n\t"
156 " addl 20(%%esp), %%eax\n\t"
157 " jmp *%%eax\n\t"
158 "1: \n\t"
159
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000160 /* Copy the coreboot bounce buffer over coreboot */
161 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000162 " movl 16(%%esp), %%edi\n\t"
163 " movl 12(%%esp), %%esi\n\t"
164 " movl 8(%%esp), %%ecx\n\t"
165 " shrl $2, %%ecx\n\t"
166 " rep movsl\n\t"
167
168 /* Now jump to the loaded image */
Robert Millan81af3d42008-11-11 20:20:54 +0000169 " movl %5, %%eax\n\t"
Eric Biederman8ca8d762003-04-22 19:02:15 +0000170 " movl 0(%%esp), %%ebx\n\t"
171 " call *4(%%esp)\n\t"
172
173 /* The loaded image returned? */
174 " cli \n\t"
175 " cld \n\t"
176
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000177 /* Copy the saved copy of coreboot where coreboot runs */
178 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000179 " movl 16(%%esp), %%edi\n\t"
180 " movl 12(%%esp), %%esi\n\t"
181 " addl 8(%%esp), %%esi\n\t"
182 " movl 8(%%esp), %%ecx\n\t"
183 " shrl $2, %%ecx\n\t"
184 " rep movsl\n\t"
185
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000186 /* Adjust the stack pointer to point into the old coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000187 " subl 20(%%esp), %%esp\n\t"
188
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000189 /* Adjust the instruction pointer to point into the old coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000190 " movl $1f, %%eax\n\t"
191 " subl 20(%%esp), %%eax\n\t"
192 " jmp *%%eax\n\t"
193 "1: \n\t"
194
195 /* Drop the parameters I was passed */
196 " addl $24, %%esp\n\t"
197
198 /* Restore the callee save registers */
199 " popl %%ebx\n\t"
200 " popl %%edi\n\t"
201 " popl %%esi\n\t"
202
Stefan Reinauer14e22772010-04-27 06:56:47 +0000203 ::
Myles Watson2a63ea52009-03-20 18:29:49 +0000204 "ri" (lb_start), "ri" (buffer), "ri" (lb_size),
205 "ri" (entry),
Robert Millan81af3d42008-11-11 20:20:54 +0000206#if CONFIG_MULTIBOOT
Myles Watson2a63ea52009-03-20 18:29:49 +0000207 "ri"(mbi), "ri" (MB_MAGIC2)
Robert Millan81af3d42008-11-11 20:20:54 +0000208#else
Myles Watson2a63ea52009-03-20 18:29:49 +0000209 "ri"(adjusted_boot_notes), "ri" (0x0E1FB007)
Robert Millan81af3d42008-11-11 20:20:54 +0000210#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000211 );
212}
Aaron Durbin8e4a3552013-02-08 17:28:04 -0600213#endif /* CONFIG_RELOCATABLE_RAMSTAGE */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000214
215