blob: bf9a02bcc00269772efcca71a13dceeccaed04fa [file] [log] [blame]
Eric Biederman8ca8d762003-04-22 19:02:15 +00001#include <console/console.h>
Stefan Reinauere8b08ba2013-05-24 15:09:36 -07002#include <arch/stages.h>
Aaron Durbin04654a22015-03-17 11:43:44 -05003#include <program_loading.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00004#include <ip_checksum.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00005#include <string.h>
Julius Wernerec5e5e02014-08-20 15:29:56 -07006#include <symbols.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00007
Aaron Durbin8e4a3552013-02-08 17:28:04 -06008/* When the ramstage is relocatable the elf loading ensures an elf image cannot
9 * be loaded over the ramstage code. */
Aaron Durbin7d1996c2014-02-24 22:27:39 -060010static void jmp_payload_no_bounce_buffer(void *entry)
Aaron Durbin8e4a3552013-02-08 17:28:04 -060011{
Aaron Durbin8e4a3552013-02-08 17:28:04 -060012 /* Jump to kernel */
13 __asm__ __volatile__(
14 " cld \n\t"
15 /* Now jump to the loaded image */
16 " call *%0\n\t"
17
18 /* The loaded image returned? */
19 " cli \n\t"
20 " cld \n\t"
21
22 ::
Aaron Durbin7ae7fc02013-05-28 16:15:01 -050023 "r" (entry)
Aaron Durbin8e4a3552013-02-08 17:28:04 -060024 );
25}
Aaron Durbin7d1996c2014-02-24 22:27:39 -060026
27static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
Eric Biederman8ca8d762003-04-22 19:02:15 +000028{
Eric Biederman8ca8d762003-04-22 19:02:15 +000029 unsigned long lb_start, lb_size;
Eric Biederman8ca8d762003-04-22 19:02:15 +000030
Julius Wernerec5e5e02014-08-20 15:29:56 -070031 lb_start = (unsigned long)&_program;
32 lb_size = _program_size;
Eric Biederman8ca8d762003-04-22 19:02:15 +000033
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000034 printk(BIOS_SPEW, "entry = 0x%08lx\n", (unsigned long)entry);
35 printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start);
36 printk(BIOS_SPEW, "lb_size = 0x%08lx\n", lb_size);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +000037 printk(BIOS_SPEW, "buffer = 0x%08lx\n", buffer);
Stefan Reinauer14e22772010-04-27 06:56:47 +000038
Eric Biederman8ca8d762003-04-22 19:02:15 +000039 /* Jump to kernel */
40 __asm__ __volatile__(
41 " cld \n\t"
Stefan Reinauer96938852015-06-18 01:23:48 -070042#ifdef __x86_64__
43 /* switch back to 32-bit mode */
44 " push %4\n\t"
45 " push %3\n\t"
46 " push %2\n\t"
47 " push %1\n\t"
48 " push %0\n\t"
49
50 ".intel_syntax noprefix\n\t"
51 /* use iret to switch to 32-bit code segment */
52 " xor rax,rax\n\t"
53 " mov ax, ss\n\t"
54 " push rax\n\t"
55 " mov rax, rsp\n\t"
56 " add rax, 8\n\t"
57 " push rax\n\t"
58 " pushfq\n\t"
59 " push 0x10\n\t"
60 " lea rax,[rip+3]\n\t"
61 " push rax\n\t"
62 " iretq\n\t"
63 ".code32\n\t"
64 /* disable paging */
65 " mov eax, cr0\n\t"
66 " btc eax, 31\n\t"
67 " mov cr0, eax\n\t"
68 /* disable long mode */
69 " mov ecx, 0xC0000080\n\t"
70 " rdmsr\n\t"
71 " btc eax, 8\n\t"
72 " wrmsr\n\t"
73
74 " pop eax\n\t"
75 " add esp, 4\n\t"
76 " pop ebx\n\t"
77 " add esp, 4\n\t"
78 " pop ecx\n\t"
79
80 " add esp, 4\n\t"
81 " pop edx\n\t"
82 " add esp, 4\n\t"
83 " pop esi\n\t"
84 " add esp, 4\n\t"
85
86 ".att_syntax prefix\n\t"
87#endif
88
Eric Biederman8ca8d762003-04-22 19:02:15 +000089 /* Save the callee save registers... */
90 " pushl %%esi\n\t"
91 " pushl %%edi\n\t"
92 " pushl %%ebx\n\t"
93 /* Save the parameters I was passed */
Stefan Reinauer96938852015-06-18 01:23:48 -070094#ifdef __x86_64__
95 " pushl $0\n\t" /* 20 adjust */
96 " pushl %%eax\n\t" /* 16 lb_start */
97 " pushl %%ebx\n\t" /* 12 buffer */
98 " pushl %%ecx\n\t" /* 8 lb_size */
99 " pushl %%edx\n\t" /* 4 entry */
100 " pushl %%esi\n\t" /* 0 elf_boot_notes */
101#else
Eric Biederman8ca8d762003-04-22 19:02:15 +0000102 " pushl $0\n\t" /* 20 adjust */
103 " pushl %0\n\t" /* 16 lb_start */
104 " pushl %1\n\t" /* 12 buffer */
105 " pushl %2\n\t" /* 8 lb_size */
106 " pushl %3\n\t" /* 4 entry */
107 " pushl %4\n\t" /* 0 elf_boot_notes */
Stefan Reinauer96938852015-06-18 01:23:48 -0700108
109#endif
Eric Biederman8ca8d762003-04-22 19:02:15 +0000110 /* Compute the adjustment */
111 " xorl %%eax, %%eax\n\t"
112 " subl 16(%%esp), %%eax\n\t"
113 " addl 12(%%esp), %%eax\n\t"
114 " addl 8(%%esp), %%eax\n\t"
115 " movl %%eax, 20(%%esp)\n\t"
Stefan Reinauerf834e202009-03-31 17:17:30 +0000116 /* Place a copy of coreboot in its new location */
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000117 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000118 " movl 12(%%esp), %%edi\n\t"
119 " addl 8(%%esp), %%edi\n\t"
120 " movl 16(%%esp), %%esi\n\t"
121 " movl 8(%%esp), %%ecx\n\n"
122 " shrl $2, %%ecx\n\t"
123 " rep movsl\n\t"
124
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000125 /* Adjust the stack pointer to point into the new coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000126 " addl 20(%%esp), %%esp\n\t"
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000127 /* Adjust the instruction pointer to point into the new coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000128 " movl $1f, %%eax\n\t"
129 " addl 20(%%esp), %%eax\n\t"
130 " jmp *%%eax\n\t"
131 "1: \n\t"
132
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000133 /* Copy the coreboot bounce buffer over coreboot */
134 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000135 " movl 16(%%esp), %%edi\n\t"
136 " movl 12(%%esp), %%esi\n\t"
137 " movl 8(%%esp), %%ecx\n\t"
138 " shrl $2, %%ecx\n\t"
139 " rep movsl\n\t"
140
141 /* Now jump to the loaded image */
Robert Millan81af3d42008-11-11 20:20:54 +0000142 " movl %5, %%eax\n\t"
Eric Biederman8ca8d762003-04-22 19:02:15 +0000143 " movl 0(%%esp), %%ebx\n\t"
144 " call *4(%%esp)\n\t"
145
146 /* The loaded image returned? */
147 " cli \n\t"
148 " cld \n\t"
149
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000150 /* Copy the saved copy of coreboot where coreboot runs */
151 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000152 " movl 16(%%esp), %%edi\n\t"
153 " movl 12(%%esp), %%esi\n\t"
154 " addl 8(%%esp), %%esi\n\t"
155 " movl 8(%%esp), %%ecx\n\t"
156 " shrl $2, %%ecx\n\t"
157 " rep movsl\n\t"
158
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000159 /* Adjust the stack pointer to point into the old coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000160 " subl 20(%%esp), %%esp\n\t"
161
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000162 /* Adjust the instruction pointer to point into the old coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000163 " movl $1f, %%eax\n\t"
164 " subl 20(%%esp), %%eax\n\t"
165 " jmp *%%eax\n\t"
166 "1: \n\t"
167
168 /* Drop the parameters I was passed */
169 " addl $24, %%esp\n\t"
170
171 /* Restore the callee save registers */
172 " popl %%ebx\n\t"
173 " popl %%edi\n\t"
174 " popl %%esi\n\t"
Stefan Reinauer96938852015-06-18 01:23:48 -0700175#ifdef __x86_64__
176 ".code64\n\t"
177#endif
Stefan Reinauer14e22772010-04-27 06:56:47 +0000178 ::
Myles Watson2a63ea52009-03-20 18:29:49 +0000179 "ri" (lb_start), "ri" (buffer), "ri" (lb_size),
180 "ri" (entry),
Stefan Reinauere8b08ba2013-05-24 15:09:36 -0700181 "ri"(0), "ri" (0)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000182 );
183}
Eric Biederman8ca8d762003-04-22 19:02:15 +0000184
Aaron Durbince9efe02015-03-20 16:37:12 -0500185static void try_payload(struct prog *prog)
Aaron Durbin7d1996c2014-02-24 22:27:39 -0600186{
Aaron Durbin7e7a4df2015-12-08 14:34:35 -0600187 if (prog_type(prog) == PROG_PAYLOAD) {
Aaron Durbince9efe02015-03-20 16:37:12 -0500188 if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE))
189 jmp_payload_no_bounce_buffer(prog_entry(prog));
190 else
191 jmp_payload(prog_entry(prog),
192 (uintptr_t)prog_start(prog),
193 prog_size(prog));
194 }
Aaron Durbin7d1996c2014-02-24 22:27:39 -0600195}
Aaron Durbinb3847e62015-03-20 15:55:08 -0500196
197void arch_prog_run(struct prog *prog)
198{
Aaron Durbince9efe02015-03-20 16:37:12 -0500199 if (ENV_RAMSTAGE)
200 try_payload(prog);
Aaron Durbinb3847e62015-03-20 15:55:08 -0500201 __asm__ volatile (
Stefan Reinauer96938852015-06-18 01:23:48 -0700202#ifdef __x86_64__
203 "jmp *%%rdi\n"
204#else
Aaron Durbinb3847e62015-03-20 15:55:08 -0500205 "jmp *%%edi\n"
Stefan Reinauer96938852015-06-18 01:23:48 -0700206#endif
207
Aaron Durbinb3847e62015-03-20 15:55:08 -0500208 :: "D"(prog_entry(prog))
209 );
210}