blob: 29070a0ce17596523ed59097dd1396a1d170a6bc [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 Durbin7d1996c2014-02-24 22:27:39 -06003#include <payload_loader.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00004#include <ip_checksum.h>
Eric Biederman8ca8d762003-04-22 19:02:15 +00005#include <string.h>
6
Aaron Durbin8e4a3552013-02-08 17:28:04 -06007/* When the ramstage is relocatable the elf loading ensures an elf image cannot
8 * be loaded over the ramstage code. */
Aaron Durbin7d1996c2014-02-24 22:27:39 -06009static void jmp_payload_no_bounce_buffer(void *entry)
Aaron Durbin8e4a3552013-02-08 17:28:04 -060010{
Aaron Durbin8e4a3552013-02-08 17:28:04 -060011 /* Jump to kernel */
12 __asm__ __volatile__(
13 " cld \n\t"
14 /* Now jump to the loaded image */
15 " call *%0\n\t"
16
17 /* The loaded image returned? */
18 " cli \n\t"
19 " cld \n\t"
20
21 ::
Aaron Durbin7ae7fc02013-05-28 16:15:01 -050022 "r" (entry)
Aaron Durbin8e4a3552013-02-08 17:28:04 -060023 );
24}
Aaron Durbin7d1996c2014-02-24 22:27:39 -060025
26static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
Eric Biederman8ca8d762003-04-22 19:02:15 +000027{
28 extern unsigned char _ram_seg, _eram_seg;
29 unsigned long lb_start, lb_size;
Eric Biederman8ca8d762003-04-22 19:02:15 +000030
Eric Biederman8ca8d762003-04-22 19:02:15 +000031 lb_start = (unsigned long)&_ram_seg;
32 lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
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"
42 /* Save the callee save registers... */
43 " pushl %%esi\n\t"
44 " pushl %%edi\n\t"
45 " pushl %%ebx\n\t"
46 /* Save the parameters I was passed */
47 " pushl $0\n\t" /* 20 adjust */
48 " pushl %0\n\t" /* 16 lb_start */
49 " pushl %1\n\t" /* 12 buffer */
50 " pushl %2\n\t" /* 8 lb_size */
51 " pushl %3\n\t" /* 4 entry */
52 " pushl %4\n\t" /* 0 elf_boot_notes */
53 /* Compute the adjustment */
54 " xorl %%eax, %%eax\n\t"
55 " subl 16(%%esp), %%eax\n\t"
56 " addl 12(%%esp), %%eax\n\t"
57 " addl 8(%%esp), %%eax\n\t"
58 " movl %%eax, 20(%%esp)\n\t"
Stefan Reinauerf834e202009-03-31 17:17:30 +000059 /* Place a copy of coreboot in its new location */
Stefan Reinauerf8ee1802008-01-18 15:08:58 +000060 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +000061 " movl 12(%%esp), %%edi\n\t"
62 " addl 8(%%esp), %%edi\n\t"
63 " movl 16(%%esp), %%esi\n\t"
64 " movl 8(%%esp), %%ecx\n\n"
65 " shrl $2, %%ecx\n\t"
66 " rep movsl\n\t"
67
Stefan Reinauerf8ee1802008-01-18 15:08:58 +000068 /* Adjust the stack pointer to point into the new coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +000069 " addl 20(%%esp), %%esp\n\t"
Stefan Reinauerf8ee1802008-01-18 15:08:58 +000070 /* Adjust the instruction pointer to point into the new coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +000071 " movl $1f, %%eax\n\t"
72 " addl 20(%%esp), %%eax\n\t"
73 " jmp *%%eax\n\t"
74 "1: \n\t"
75
Stefan Reinauerf8ee1802008-01-18 15:08:58 +000076 /* Copy the coreboot bounce buffer over coreboot */
77 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +000078 " movl 16(%%esp), %%edi\n\t"
79 " movl 12(%%esp), %%esi\n\t"
80 " movl 8(%%esp), %%ecx\n\t"
81 " shrl $2, %%ecx\n\t"
82 " rep movsl\n\t"
83
84 /* Now jump to the loaded image */
Robert Millan81af3d42008-11-11 20:20:54 +000085 " movl %5, %%eax\n\t"
Eric Biederman8ca8d762003-04-22 19:02:15 +000086 " movl 0(%%esp), %%ebx\n\t"
87 " call *4(%%esp)\n\t"
88
89 /* The loaded image returned? */
90 " cli \n\t"
91 " cld \n\t"
92
Stefan Reinauerf8ee1802008-01-18 15:08:58 +000093 /* Copy the saved copy of coreboot where coreboot runs */
94 /* Move ``longs'' the coreboot size is 4 byte aligned */
Eric Biederman8ca8d762003-04-22 19:02:15 +000095 " movl 16(%%esp), %%edi\n\t"
96 " movl 12(%%esp), %%esi\n\t"
97 " addl 8(%%esp), %%esi\n\t"
98 " movl 8(%%esp), %%ecx\n\t"
99 " shrl $2, %%ecx\n\t"
100 " rep movsl\n\t"
101
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000102 /* Adjust the stack pointer to point into the old coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000103 " subl 20(%%esp), %%esp\n\t"
104
Stefan Reinauerf8ee1802008-01-18 15:08:58 +0000105 /* Adjust the instruction pointer to point into the old coreboot image */
Eric Biederman8ca8d762003-04-22 19:02:15 +0000106 " movl $1f, %%eax\n\t"
107 " subl 20(%%esp), %%eax\n\t"
108 " jmp *%%eax\n\t"
109 "1: \n\t"
110
111 /* Drop the parameters I was passed */
112 " addl $24, %%esp\n\t"
113
114 /* Restore the callee save registers */
115 " popl %%ebx\n\t"
116 " popl %%edi\n\t"
117 " popl %%esi\n\t"
118
Stefan Reinauer14e22772010-04-27 06:56:47 +0000119 ::
Myles Watson2a63ea52009-03-20 18:29:49 +0000120 "ri" (lb_start), "ri" (buffer), "ri" (lb_size),
121 "ri" (entry),
Stefan Reinauere8b08ba2013-05-24 15:09:36 -0700122 "ri"(0), "ri" (0)
Eric Biederman8ca8d762003-04-22 19:02:15 +0000123 );
124}
Eric Biederman8ca8d762003-04-22 19:02:15 +0000125
Aaron Durbin7d1996c2014-02-24 22:27:39 -0600126void arch_payload_run(const struct payload *payload)
127{
128 if (IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE))
129 jmp_payload_no_bounce_buffer(payload->entry);
130 else
131 jmp_payload(payload->entry, (uintptr_t)payload->bounce.data,
132 payload->bounce.size);
133}