1
/* boot.c - load and bootstrap a kernel */
3
* GRUB -- GRand Unified Bootloader
4
* Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
#include "imgact_aout.h"
29
static unsigned long cur_addr;
30
entry_func entry_addr;
31
static struct mod_list mll[99];
32
static unsigned long linux_mem_size;
35
* The next two functions, 'load_image' and 'load_module', are the building
36
* blocks of the multiboot loader component. They handle essentially all
37
* of the gory details of loading in a bootable image and the modules.
41
load_image (char *kernel, char *arg, kernel_t suggested_type,
42
unsigned long load_flags)
44
unsigned long len, i, exec_type = 0, align_4k = 1;
45
entry_func real_entry_addr = 0;
46
kernel_t type = KERNEL_TYPE_NONE;
47
unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
48
char *str = 0, *str2 = 0;
49
struct linux_kernel_header *lh;
52
struct multiboot_header *mb;
57
/* presuming that MULTIBOOT_SEARCH is large enough to encompass an
60
unsigned char *buffer = (unsigned char *)(FSYS_BUF - MULTIBOOT_SEARCH);
62
unsigned char buffer[MULTIBOOT_SEARCH];
65
/* sets the header pointer to point to the beginning of the
67
pu.aout = (struct exec *) buffer;
69
if (!grub_open (kernel))
70
return KERNEL_TYPE_NONE;
72
if (!(len = grub_read ((char *)buffer, MULTIBOOT_SEARCH)) || len < 32)
77
errnum = ERR_EXEC_FORMAT;
79
return KERNEL_TYPE_NONE;
82
for (i = 0; i < len; i++)
84
if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
86
flags = ((struct multiboot_header *) (buffer + i))->flags;
87
if (flags & MULTIBOOT_UNSUPPORTED)
90
errnum = ERR_BOOT_FEATURES;
91
return KERNEL_TYPE_NONE;
93
type = KERNEL_TYPE_MULTIBOOT;
99
/* leave graphics mode now before the extended memory is overwritten. */
100
#ifdef SUPPORT_GRAPHICS
104
current_term = term_table; /* assumption: console is first */
108
/* Use BUFFER as a linux kernel header, if the image is Linux zImage
110
lh = (struct linux_kernel_header *) buffer;
112
/* ELF loading supported if multiboot, FreeBSD and NetBSD. */
113
if ((type == KERNEL_TYPE_MULTIBOOT
114
|| pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
115
|| grub_strcmp ((const char *)(pu.elf->e_ident + EI_BRAND), "FreeBSD") == 0
116
|| suggested_type == KERNEL_TYPE_NETBSD)
117
&& len > sizeof (Elf32_Ehdr)
118
&& BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer))))
120
if (type == KERNEL_TYPE_MULTIBOOT)
121
entry_addr = (entry_func) pu.elf->e_entry;
123
entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
125
if (entry_addr < (entry_func) 0x100000)
126
errnum = ERR_BELOW_1MB;
128
/* don't want to deal with ELF program header at some random
129
place in the file -- this generally won't happen */
130
if (pu.elf->e_phoff == 0 || pu.elf->e_phnum == 0
131
|| ((pu.elf->e_phoff + (pu.elf->e_phentsize * pu.elf->e_phnum))
133
errnum = ERR_EXEC_FORMAT;
136
if (type == KERNEL_TYPE_NONE)
138
/* At the moment, there is no way to identify a NetBSD ELF
139
kernel, so rely on the suggested type by the user. */
140
if (suggested_type == KERNEL_TYPE_NETBSD)
143
type = suggested_type;
148
type = KERNEL_TYPE_FREEBSD;
152
else if (flags & MULTIBOOT_AOUT_KLUDGE)
154
pu.mb = (struct multiboot_header *) (buffer + i);
155
entry_addr = (entry_func) pu.mb->entry_addr;
156
cur_addr = pu.mb->load_addr;
157
/* first offset into file */
158
filepos = i - (pu.mb->header_addr - cur_addr);
160
/* If the load end address is zero, load the whole contents. */
161
if (! pu.mb->load_end_addr)
162
pu.mb->load_end_addr = cur_addr + filemax;
164
text_len = pu.mb->load_end_addr - cur_addr;
167
/* If the bss end address is zero, assume that there is no bss area. */
168
if (! pu.mb->bss_end_addr)
169
pu.mb->bss_end_addr = pu.mb->load_end_addr;
171
bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
173
if (pu.mb->header_addr < pu.mb->load_addr
174
|| pu.mb->load_end_addr <= pu.mb->load_addr
175
|| pu.mb->bss_end_addr < pu.mb->load_end_addr
176
|| (pu.mb->header_addr - pu.mb->load_addr) > i)
177
errnum = ERR_EXEC_FORMAT;
179
if (cur_addr < 0x100000)
180
errnum = ERR_BELOW_1MB;
182
pu.aout = (struct exec *) buffer;
186
else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
188
entry_addr = (entry_func) pu.aout->a_entry;
190
if (type == KERNEL_TYPE_NONE)
193
* If it doesn't have a Multiboot header, then presume
194
* it is either a FreeBSD or NetBSD executable. If so,
195
* then use a magic number of normal ordering, ZMAGIC to
196
* determine if it is FreeBSD.
198
* This is all because freebsd and netbsd seem to require
199
* masking out some address bits... differently for each
200
* one... plus of course we need to know which booting
203
entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
205
if (buffer[0] == 0xb && buffer[1] == 1)
207
type = KERNEL_TYPE_FREEBSD;
208
cur_addr = (int) entry_addr;
213
type = KERNEL_TYPE_NETBSD;
214
cur_addr = (int) entry_addr & 0xF00000;
215
if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
221
/* first offset into file */
222
filepos = N_TXTOFF (*(pu.aout));
223
text_len = pu.aout->a_text;
224
data_len = pu.aout->a_data;
225
bss_len = pu.aout->a_bss;
227
if (cur_addr < 0x100000)
228
errnum = ERR_BELOW_1MB;
233
else if (lh->boot_flag == BOOTSEC_SIGNATURE
234
&& lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
237
int setup_sects = lh->setup_sects;
239
if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
241
big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
242
lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
244
/* Put the real mode part at as a high location as possible. */
246
= (char *) ((saved_mem_lower << 10) - LINUX_SETUP_MOVE_SIZE);
247
/* But it must not exceed the traditional area. */
248
if (linux_data_real_addr > (char *) LINUX_OLD_REAL_MODE_ADDR)
249
linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
251
if (lh->version >= 0x0201)
253
lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
254
lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
257
if (lh->version >= 0x0202)
258
lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
261
lh->cl_magic = LINUX_CL_MAGIC;
262
lh->cl_offset = LINUX_CL_OFFSET;
263
lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
268
/* Your kernel is quite old... */
269
lh->cl_magic = LINUX_CL_MAGIC;
270
lh->cl_offset = LINUX_CL_OFFSET;
272
setup_sects = LINUX_DEFAULT_SETUP_SECTS;
274
linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
277
/* If SETUP_SECTS is not set, set it to the default (4). */
279
setup_sects = LINUX_DEFAULT_SETUP_SECTS;
281
data_len = setup_sects << 9;
282
text_len = filemax - data_len - SECTOR_SIZE;
284
linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
287
&& text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
289
grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
290
errnum = ERR_WONT_FIT;
292
else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
293
> RAW_ADDR ((char *) (saved_mem_lower << 10)))
294
errnum = ERR_WONT_FIT;
298
grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
299
(big_linux ? "bzImage" : "zImage"), data_len, text_len);
301
/* Video mode selection support. What a mess! */
302
/* NOTE: Even the word "mess" is not still enough to
303
represent how wrong and bad the Linux video support is,
304
but I don't want to hear complaints from Linux fanatics
309
/* Find the substring "vga=". */
310
vga = grub_strstr (arg, "vga=");
313
char *value = vga + 4;
316
/* Handle special strings. */
317
if (substring ("normal", value, 0) < 1)
318
vid_mode = LINUX_VID_MODE_NORMAL;
319
else if (substring ("ext", value, 0) < 1)
320
vid_mode = LINUX_VID_MODE_EXTENDED;
321
else if (substring ("ask", value, 0) < 1)
322
vid_mode = LINUX_VID_MODE_ASK;
323
else if (safe_parse_maxint (&value, &vid_mode))
327
/* ERRNUM is already set inside the function
328
safe_parse_maxint. */
330
return KERNEL_TYPE_NONE;
333
lh->vid_mode = vid_mode;
337
/* Check the mem= option to limit memory used for initrd. */
341
mem = grub_strstr (arg, "mem=");
344
char *value = mem + 4;
346
safe_parse_maxint (&value, (int *)(void *)&linux_mem_size);
349
case ERR_NUMBER_OVERFLOW:
350
/* If an overflow occurs, use the maximum address for
351
initrd instead. This is good, because MAXINT is
352
greater than LINUX_INITRD_MAX_ADDRESS. */
353
linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
361
switch (grub_tolower (*value))
373
/* Check an overflow. */
374
if (linux_mem_size > (MAXINT >> shift))
375
linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
377
linux_mem_size <<= shift;
391
/* It is possible that DATA_LEN + SECTOR_SIZE is greater than
392
MULTIBOOT_SEARCH, so the data may have been read partially. */
393
if (data_len + SECTOR_SIZE <= MULTIBOOT_SEARCH)
394
grub_memmove (linux_data_tmp_addr, buffer,
395
data_len + SECTOR_SIZE);
398
grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
399
grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
400
data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
403
if (lh->header != LINUX_MAGIC_SIGNATURE ||
404
lh->version < 0x0200)
405
/* Clear the heap space. */
406
grub_memset (linux_data_tmp_addr + ((setup_sects + 1) << 9),
408
(64 - setup_sects - 1) << 9);
410
/* Copy command-line plus memory hack to staging area.
411
NOTE: Linux has a bug that it doesn't handle multiple spaces
412
between two options and a space after a "mem=" option isn't
413
removed correctly so the arguments to init could be like
414
{"init", "", "", NULL}. This affects some not-very-clever
415
shells. Thus, the code below does a trick to avoid the bug.
416
That is, copy "mem=XXX" to the end of the command-line, and
417
avoid to copy spaces unnecessarily. Hell. */
419
char *src = skip_to (0, arg);
420
char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
422
while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
423
*(dest++) = *(src++);
425
/* Old Linux kernels have problems determining the amount of
426
the available memory. To work around this problem, we add
427
the "mem" option to the kernel command line. This has its
428
own drawbacks because newer kernels can determine the
429
memory map more accurately. Boot protocol 2.03, which
430
appeared in Linux 2.4.18, provides a pointer to the kernel
431
version string, so we could check it. But since kernel
432
2.4.18 and newer are known to detect memory reliably, boot
433
protocol 2.03 already implies that the kernel is new
434
enough. The "mem" option is added if neither of the
435
following conditions is met:
436
1) The "mem" option is already present.
437
2) The "kernel" command is used with "--no-mem-option".
438
3) GNU GRUB is configured not to pass the "mem" option.
439
4) The kernel supports boot protocol 2.03 or newer. */
440
if (! grub_strstr (arg, "mem=")
441
&& ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION)
442
&& lh->version < 0x0203 /* kernel version < 2.4.18 */
443
&& dest + 15 < linux_data_tmp_addr + LINUX_CL_END_OFFSET)
451
dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
458
/* offset into file */
459
filepos = data_len + SECTOR_SIZE;
461
cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
462
grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
464
if (errnum == ERR_NONE)
469
if (suggested_type != KERNEL_TYPE_NONE
470
&& ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX)
471
|| (! big_linux && suggested_type != KERNEL_TYPE_LINUX)))
473
errnum = ERR_EXEC_FORMAT;
474
return KERNEL_TYPE_NONE;
478
linux_text_len = text_len;
480
return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
484
else /* no recognizable format */
485
errnum = ERR_EXEC_FORMAT;
487
/* return if error */
491
return KERNEL_TYPE_NONE;
494
/* fill the multiboot info structure */
495
mbi.cmdline = (int) arg;
498
mbi.boot_device = (current_drive << 24) | current_partition;
499
mbi.flags &= ~(MB_INFO_MODS | MB_INFO_AOUT_SYMS | MB_INFO_ELF_SHDR);
500
mbi.syms.a.tabsize = 0;
501
mbi.syms.a.strsize = 0;
506
printf (" [%s-%s", str2, str);
510
if (exec_type) /* can be loaded like a.out */
512
if (flags & MULTIBOOT_AOUT_KLUDGE)
516
printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
518
/* read text, then read data */
519
if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
521
cur_addr += text_len;
523
if (!(flags & MULTIBOOT_AOUT_KLUDGE))
525
/* we have to align to a 4K boundary */
527
cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
533
printf (", data=0x%x", data_len);
535
if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
538
errnum = ERR_EXEC_FORMAT;
539
cur_addr += data_len;
544
memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
548
printf (", bss=0x%x", bss_len);
552
errnum = ERR_EXEC_FORMAT;
554
if (!errnum && pu.aout->a_syms
555
&& pu.aout->a_syms < (filemax - filepos))
557
int symtab_err, orig_addr = cur_addr;
559
/* we should align to a 4K boundary here for good measure */
561
cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
563
mbi.syms.a.addr = cur_addr;
565
*((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
566
cur_addr += sizeof (int);
569
printf (", symtab=0x%x", pu.aout->a_syms);
571
if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
574
cur_addr += pu.aout->a_syms;
575
mbi.syms.a.tabsize = pu.aout->a_syms;
577
if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
579
*((int *) RAW_ADDR (cur_addr)) = i;
580
cur_addr += sizeof (int);
582
mbi.syms.a.strsize = i;
587
printf (", strtab=0x%x", i);
589
symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
603
cur_addr = orig_addr;
604
mbi.syms.a.tabsize = 0;
605
mbi.syms.a.strsize = 0;
609
mbi.flags |= MB_INFO_AOUT_SYMS;
615
unsigned loaded = 0, memaddr, memsiz, filesiz;
618
/* reset this to zero for now */
621
/* scan for program segments */
622
for (i = 0; i < pu.elf->e_phnum; i++)
624
phdr = (Elf32_Phdr *)
625
(pu.elf->e_phoff + ((int) buffer)
626
+ (pu.elf->e_phentsize * i));
627
if (phdr->p_type == PT_LOAD)
629
/* offset into file */
630
filepos = phdr->p_offset;
631
filesiz = phdr->p_filesz;
633
if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
634
memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
636
memaddr = RAW_ADDR (phdr->p_paddr);
638
memsiz = phdr->p_memsz;
639
if (memaddr < RAW_ADDR (0x100000))
640
errnum = ERR_BELOW_1MB;
642
/* If the memory range contains the entry address, get the
643
physical address here. */
644
if (type == KERNEL_TYPE_MULTIBOOT
645
&& (unsigned) entry_addr >= phdr->p_vaddr
646
&& (unsigned) entry_addr < phdr->p_vaddr + memsiz)
647
real_entry_addr = (entry_func) ((unsigned) entry_addr
648
+ memaddr - phdr->p_vaddr);
650
/* make sure we only load what we're supposed to! */
651
if (filesiz > memsiz)
653
/* mark memory as used */
654
if (cur_addr < memaddr + memsiz)
655
cur_addr = memaddr + memsiz;
657
printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
659
/* increment number of segments */
662
/* load the segment */
663
if (memcheck (memaddr, memsiz)
664
&& grub_read ((char *) memaddr, filesiz) == filesiz)
666
if (memsiz > filesiz)
667
memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
677
errnum = ERR_EXEC_FORMAT;
680
/* Load ELF symbols. */
681
Elf32_Shdr *shdr = NULL;
682
int tab_size, sec_size;
685
mbi.syms.e.num = pu.elf->e_shnum;
686
mbi.syms.e.size = pu.elf->e_shentsize;
687
mbi.syms.e.shndx = pu.elf->e_shstrndx;
689
/* We should align to a 4K boundary here for good measure. */
691
cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
693
tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
695
filepos = pu.elf->e_shoff;
696
if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size)
699
mbi.syms.e.addr = cur_addr;
700
shdr = (Elf32_Shdr *) mbi.syms.e.addr;
701
cur_addr += tab_size;
704
printf (", shtab=0x%x", cur_addr);
706
for (i = 0; i < mbi.syms.e.num; i++)
708
/* This section is a loaded section,
710
if (shdr[i].sh_addr != 0)
713
/* This section is empty, so we don't care. */
714
if (shdr[i].sh_size == 0)
717
/* Align the section to a sh_addralign bits boundary. */
718
cur_addr = ((cur_addr + shdr[i].sh_addralign) &
719
- (int) shdr[i].sh_addralign);
721
filepos = shdr[i].sh_offset;
723
sec_size = shdr[i].sh_size;
725
if (! (memcheck (cur_addr, sec_size)
726
&& (grub_read ((char *) RAW_ADDR (cur_addr),
734
shdr[i].sh_addr = cur_addr;
735
cur_addr += sec_size;
741
if (mbi.syms.e.addr < (unsigned long)(RAW_ADDR(0x10000)))
751
mbi.syms.e.shndx = 0;
755
mbi.flags |= MB_INFO_ELF_SHDR;
763
grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
765
/* If the entry address is physically different from that of the ELF
766
header, correct it here. */
768
entry_addr = real_entry_addr;
773
type = KERNEL_TYPE_NONE;
779
if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
781
errnum = ERR_EXEC_FORMAT;
782
return KERNEL_TYPE_NONE;
789
load_module (char *module, char *arg)
793
/* if we are supposed to load on 4K boundaries */
794
cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
796
if (!grub_open (module))
799
len = grub_read ((char *) cur_addr, -1);
807
printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
809
/* these two simply need to be set if any modules are loaded at all */
810
mbi.flags |= MB_INFO_MODS;
811
mbi.mods_addr = (int) mll;
813
mll[mbi.mods_count].cmdline = (int) arg;
814
mll[mbi.mods_count].mod_start = cur_addr;
816
mll[mbi.mods_count].mod_end = cur_addr;
817
mll[mbi.mods_count].pad = 0;
819
/* increment number of modules included */
827
load_initrd (char *initrd)
830
unsigned long moveto;
831
unsigned long max_addr;
832
struct linux_kernel_header *lh
833
= (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
835
#ifndef NO_DECOMPRESSION
836
no_decompression = 1;
839
if (! grub_open (initrd))
842
len = filemax; //grub_read ((char *) cur_addr, -1);
846
errnum = ERR_EXEC_FORMAT; /* empty file */
851
moveto = linux_mem_size;
853
moveto = (saved_mem_upper + 0x400) << 10;
855
moveto = (moveto - len) & 0xfffff000;
856
max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
857
? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
858
if (moveto + len >= max_addr)
859
moveto = (max_addr - len) & 0xfffff000;
861
/* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
863
XXX: Linux 2.2.xx has a bug in the memory range check, which is
864
worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */
866
//memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
867
len = grub_read ((char *) RAW_ADDR (moveto), -1);
875
printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
877
/* FIXME: Should check if the kernel supports INITRD. */
878
lh->ramdisk_image = RAW_ADDR (moveto);
879
lh->ramdisk_size = len;
885
#ifndef NO_DECOMPRESSION
886
no_decompression = 0;
894
/* Dummy function to fake the *BSD boot. */
896
bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
897
int mem_upper, int mem_lower)
905
* All "*_boot" commands depend on the images being loaded into memory
906
* correctly, the variables in this file being set up correctly, and
907
* the root partition being set in the 'saved_drive' and 'saved_partition'
913
bsd_boot (kernel_t type, int bootdev, char *arg)
919
struct bootinfo bi1; //this takes up too much stack!
920
struct bootinfo *bi = &bi1;
921
entry_addr = (entry_func) bsd_boot_entry;
923
struct bootinfo *bi = (struct bootinfo *)mbr; // tmp. use mbr
927
while (*(++arg) && *arg != ' ');
933
while (*str && *str != ' ')
946
clval |= RB_MULTIPLE;
954
clval |= RB_DFLTROOT;
966
if (type == KERNEL_TYPE_FREEBSD)
968
clval |= RB_BOOTINFO;
970
bi->bi_version = BOOTINFO_VERSION;
973
while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
975
bi->bi_kernelname = (unsigned char *)arg + 1;
977
bi->bi_kernelname = 0;
979
bi->bi_nfs_diskless = 0;
980
bi->bi_n_bios_used = 0; /* this field is apparently unused */
982
for (i = 0; i < N_BIOS_GEOM; i++)
984
// struct geometry tmp_geom;
986
/* XXX Should check the return value. */
987
get_diskinfo (i + 0x80, &tmp_geom);
988
/* FIXME: If HEADS or SECTORS is greater than 255, then this will
989
break the geometry information. That is a drawback of BSD
991
bi->bi_bios_geom[i] = (((tmp_geom.cylinders - 1) << 16)
992
+ (((tmp_geom.heads - 1) & 0xff) << 8)
993
+ (tmp_geom.sectors & 0xff));
996
bi->bi_size = sizeof (struct bootinfo);
997
bi->bi_memsizes_valid = 1;
998
bi->bi_bios_dev = saved_drive;
999
bi->bi_basemem = saved_mem_lower;
1000
bi->bi_extmem = extended_memory;
1002
if (mbi.flags & MB_INFO_AOUT_SYMS)
1004
bi->bi_symtab = mbi.syms.a.addr;
1005
bi->bi_esymtab = mbi.syms.a.addr + 4 + mbi.syms.a.tabsize + mbi.syms.a.strsize;
1008
else if (mbi.flags & MB_INFO_ELF_SHDR)
1010
/* FIXME: Should check if a symbol table exists and, if exists,
1011
pass the table to BI. */
1020
/* call entry point */
1021
(*entry_addr) (clval, bootdev, 0, 0, 0, ((int) bi));
1026
* We now pass the various bootstrap parameters to the loaded
1027
* image via the argument list.
1029
* This is the official list:
1033
* arg2 = boot device
1034
* arg3 = start of symbol table (0 if not loaded)
1035
* arg4 = end of symbol table (0 if not loaded)
1036
* arg5 = transfer address from image
1037
* arg6 = transfer address for next image pointer
1038
* arg7 = conventional memory size (640)
1039
* arg8 = extended memory size (8196)
1041
* ...in actuality, we just pass the parameters used by the kernel.
1044
/* call entry point */
1045
unsigned long end_mark;
1047
if (mbi.flags & MB_INFO_AOUT_SYMS)
1048
end_mark = (mbi.syms.a.addr + 4 + mbi.syms.a.tabsize + mbi.syms.a.strsize);
1050
/* FIXME: it should be mbi.syms.e.size. */
1053
(*entry_addr) (clval, bootdev, 0, end_mark, extended_memory, saved_mem_lower);