blob: edba2d1c3d415fadabedde8e391dfcd44387c17a [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>
6
7
8#ifndef CMD_LINE
9#define CMD_LINE ""
10#endif
11
12
13
14#define UPSZ(X) ((sizeof(X) + 3) &~3)
15
16static struct {
17 Elf_Bhdr hdr;
18 Elf_Nhdr ft_hdr;
19 unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)];
20 Elf_Nhdr bl_hdr;
21 unsigned char bl_desc[UPSZ(BOOTLOADER)];
22 Elf_Nhdr blv_hdr;
23 unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
24 Elf_Nhdr cmd_hdr;
25 unsigned char cmd_desc[UPSZ(CMD_LINE)];
26} elf_boot_notes = {
27 .hdr = {
28 .b_signature = 0x0E1FB007,
29 .b_size = sizeof(elf_boot_notes),
30 .b_checksum = 0,
31 .b_records = 4,
32 },
33 .ft_hdr = {
34 .n_namesz = 0,
35 .n_descsz = sizeof(FIRMWARE_TYPE),
36 .n_type = EBN_FIRMWARE_TYPE,
37 },
38 .ft_desc = FIRMWARE_TYPE,
39 .bl_hdr = {
40 .n_namesz = 0,
41 .n_descsz = sizeof(BOOTLOADER),
42 .n_type = EBN_BOOTLOADER_NAME,
43 },
44 .bl_desc = BOOTLOADER,
45 .blv_hdr = {
46 .n_namesz = 0,
47 .n_descsz = sizeof(BOOTLOADER_VERSION),
48 .n_type = EBN_BOOTLOADER_VERSION,
49 },
50 .blv_desc = BOOTLOADER_VERSION,
51 .cmd_hdr = {
52 .n_namesz = 0,
53 .n_descsz = sizeof(CMD_LINE),
54 .n_type = EBN_COMMAND_LINE,
55 },
56 .cmd_desc = CMD_LINE,
57};
58
59
60int elf_check_arch(Elf_ehdr *ehdr)
61{
62 return (
63 ((ehdr->e_machine == EM_386) || (ehdr->e_machine == EM_486)) &&
64 (ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
65 (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
66 );
67
68}
69
70void jmp_to_elf_entry(void *entry, unsigned long buffer)
71{
72 extern unsigned char _ram_seg, _eram_seg;
73 unsigned long lb_start, lb_size;
74 unsigned long adjust, adjusted_boot_notes;
75 unsigned long type;
76
77 elf_boot_notes.hdr.b_checksum =
78 compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes));
79
80 type = 0x0E1FB007;
81 lb_start = (unsigned long)&_ram_seg;
82 lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
83 adjust = buffer + lb_size - lb_start;
84
85 adjusted_boot_notes = (unsigned long)&elf_boot_notes;
86 adjusted_boot_notes += adjust;
87
88 printk_spew("entry = 0x%08lx\n", (unsigned long)entry);
89 printk_spew("lb_start = 0x%08lx\n", lb_start);
90 printk_spew("lb_size = 0x%08lx\n", lb_size);
91 printk_spew("adjust = 0x%08lx\n", adjust);
92 printk_spew("buffer = 0x%08lx\n", buffer);
93 printk_spew(" elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes);
94 printk_spew("adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes);
95
96 /* Jump to kernel */
97 __asm__ __volatile__(
98 " cld \n\t"
99 /* Save the callee save registers... */
100 " pushl %%esi\n\t"
101 " pushl %%edi\n\t"
102 " pushl %%ebx\n\t"
103 /* Save the parameters I was passed */
104 " pushl $0\n\t" /* 20 adjust */
105 " pushl %0\n\t" /* 16 lb_start */
106 " pushl %1\n\t" /* 12 buffer */
107 " pushl %2\n\t" /* 8 lb_size */
108 " pushl %3\n\t" /* 4 entry */
109 " pushl %4\n\t" /* 0 elf_boot_notes */
110 /* 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 Reinauerf8ee1802008-01-18 15:08:58 +0000116 /* Place a copy of coreboot in it's new location */
117 /* 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 */
142 " movl $0x0E1FB007, %%eax\n\t"
143 " 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"
175
176 ::
177 "g" (lb_start), "g" (buffer), "g" (lb_size),
178 "g" (entry), "g"(adjusted_boot_notes)
179 );
180}
181
182