boot.c

Go to the documentation of this file.
00001 #include <console/console.h>
00002 #include <ip_checksum.h>
00003 #include <boot/elf.h>
00004 #include <boot/elf_boot.h>
00005 #include <string.h>
00006 #include <cpu/x86/multiboot.h>
00007 
00008 
00009 #ifndef CMD_LINE
00010 #define CMD_LINE ""
00011 #endif
00012 
00013 
00014 
00015 #define UPSZ(X) ((sizeof(X) + 3) &~3)
00016 
00017 static struct {
00018         Elf_Bhdr hdr;
00019         Elf_Nhdr ft_hdr;
00020         unsigned char ft_desc[UPSZ(FIRMWARE_TYPE)];
00021         Elf_Nhdr bl_hdr;
00022         unsigned char bl_desc[UPSZ(BOOTLOADER)];
00023         Elf_Nhdr blv_hdr;
00024         unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)];
00025         Elf_Nhdr cmd_hdr;
00026         unsigned char cmd_desc[UPSZ(CMD_LINE)];
00027 } elf_boot_notes = {
00028         .hdr = {
00029                 .b_signature = 0x0E1FB007,
00030                 .b_size = sizeof(elf_boot_notes),
00031                 .b_checksum = 0,
00032                 .b_records = 4,
00033         },
00034         .ft_hdr = {
00035                 .n_namesz = 0,
00036                 .n_descsz = sizeof(FIRMWARE_TYPE),
00037                 .n_type = EBN_FIRMWARE_TYPE,
00038         },
00039         .ft_desc = FIRMWARE_TYPE,
00040         .bl_hdr = {
00041                 .n_namesz = 0,
00042                 .n_descsz = sizeof(BOOTLOADER),
00043                 .n_type = EBN_BOOTLOADER_NAME,
00044         },
00045         .bl_desc = BOOTLOADER,
00046         .blv_hdr = {
00047                 .n_namesz = 0,
00048                 .n_descsz = sizeof(BOOTLOADER_VERSION),
00049                 .n_type = EBN_BOOTLOADER_VERSION,
00050         },
00051         .blv_desc = BOOTLOADER_VERSION,
00052         .cmd_hdr = {
00053                 .n_namesz = 0,
00054                 .n_descsz = sizeof(CMD_LINE),
00055                 .n_type = EBN_COMMAND_LINE,
00056         },
00057         .cmd_desc = CMD_LINE,
00058 };
00059 
00060 
00061 int elf_check_arch(Elf_ehdr *ehdr)
00062 {
00063         return (
00064                 ((ehdr->e_machine == EM_386) || (ehdr->e_machine == EM_486)) &&
00065                 (ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
00066                 (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) 
00067                 );
00068         
00069 }
00070 
00071 void jmp_to_elf_entry(void *entry, unsigned long buffer)
00072 {
00073         extern unsigned char _ram_seg, _eram_seg;
00074         unsigned long lb_start, lb_size;
00075         unsigned long adjust, adjusted_boot_notes;
00076         unsigned long type;
00077 
00078         elf_boot_notes.hdr.b_checksum = 
00079                 compute_ip_checksum(&elf_boot_notes, sizeof(elf_boot_notes));
00080 
00081         type = 0x0E1FB007;
00082         lb_start = (unsigned long)&_ram_seg;
00083         lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
00084         adjust = buffer + lb_size - lb_start;
00085 
00086         adjusted_boot_notes = (unsigned long)&elf_boot_notes;
00087         adjusted_boot_notes += adjust; 
00088 
00089         printk_spew("entry    = 0x%08lx\n", (unsigned long)entry);
00090         printk_spew("lb_start = 0x%08lx\n", lb_start);
00091         printk_spew("lb_size  = 0x%08lx\n", lb_size);
00092         printk_spew("adjust   = 0x%08lx\n", adjust);
00093         printk_spew("buffer   = 0x%08lx\n", buffer);
00094         printk_spew("     elf_boot_notes = 0x%08lx\n", (unsigned long)&elf_boot_notes);
00095         printk_spew("adjusted_boot_notes = 0x%08lx\n", adjusted_boot_notes);
00096         
00097         /* Jump to kernel */
00098         __asm__ __volatile__(
00099                 "       cld     \n\t"
00100                 /* Save the callee save registers... */
00101                 "       pushl   %%esi\n\t"
00102                 "       pushl   %%edi\n\t"
00103                 "       pushl   %%ebx\n\t"
00104                 /* Save the parameters I was passed */
00105                 "       pushl   $0\n\t" /* 20 adjust */
00106                 "       pushl   %0\n\t" /* 16 lb_start */
00107                 "       pushl   %1\n\t" /* 12 buffer */
00108                 "       pushl   %2\n\t" /*  8 lb_size */
00109                 "       pushl   %3\n\t" /*  4 entry */
00110                 "       pushl   %4\n\t" /*  0 elf_boot_notes */
00111                 /* Compute the adjustment */
00112                 "       xorl    %%eax, %%eax\n\t"
00113                 "       subl    16(%%esp), %%eax\n\t"
00114                 "       addl    12(%%esp), %%eax\n\t"
00115                 "       addl     8(%%esp), %%eax\n\t"
00116                 "       movl    %%eax, 20(%%esp)\n\t"
00117                 /* Place a copy of coreboot in it's new location */
00118                 /* Move ``longs'' the coreboot size is 4 byte aligned */
00119                 "       movl    12(%%esp), %%edi\n\t"
00120                 "       addl     8(%%esp), %%edi\n\t"
00121                 "       movl    16(%%esp), %%esi\n\t"
00122                 "       movl     8(%%esp), %%ecx\n\n"
00123                 "       shrl    $2, %%ecx\n\t"
00124                 "       rep     movsl\n\t"
00125 
00126                 /* Adjust the stack pointer to point into the new coreboot image */
00127                 "       addl    20(%%esp), %%esp\n\t"
00128                 /* Adjust the instruction pointer to point into the new coreboot image */
00129                 "       movl    $1f, %%eax\n\t"
00130                 "       addl    20(%%esp), %%eax\n\t"
00131                 "       jmp     *%%eax\n\t"
00132                 "1:     \n\t"
00133 
00134                 /* Copy the coreboot bounce buffer over coreboot */
00135                 /* Move ``longs'' the coreboot size is 4 byte aligned */
00136                 "       movl    16(%%esp), %%edi\n\t"
00137                 "       movl    12(%%esp), %%esi\n\t"
00138                 "       movl     8(%%esp), %%ecx\n\t"
00139                 "       shrl    $2, %%ecx\n\t"
00140                 "       rep     movsl\n\t"
00141 
00142                 /* Now jump to the loaded image */
00143                 "       movl    %5, %%eax\n\t"
00144                 "       movl     0(%%esp), %%ebx\n\t"
00145                 "       call    *4(%%esp)\n\t"
00146 
00147                 /* The loaded image returned? */
00148                 "       cli     \n\t"
00149                 "       cld     \n\t"
00150 
00151                 /* Copy the saved copy of coreboot where coreboot runs */
00152                 /* Move ``longs'' the coreboot size is 4 byte aligned */
00153                 "       movl    16(%%esp), %%edi\n\t"
00154                 "       movl    12(%%esp), %%esi\n\t"
00155                 "       addl     8(%%esp), %%esi\n\t"
00156                 "       movl     8(%%esp), %%ecx\n\t"
00157                 "       shrl    $2, %%ecx\n\t"
00158                 "       rep     movsl\n\t"
00159 
00160                 /* Adjust the stack pointer to point into the old coreboot image */
00161                 "       subl    20(%%esp), %%esp\n\t"
00162 
00163                 /* Adjust the instruction pointer to point into the old coreboot image */
00164                 "       movl    $1f, %%eax\n\t"
00165                 "       subl    20(%%esp), %%eax\n\t"
00166                 "       jmp     *%%eax\n\t"
00167                 "1:     \n\t"
00168 
00169                 /* Drop the parameters I was passed */
00170                 "       addl    $24, %%esp\n\t"
00171 
00172                 /* Restore the callee save registers */
00173                 "       popl    %%ebx\n\t"
00174                 "       popl    %%edi\n\t"
00175                 "       popl    %%esi\n\t"
00176 
00177                 :: 
00178                 "g" (lb_start), "g" (buffer), "g" (lb_size),
00179                 "g" (entry),
00180 #if CONFIG_MULTIBOOT
00181                 "g"(mbi), "g" (MB_MAGIC2)
00182 #else
00183                 "g"(adjusted_boot_notes), "g" (0x0E1FB007)
00184 #endif
00185                 );
00186 }
00187 
00188 

Generated on Mon Dec 29 10:54:06 2008 for coreboot by  doxygen 1.5.5