Rename almost all occurences of LinuxBIOS to coreboot.
[coreboot.git] / src / arch / i386 / boot / boot.c
1 #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
16 static 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
60 int 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
70 void 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"
116                 /* Place a copy of coreboot in it's new location */
117                 /* Move ``longs'' the coreboot size is 4 byte aligned */
118                 "       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
125                 /* Adjust the stack pointer to point into the new coreboot image */
126                 "       addl    20(%%esp), %%esp\n\t"
127                 /* Adjust the instruction pointer to point into the new coreboot image */
128                 "       movl    $1f, %%eax\n\t"
129                 "       addl    20(%%esp), %%eax\n\t"
130                 "       jmp     *%%eax\n\t"
131                 "1:     \n\t"
132
133                 /* Copy the coreboot bounce buffer over coreboot */
134                 /* Move ``longs'' the coreboot size is 4 byte aligned */
135                 "       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
150                 /* Copy the saved copy of coreboot where coreboot runs */
151                 /* Move ``longs'' the coreboot size is 4 byte aligned */
152                 "       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
159                 /* Adjust the stack pointer to point into the old coreboot image */
160                 "       subl    20(%%esp), %%esp\n\t"
161
162                 /* Adjust the instruction pointer to point into the old coreboot image */
163                 "       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