freebsd_loader.c
Go to the documentation of this file.00001
00002 #define BOOTINFO_VERSION 1
00003 #define NODEV (-1)
00004 #define PAGE_SHIFT 12
00005 #define PAGE_SIZE (1<<PAGE_SHIFT)
00006 #define PAGE_MASK (PAGE_SIZE-1)
00007 #define N_BIOS_GEOM 8
00008
00009 struct bootinfo {
00010 unsigned int bi_version;
00011 const unsigned char *bi_kernelname;
00012 struct nfs_diskless *bi_nfs_diskless;
00013
00014 #define bi_endcommon bi_n_bios_used
00015 unsigned int bi_n_bios_used;
00016 unsigned long bi_bios_geom[N_BIOS_GEOM];
00017 unsigned int bi_size;
00018 unsigned char bi_memsizes_valid;
00019 unsigned char bi_pad[3];
00020 unsigned long bi_basemem;
00021 unsigned long bi_extmem;
00022 unsigned long bi_symtab;
00023 unsigned long bi_esymtab;
00024
00025 unsigned long bi_kernend;
00026 unsigned long bi_envp;
00027 unsigned long bi_modulep;
00028 };
00029
00030 static struct bootinfo bsdinfo;
00031
00032 #ifdef ELF_IMAGE
00033 static Elf32_Shdr *shdr;
00034 static Address symtab_load;
00035 static Address symstr_load;
00036 static int symtabindex;
00037 static int symstrindex;
00038 #endif
00039
00040 static enum {
00041 Unknown, Tagged, Aout, Elf, Aout_FreeBSD, Elf_FreeBSD,
00042 } image_type = Unknown;
00043
00044 static unsigned int off;
00045
00046
00047 #ifdef ELF_IMAGE
00048 static void elf_freebsd_probe(void)
00049 {
00050 image_type = Elf;
00051 if ( (estate.e.elf32.e_entry & 0xf0000000) &&
00052 (estate.e.elf32.e_type == ET_EXEC))
00053 {
00054 image_type = Elf_FreeBSD;
00055 printf("/FreeBSD");
00056 off = -(estate.e.elf32.e_entry & 0xff000000);
00057 estate.e.elf32.e_entry += off;
00058 }
00059
00060 shdr = 0;
00061
00062
00063 symtabindex = -1;
00064 symstrindex = -1;
00065
00066
00067 symtab_load = 0;
00068 symstr_load = 0;
00069 }
00070
00071 static void elf_freebsd_fixup_segment(void)
00072 {
00073 if (image_type == Elf_FreeBSD) {
00074 estate.p.phdr32[estate.segment].p_paddr += off;
00075 }
00076 }
00077
00078 static void elf_freebsd_find_segment_end(void)
00079 {
00080
00081
00082
00083
00084
00085
00086
00087 estate.curaddr +=
00088 (estate.p.phdr32[estate.segment].p_memsz -
00089 estate.p.phdr32[estate.segment].p_filesz);
00090 }
00091
00092 static int elf_freebsd_debug_loader(unsigned int offset)
00093 {
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 estate.curaddr = (estate.curaddr + sizeof(long) - 1) & ~(sizeof(long) - 1);
00133
00134
00135 if (shdr == 0)
00136 {
00137 estate.toread = estate.e.elf32.e_shnum * estate.e.elf32.e_shentsize;
00138 estate.skip = estate.e.elf32.e_shoff - (estate.loc + offset);
00139 if (estate.toread)
00140 {
00141 #if ELF_DEBUG
00142 printf("shdr *, size %lX, curaddr %lX\n",
00143 estate.toread, estate.curaddr);
00144 #endif
00145
00146
00147 shdr = (Elf32_Shdr *)phys_to_virt(estate.curaddr);
00148
00149
00150 return 1;
00151 }
00152 }
00153 else
00154 {
00155
00156
00157 if ((symtabindex == -1) && (symstrindex == -1))
00158 {
00159 int i;
00160
00161
00162 estate.curaddr = (estate.curaddr + 4095) & ~4095;
00163
00164
00165 for (i=0; i < estate.e.elf32.e_shnum; i++)
00166 {
00167 if (shdr[i].sh_type == SHT_SYMTAB)
00168 {
00169 int j;
00170 for (j=0; j < estate.e.elf32.e_phnum; j++)
00171 {
00172
00173 if ((estate.p.phdr32[j].p_type | 0x80) == (PT_LOAD | 0x80))
00174 {
00175
00176 if ((shdr[i].sh_offset >= estate.p.phdr32[j].p_offset) &&
00177 ((shdr[i].sh_offset + shdr[i].sh_size) <=
00178 (estate.p.phdr32[j].p_offset + estate.p.phdr32[j].p_filesz)))
00179 {
00180 shdr[i].sh_offset=0;
00181 shdr[i].sh_size=0;
00182 break;
00183 }
00184 }
00185 }
00186 if ((shdr[i].sh_offset != 0) && (shdr[i].sh_size != 0))
00187 {
00188 symtabindex = i;
00189 symstrindex = shdr[i].sh_link;
00190 }
00191 }
00192 }
00193 }
00194
00195
00196 if ((symtab_load == 0) && (symtabindex >= 0))
00197 {
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 estate.skip = shdr[symtabindex].sh_offset - (estate.loc + offset);
00208
00209
00210 estate.toread = shdr[symtabindex].sh_size;
00211
00212 if (estate.toread)
00213 {
00214 #if ELF_DEBUG
00215 printf("db sym, size %lX, curaddr %lX\n",
00216 estate.toread, estate.curaddr);
00217 #endif
00218
00219 symtab_load = estate.curaddr;
00220
00221 *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
00222 estate.curaddr += sizeof(long);
00223
00224
00225 return 1;
00226 }
00227 }
00228 else if ((symstr_load == 0) && (symstrindex >= 0))
00229 {
00230
00231
00232
00233
00234
00235 estate.skip = shdr[symstrindex].sh_offset - (estate.loc + offset);
00236
00237
00238 estate.toread = shdr[symstrindex].sh_size;
00239
00240 if (estate.toread)
00241 {
00242 #if ELF_DEBUG
00243 printf("db str, size %lX, curaddr %lX\n",
00244 estate.toread, estate.curaddr);
00245 #endif
00246
00247 symstr_load = estate.curaddr;
00248
00249 *((long *)phys_to_virt(estate.curaddr)) = estate.toread;
00250 estate.curaddr += sizeof(long);
00251
00252
00253 return 1;
00254 }
00255 }
00256 }
00257
00258 return 0;
00259 }
00260
00261 static void elf_freebsd_boot(unsigned long entry)
00262 {
00263 if (image_type != Elf_FreeBSD)
00264 return;
00265
00266 memset(&bsdinfo, 0, sizeof(bsdinfo));
00267 bsdinfo.bi_basemem = meminfo.basememsize;
00268 bsdinfo.bi_extmem = meminfo.memsize;
00269 bsdinfo.bi_memsizes_valid = 1;
00270 bsdinfo.bi_version = BOOTINFO_VERSION;
00271 bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
00272 bsdinfo.bi_nfs_diskless = NULL;
00273 bsdinfo.bi_size = sizeof(bsdinfo);
00274 #define RB_BOOTINFO 0x80000000
00275 if(freebsd_kernel_env[0] != '\0'){
00276 freebsd_howto |= RB_BOOTINFO;
00277 bsdinfo.bi_envp = (unsigned long)freebsd_kernel_env;
00278 }
00279
00280
00281
00282
00283 if ((symtab_load !=0) && (symstr_load != 0))
00284 {
00285 unsigned long *t;
00286
00287 bsdinfo.bi_symtab = symtab_load;
00288
00289
00290
00291 bsdinfo.bi_esymtab = (symstr_load +
00292 sizeof(long) +
00293 *((long *)phys_to_virt(symstr_load)) +
00294 sizeof(long) - 1) & ~(sizeof(long) - 1);
00295
00296
00297 t = phys_to_virt(bsdinfo.bi_esymtab);
00298
00299 #if ELF_DEBUG
00300 printf("Metadata at %lX\n",t);
00301 #endif
00302
00303
00304 bsdinfo.bi_modulep = virt_to_phys(t);
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 *t++=MODINFO_NAME; *t++= 7; *t++=0x6E72656B; *t++=0x00006C65;
00317
00318
00319 *t++=MODINFO_TYPE; *t++=11; *t++=0x20666C65; *t++=0x6E72656B; *t++ = 0x00006C65;
00320
00321
00322
00323
00324 *t++=MODINFOMD_SSYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_symtab;
00325 *t++=MODINFOMD_ESYM | MODINFO_METADATA; *t++=sizeof(*t); *t++=bsdinfo.bi_esymtab;
00326
00327 *t++=MODINFO_END; *t++=0;
00328
00329
00330
00331
00332
00333 bsdinfo.bi_kernend = virt_to_phys(t);
00334
00335
00336
00337 freebsd_howto |= 0x80000000;
00338 }
00339
00340 xstart32(entry, freebsd_howto, NODEV, 0, 0, 0,
00341 virt_to_phys(&bsdinfo), 0, 0, 0);
00342 longjmp(restart_etherboot, -2);
00343 }
00344 #endif
00345
00346 #ifdef AOUT_IMAGE
00347 static void aout_freebsd_probe(void)
00348 {
00349 image_type = Aout;
00350 if (((astate.head.a_midmag >> 16) & 0xffff) == 0) {
00351
00352
00353
00354 image_type = Aout_FreeBSD;
00355 printf("/FreeBSD");
00356 off = -(astate.head.a_entry & 0xff000000);
00357 astate.head.a_entry += off;
00358 }
00359 }
00360
00361 static void aout_freebsd_boot(void)
00362 {
00363 if (image_type == Aout_FreeBSD) {
00364 memset(&bsdinfo, 0, sizeof(bsdinfo));
00365 bsdinfo.bi_basemem = meminfo.basememsize;
00366 bsdinfo.bi_extmem = meminfo.memsize;
00367 bsdinfo.bi_memsizes_valid = 1;
00368 bsdinfo.bi_version = BOOTINFO_VERSION;
00369 bsdinfo.bi_kernelname = virt_to_phys(KERNEL_BUF);
00370 bsdinfo.bi_nfs_diskless = NULL;
00371 bsdinfo.bi_size = sizeof(bsdinfo);
00372 xstart32(astate.head.a_entry, freebsd_howto, NODEV, 0, 0, 0,
00373 virt_to_phys(&bsdinfo), 0, 0, 0);
00374 longjmp(restart_etherboot, -2);
00375 }
00376 }
00377 #endif