1*1b8adde7SWilliam Kucharski /* boot.c - load and bootstrap a kernel */
2*1b8adde7SWilliam Kucharski /*
3*1b8adde7SWilliam Kucharski * GRUB -- GRand Unified Bootloader
4*1b8adde7SWilliam Kucharski * Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
5*1b8adde7SWilliam Kucharski *
6*1b8adde7SWilliam Kucharski * This program is free software; you can redistribute it and/or modify
7*1b8adde7SWilliam Kucharski * it under the terms of the GNU General Public License as published by
8*1b8adde7SWilliam Kucharski * the Free Software Foundation; either version 2 of the License, or
9*1b8adde7SWilliam Kucharski * (at your option) any later version.
10*1b8adde7SWilliam Kucharski *
11*1b8adde7SWilliam Kucharski * This program is distributed in the hope that it will be useful,
12*1b8adde7SWilliam Kucharski * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*1b8adde7SWilliam Kucharski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*1b8adde7SWilliam Kucharski * GNU General Public License for more details.
15*1b8adde7SWilliam Kucharski *
16*1b8adde7SWilliam Kucharski * You should have received a copy of the GNU General Public License
17*1b8adde7SWilliam Kucharski * along with this program; if not, write to the Free Software
18*1b8adde7SWilliam Kucharski * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*1b8adde7SWilliam Kucharski */
20*1b8adde7SWilliam Kucharski
21*1b8adde7SWilliam Kucharski
22*1b8adde7SWilliam Kucharski #include "shared.h"
23*1b8adde7SWilliam Kucharski
24*1b8adde7SWilliam Kucharski #include "freebsd.h"
25*1b8adde7SWilliam Kucharski #include "imgact_aout.h"
26*1b8adde7SWilliam Kucharski #include "i386-elf.h"
27*1b8adde7SWilliam Kucharski
28*1b8adde7SWilliam Kucharski static int cur_addr;
29*1b8adde7SWilliam Kucharski entry_func entry_addr;
30*1b8adde7SWilliam Kucharski static struct mod_list mll[99];
31*1b8adde7SWilliam Kucharski static int linux_mem_size;
32*1b8adde7SWilliam Kucharski
33*1b8adde7SWilliam Kucharski /*
34*1b8adde7SWilliam Kucharski * The next two functions, 'load_image' and 'load_module', are the building
35*1b8adde7SWilliam Kucharski * blocks of the multiboot loader component. They handle essentially all
36*1b8adde7SWilliam Kucharski * of the gory details of loading in a bootable image and the modules.
37*1b8adde7SWilliam Kucharski */
38*1b8adde7SWilliam Kucharski
39*1b8adde7SWilliam Kucharski kernel_t
load_image(char * kernel,char * arg,kernel_t suggested_type,unsigned long load_flags)40*1b8adde7SWilliam Kucharski load_image (char *kernel, char *arg, kernel_t suggested_type,
41*1b8adde7SWilliam Kucharski unsigned long load_flags)
42*1b8adde7SWilliam Kucharski {
43*1b8adde7SWilliam Kucharski int len, i, exec_type = 0, align_4k = 1;
44*1b8adde7SWilliam Kucharski entry_func real_entry_addr = 0;
45*1b8adde7SWilliam Kucharski kernel_t type = KERNEL_TYPE_NONE;
46*1b8adde7SWilliam Kucharski unsigned long flags = 0, text_len = 0, data_len = 0, bss_len = 0;
47*1b8adde7SWilliam Kucharski char *str = 0, *str2 = 0;
48*1b8adde7SWilliam Kucharski struct linux_kernel_header *lh;
49*1b8adde7SWilliam Kucharski union
50*1b8adde7SWilliam Kucharski {
51*1b8adde7SWilliam Kucharski struct multiboot_header *mb;
52*1b8adde7SWilliam Kucharski struct exec *aout;
53*1b8adde7SWilliam Kucharski Elf32_Ehdr *elf;
54*1b8adde7SWilliam Kucharski }
55*1b8adde7SWilliam Kucharski pu;
56*1b8adde7SWilliam Kucharski /* presuming that MULTIBOOT_SEARCH is large enough to encompass an
57*1b8adde7SWilliam Kucharski executable header */
58*1b8adde7SWilliam Kucharski unsigned char buffer[MULTIBOOT_SEARCH];
59*1b8adde7SWilliam Kucharski
60*1b8adde7SWilliam Kucharski /* sets the header pointer to point to the beginning of the
61*1b8adde7SWilliam Kucharski buffer by default */
62*1b8adde7SWilliam Kucharski pu.aout = (struct exec *) buffer;
63*1b8adde7SWilliam Kucharski
64*1b8adde7SWilliam Kucharski if (!grub_open (kernel))
65*1b8adde7SWilliam Kucharski return KERNEL_TYPE_NONE;
66*1b8adde7SWilliam Kucharski
67*1b8adde7SWilliam Kucharski if (!(len = grub_read (buffer, MULTIBOOT_SEARCH)) || len < 32)
68*1b8adde7SWilliam Kucharski {
69*1b8adde7SWilliam Kucharski grub_close ();
70*1b8adde7SWilliam Kucharski
71*1b8adde7SWilliam Kucharski if (!errnum)
72*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
73*1b8adde7SWilliam Kucharski
74*1b8adde7SWilliam Kucharski return KERNEL_TYPE_NONE;
75*1b8adde7SWilliam Kucharski }
76*1b8adde7SWilliam Kucharski
77*1b8adde7SWilliam Kucharski for (i = 0; i < len; i++)
78*1b8adde7SWilliam Kucharski {
79*1b8adde7SWilliam Kucharski if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
80*1b8adde7SWilliam Kucharski {
81*1b8adde7SWilliam Kucharski flags = ((struct multiboot_header *) (buffer + i))->flags;
82*1b8adde7SWilliam Kucharski if (flags & MULTIBOOT_UNSUPPORTED)
83*1b8adde7SWilliam Kucharski {
84*1b8adde7SWilliam Kucharski grub_close ();
85*1b8adde7SWilliam Kucharski errnum = ERR_BOOT_FEATURES;
86*1b8adde7SWilliam Kucharski return KERNEL_TYPE_NONE;
87*1b8adde7SWilliam Kucharski }
88*1b8adde7SWilliam Kucharski type = KERNEL_TYPE_MULTIBOOT;
89*1b8adde7SWilliam Kucharski str2 = "Multiboot";
90*1b8adde7SWilliam Kucharski break;
91*1b8adde7SWilliam Kucharski }
92*1b8adde7SWilliam Kucharski }
93*1b8adde7SWilliam Kucharski
94*1b8adde7SWilliam Kucharski /* Use BUFFER as a linux kernel header, if the image is Linux zImage
95*1b8adde7SWilliam Kucharski or bzImage. */
96*1b8adde7SWilliam Kucharski lh = (struct linux_kernel_header *) buffer;
97*1b8adde7SWilliam Kucharski
98*1b8adde7SWilliam Kucharski /* ELF loading supported if multiboot, FreeBSD and NetBSD. */
99*1b8adde7SWilliam Kucharski if ((type == KERNEL_TYPE_MULTIBOOT
100*1b8adde7SWilliam Kucharski || pu.elf->e_ident[EI_OSABI] == ELFOSABI_FREEBSD
101*1b8adde7SWilliam Kucharski || grub_strcmp (pu.elf->e_ident + EI_BRAND, "FreeBSD") == 0
102*1b8adde7SWilliam Kucharski || suggested_type == KERNEL_TYPE_NETBSD)
103*1b8adde7SWilliam Kucharski && len > sizeof (Elf32_Ehdr)
104*1b8adde7SWilliam Kucharski && BOOTABLE_I386_ELF ((*((Elf32_Ehdr *) buffer))))
105*1b8adde7SWilliam Kucharski {
106*1b8adde7SWilliam Kucharski if (type == KERNEL_TYPE_MULTIBOOT)
107*1b8adde7SWilliam Kucharski entry_addr = (entry_func) pu.elf->e_entry;
108*1b8adde7SWilliam Kucharski else
109*1b8adde7SWilliam Kucharski entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
110*1b8adde7SWilliam Kucharski
111*1b8adde7SWilliam Kucharski if (entry_addr < (entry_func) 0x100000)
112*1b8adde7SWilliam Kucharski errnum = ERR_BELOW_1MB;
113*1b8adde7SWilliam Kucharski
114*1b8adde7SWilliam Kucharski /* don't want to deal with ELF program header at some random
115*1b8adde7SWilliam Kucharski place in the file -- this generally won't happen */
116*1b8adde7SWilliam Kucharski if (pu.elf->e_phoff == 0 || pu.elf->e_phnum == 0
117*1b8adde7SWilliam Kucharski || ((pu.elf->e_phoff + (pu.elf->e_phentsize * pu.elf->e_phnum))
118*1b8adde7SWilliam Kucharski >= len))
119*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
120*1b8adde7SWilliam Kucharski str = "elf";
121*1b8adde7SWilliam Kucharski
122*1b8adde7SWilliam Kucharski if (type == KERNEL_TYPE_NONE)
123*1b8adde7SWilliam Kucharski {
124*1b8adde7SWilliam Kucharski /* At the moment, there is no way to identify a NetBSD ELF
125*1b8adde7SWilliam Kucharski kernel, so rely on the suggested type by the user. */
126*1b8adde7SWilliam Kucharski if (suggested_type == KERNEL_TYPE_NETBSD)
127*1b8adde7SWilliam Kucharski {
128*1b8adde7SWilliam Kucharski str2 = "NetBSD";
129*1b8adde7SWilliam Kucharski type = suggested_type;
130*1b8adde7SWilliam Kucharski }
131*1b8adde7SWilliam Kucharski else
132*1b8adde7SWilliam Kucharski {
133*1b8adde7SWilliam Kucharski str2 = "FreeBSD";
134*1b8adde7SWilliam Kucharski type = KERNEL_TYPE_FREEBSD;
135*1b8adde7SWilliam Kucharski }
136*1b8adde7SWilliam Kucharski }
137*1b8adde7SWilliam Kucharski }
138*1b8adde7SWilliam Kucharski else if (flags & MULTIBOOT_AOUT_KLUDGE)
139*1b8adde7SWilliam Kucharski {
140*1b8adde7SWilliam Kucharski pu.mb = (struct multiboot_header *) (buffer + i);
141*1b8adde7SWilliam Kucharski entry_addr = (entry_func) pu.mb->entry_addr;
142*1b8adde7SWilliam Kucharski cur_addr = pu.mb->load_addr;
143*1b8adde7SWilliam Kucharski /* first offset into file */
144*1b8adde7SWilliam Kucharski grub_seek (i - (pu.mb->header_addr - cur_addr));
145*1b8adde7SWilliam Kucharski
146*1b8adde7SWilliam Kucharski /* If the load end address is zero, load the whole contents. */
147*1b8adde7SWilliam Kucharski if (! pu.mb->load_end_addr)
148*1b8adde7SWilliam Kucharski pu.mb->load_end_addr = cur_addr + filemax;
149*1b8adde7SWilliam Kucharski
150*1b8adde7SWilliam Kucharski text_len = pu.mb->load_end_addr - cur_addr;
151*1b8adde7SWilliam Kucharski data_len = 0;
152*1b8adde7SWilliam Kucharski
153*1b8adde7SWilliam Kucharski /* If the bss end address is zero, assume that there is no bss area. */
154*1b8adde7SWilliam Kucharski if (! pu.mb->bss_end_addr)
155*1b8adde7SWilliam Kucharski pu.mb->bss_end_addr = pu.mb->load_end_addr;
156*1b8adde7SWilliam Kucharski
157*1b8adde7SWilliam Kucharski bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
158*1b8adde7SWilliam Kucharski
159*1b8adde7SWilliam Kucharski if (pu.mb->header_addr < pu.mb->load_addr
160*1b8adde7SWilliam Kucharski || pu.mb->load_end_addr <= pu.mb->load_addr
161*1b8adde7SWilliam Kucharski || pu.mb->bss_end_addr < pu.mb->load_end_addr
162*1b8adde7SWilliam Kucharski || (pu.mb->header_addr - pu.mb->load_addr) > i)
163*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
164*1b8adde7SWilliam Kucharski
165*1b8adde7SWilliam Kucharski if (cur_addr < 0x100000)
166*1b8adde7SWilliam Kucharski errnum = ERR_BELOW_1MB;
167*1b8adde7SWilliam Kucharski
168*1b8adde7SWilliam Kucharski pu.aout = (struct exec *) buffer;
169*1b8adde7SWilliam Kucharski exec_type = 2;
170*1b8adde7SWilliam Kucharski str = "kludge";
171*1b8adde7SWilliam Kucharski }
172*1b8adde7SWilliam Kucharski else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
173*1b8adde7SWilliam Kucharski {
174*1b8adde7SWilliam Kucharski entry_addr = (entry_func) pu.aout->a_entry;
175*1b8adde7SWilliam Kucharski
176*1b8adde7SWilliam Kucharski if (type == KERNEL_TYPE_NONE)
177*1b8adde7SWilliam Kucharski {
178*1b8adde7SWilliam Kucharski /*
179*1b8adde7SWilliam Kucharski * If it doesn't have a Multiboot header, then presume
180*1b8adde7SWilliam Kucharski * it is either a FreeBSD or NetBSD executable. If so,
181*1b8adde7SWilliam Kucharski * then use a magic number of normal ordering, ZMAGIC to
182*1b8adde7SWilliam Kucharski * determine if it is FreeBSD.
183*1b8adde7SWilliam Kucharski *
184*1b8adde7SWilliam Kucharski * This is all because freebsd and netbsd seem to require
185*1b8adde7SWilliam Kucharski * masking out some address bits... differently for each
186*1b8adde7SWilliam Kucharski * one... plus of course we need to know which booting
187*1b8adde7SWilliam Kucharski * method to use.
188*1b8adde7SWilliam Kucharski */
189*1b8adde7SWilliam Kucharski entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
190*1b8adde7SWilliam Kucharski
191*1b8adde7SWilliam Kucharski if (buffer[0] == 0xb && buffer[1] == 1)
192*1b8adde7SWilliam Kucharski {
193*1b8adde7SWilliam Kucharski type = KERNEL_TYPE_FREEBSD;
194*1b8adde7SWilliam Kucharski cur_addr = (int) entry_addr;
195*1b8adde7SWilliam Kucharski str2 = "FreeBSD";
196*1b8adde7SWilliam Kucharski }
197*1b8adde7SWilliam Kucharski else
198*1b8adde7SWilliam Kucharski {
199*1b8adde7SWilliam Kucharski type = KERNEL_TYPE_NETBSD;
200*1b8adde7SWilliam Kucharski cur_addr = (int) entry_addr & 0xF00000;
201*1b8adde7SWilliam Kucharski if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
202*1b8adde7SWilliam Kucharski align_4k = 0;
203*1b8adde7SWilliam Kucharski str2 = "NetBSD";
204*1b8adde7SWilliam Kucharski }
205*1b8adde7SWilliam Kucharski }
206*1b8adde7SWilliam Kucharski
207*1b8adde7SWilliam Kucharski /* first offset into file */
208*1b8adde7SWilliam Kucharski grub_seek (N_TXTOFF (*(pu.aout)));
209*1b8adde7SWilliam Kucharski text_len = pu.aout->a_text;
210*1b8adde7SWilliam Kucharski data_len = pu.aout->a_data;
211*1b8adde7SWilliam Kucharski bss_len = pu.aout->a_bss;
212*1b8adde7SWilliam Kucharski
213*1b8adde7SWilliam Kucharski if (cur_addr < 0x100000)
214*1b8adde7SWilliam Kucharski errnum = ERR_BELOW_1MB;
215*1b8adde7SWilliam Kucharski
216*1b8adde7SWilliam Kucharski exec_type = 1;
217*1b8adde7SWilliam Kucharski str = "a.out";
218*1b8adde7SWilliam Kucharski }
219*1b8adde7SWilliam Kucharski else if (lh->boot_flag == BOOTSEC_SIGNATURE
220*1b8adde7SWilliam Kucharski && lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
221*1b8adde7SWilliam Kucharski {
222*1b8adde7SWilliam Kucharski int big_linux = 0;
223*1b8adde7SWilliam Kucharski int setup_sects = lh->setup_sects;
224*1b8adde7SWilliam Kucharski
225*1b8adde7SWilliam Kucharski if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
226*1b8adde7SWilliam Kucharski {
227*1b8adde7SWilliam Kucharski big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
228*1b8adde7SWilliam Kucharski lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
229*1b8adde7SWilliam Kucharski
230*1b8adde7SWilliam Kucharski /* Put the real mode part at as a high location as possible. */
231*1b8adde7SWilliam Kucharski linux_data_real_addr
232*1b8adde7SWilliam Kucharski = (char *) ((mbi.mem_lower << 10) - LINUX_SETUP_MOVE_SIZE);
233*1b8adde7SWilliam Kucharski /* But it must not exceed the traditional area. */
234*1b8adde7SWilliam Kucharski if (linux_data_real_addr > (char *) LINUX_OLD_REAL_MODE_ADDR)
235*1b8adde7SWilliam Kucharski linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
236*1b8adde7SWilliam Kucharski
237*1b8adde7SWilliam Kucharski if (lh->version >= 0x0201)
238*1b8adde7SWilliam Kucharski {
239*1b8adde7SWilliam Kucharski lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
240*1b8adde7SWilliam Kucharski lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
241*1b8adde7SWilliam Kucharski }
242*1b8adde7SWilliam Kucharski
243*1b8adde7SWilliam Kucharski if (lh->version >= 0x0202)
244*1b8adde7SWilliam Kucharski lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
245*1b8adde7SWilliam Kucharski else
246*1b8adde7SWilliam Kucharski {
247*1b8adde7SWilliam Kucharski lh->cl_magic = LINUX_CL_MAGIC;
248*1b8adde7SWilliam Kucharski lh->cl_offset = LINUX_CL_OFFSET;
249*1b8adde7SWilliam Kucharski lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
250*1b8adde7SWilliam Kucharski }
251*1b8adde7SWilliam Kucharski }
252*1b8adde7SWilliam Kucharski else
253*1b8adde7SWilliam Kucharski {
254*1b8adde7SWilliam Kucharski /* Your kernel is quite old... */
255*1b8adde7SWilliam Kucharski lh->cl_magic = LINUX_CL_MAGIC;
256*1b8adde7SWilliam Kucharski lh->cl_offset = LINUX_CL_OFFSET;
257*1b8adde7SWilliam Kucharski
258*1b8adde7SWilliam Kucharski setup_sects = LINUX_DEFAULT_SETUP_SECTS;
259*1b8adde7SWilliam Kucharski
260*1b8adde7SWilliam Kucharski linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
261*1b8adde7SWilliam Kucharski }
262*1b8adde7SWilliam Kucharski
263*1b8adde7SWilliam Kucharski /* If SETUP_SECTS is not set, set it to the default (4). */
264*1b8adde7SWilliam Kucharski if (! setup_sects)
265*1b8adde7SWilliam Kucharski setup_sects = LINUX_DEFAULT_SETUP_SECTS;
266*1b8adde7SWilliam Kucharski
267*1b8adde7SWilliam Kucharski data_len = setup_sects << 9;
268*1b8adde7SWilliam Kucharski text_len = filemax - data_len - SECTOR_SIZE;
269*1b8adde7SWilliam Kucharski
270*1b8adde7SWilliam Kucharski linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
271*1b8adde7SWilliam Kucharski
272*1b8adde7SWilliam Kucharski if (! big_linux
273*1b8adde7SWilliam Kucharski && text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
274*1b8adde7SWilliam Kucharski {
275*1b8adde7SWilliam Kucharski grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
276*1b8adde7SWilliam Kucharski errnum = ERR_WONT_FIT;
277*1b8adde7SWilliam Kucharski }
278*1b8adde7SWilliam Kucharski else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
279*1b8adde7SWilliam Kucharski > RAW_ADDR ((char *) (mbi.mem_lower << 10)))
280*1b8adde7SWilliam Kucharski errnum = ERR_WONT_FIT;
281*1b8adde7SWilliam Kucharski else
282*1b8adde7SWilliam Kucharski {
283*1b8adde7SWilliam Kucharski grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n",
284*1b8adde7SWilliam Kucharski (big_linux ? "bzImage" : "zImage"), data_len, text_len);
285*1b8adde7SWilliam Kucharski
286*1b8adde7SWilliam Kucharski /* Video mode selection support. What a mess! */
287*1b8adde7SWilliam Kucharski /* NOTE: Even the word "mess" is not still enough to
288*1b8adde7SWilliam Kucharski represent how wrong and bad the Linux video support is,
289*1b8adde7SWilliam Kucharski but I don't want to hear complaints from Linux fanatics
290*1b8adde7SWilliam Kucharski any more. -okuji */
291*1b8adde7SWilliam Kucharski {
292*1b8adde7SWilliam Kucharski char *vga;
293*1b8adde7SWilliam Kucharski
294*1b8adde7SWilliam Kucharski /* Find the substring "vga=". */
295*1b8adde7SWilliam Kucharski vga = grub_strstr (arg, "vga=");
296*1b8adde7SWilliam Kucharski if (vga)
297*1b8adde7SWilliam Kucharski {
298*1b8adde7SWilliam Kucharski char *value = vga + 4;
299*1b8adde7SWilliam Kucharski int vid_mode;
300*1b8adde7SWilliam Kucharski
301*1b8adde7SWilliam Kucharski /* Handle special strings. */
302*1b8adde7SWilliam Kucharski if (substring ("normal", value) < 1)
303*1b8adde7SWilliam Kucharski vid_mode = LINUX_VID_MODE_NORMAL;
304*1b8adde7SWilliam Kucharski else if (substring ("ext", value) < 1)
305*1b8adde7SWilliam Kucharski vid_mode = LINUX_VID_MODE_EXTENDED;
306*1b8adde7SWilliam Kucharski else if (substring ("ask", value) < 1)
307*1b8adde7SWilliam Kucharski vid_mode = LINUX_VID_MODE_ASK;
308*1b8adde7SWilliam Kucharski else if (safe_parse_maxint (&value, &vid_mode))
309*1b8adde7SWilliam Kucharski ;
310*1b8adde7SWilliam Kucharski else
311*1b8adde7SWilliam Kucharski {
312*1b8adde7SWilliam Kucharski /* ERRNUM is already set inside the function
313*1b8adde7SWilliam Kucharski safe_parse_maxint. */
314*1b8adde7SWilliam Kucharski grub_close ();
315*1b8adde7SWilliam Kucharski return KERNEL_TYPE_NONE;
316*1b8adde7SWilliam Kucharski }
317*1b8adde7SWilliam Kucharski
318*1b8adde7SWilliam Kucharski lh->vid_mode = vid_mode;
319*1b8adde7SWilliam Kucharski }
320*1b8adde7SWilliam Kucharski }
321*1b8adde7SWilliam Kucharski
322*1b8adde7SWilliam Kucharski /* Check the mem= option to limit memory used for initrd. */
323*1b8adde7SWilliam Kucharski {
324*1b8adde7SWilliam Kucharski char *mem;
325*1b8adde7SWilliam Kucharski
326*1b8adde7SWilliam Kucharski mem = grub_strstr (arg, "mem=");
327*1b8adde7SWilliam Kucharski if (mem)
328*1b8adde7SWilliam Kucharski {
329*1b8adde7SWilliam Kucharski char *value = mem + 4;
330*1b8adde7SWilliam Kucharski
331*1b8adde7SWilliam Kucharski safe_parse_maxint (&value, &linux_mem_size);
332*1b8adde7SWilliam Kucharski switch (errnum)
333*1b8adde7SWilliam Kucharski {
334*1b8adde7SWilliam Kucharski case ERR_NUMBER_OVERFLOW:
335*1b8adde7SWilliam Kucharski /* If an overflow occurs, use the maximum address for
336*1b8adde7SWilliam Kucharski initrd instead. This is good, because MAXINT is
337*1b8adde7SWilliam Kucharski greater than LINUX_INITRD_MAX_ADDRESS. */
338*1b8adde7SWilliam Kucharski linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
339*1b8adde7SWilliam Kucharski errnum = ERR_NONE;
340*1b8adde7SWilliam Kucharski break;
341*1b8adde7SWilliam Kucharski
342*1b8adde7SWilliam Kucharski case ERR_NONE:
343*1b8adde7SWilliam Kucharski {
344*1b8adde7SWilliam Kucharski int shift = 0;
345*1b8adde7SWilliam Kucharski
346*1b8adde7SWilliam Kucharski switch (grub_tolower (*value))
347*1b8adde7SWilliam Kucharski {
348*1b8adde7SWilliam Kucharski case 'g':
349*1b8adde7SWilliam Kucharski shift += 10;
350*1b8adde7SWilliam Kucharski case 'm':
351*1b8adde7SWilliam Kucharski shift += 10;
352*1b8adde7SWilliam Kucharski case 'k':
353*1b8adde7SWilliam Kucharski shift += 10;
354*1b8adde7SWilliam Kucharski default:
355*1b8adde7SWilliam Kucharski break;
356*1b8adde7SWilliam Kucharski }
357*1b8adde7SWilliam Kucharski
358*1b8adde7SWilliam Kucharski /* Check an overflow. */
359*1b8adde7SWilliam Kucharski if (linux_mem_size > (MAXINT >> shift))
360*1b8adde7SWilliam Kucharski linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
361*1b8adde7SWilliam Kucharski else
362*1b8adde7SWilliam Kucharski linux_mem_size <<= shift;
363*1b8adde7SWilliam Kucharski }
364*1b8adde7SWilliam Kucharski break;
365*1b8adde7SWilliam Kucharski
366*1b8adde7SWilliam Kucharski default:
367*1b8adde7SWilliam Kucharski linux_mem_size = 0;
368*1b8adde7SWilliam Kucharski errnum = ERR_NONE;
369*1b8adde7SWilliam Kucharski break;
370*1b8adde7SWilliam Kucharski }
371*1b8adde7SWilliam Kucharski }
372*1b8adde7SWilliam Kucharski else
373*1b8adde7SWilliam Kucharski linux_mem_size = 0;
374*1b8adde7SWilliam Kucharski }
375*1b8adde7SWilliam Kucharski
376*1b8adde7SWilliam Kucharski /* It is possible that DATA_LEN + SECTOR_SIZE is greater than
377*1b8adde7SWilliam Kucharski MULTIBOOT_SEARCH, so the data may have been read partially. */
378*1b8adde7SWilliam Kucharski if (data_len + SECTOR_SIZE <= MULTIBOOT_SEARCH)
379*1b8adde7SWilliam Kucharski grub_memmove (linux_data_tmp_addr, buffer,
380*1b8adde7SWilliam Kucharski data_len + SECTOR_SIZE);
381*1b8adde7SWilliam Kucharski else
382*1b8adde7SWilliam Kucharski {
383*1b8adde7SWilliam Kucharski grub_memmove (linux_data_tmp_addr, buffer, MULTIBOOT_SEARCH);
384*1b8adde7SWilliam Kucharski grub_read (linux_data_tmp_addr + MULTIBOOT_SEARCH,
385*1b8adde7SWilliam Kucharski data_len + SECTOR_SIZE - MULTIBOOT_SEARCH);
386*1b8adde7SWilliam Kucharski }
387*1b8adde7SWilliam Kucharski
388*1b8adde7SWilliam Kucharski if (lh->header != LINUX_MAGIC_SIGNATURE ||
389*1b8adde7SWilliam Kucharski lh->version < 0x0200)
390*1b8adde7SWilliam Kucharski /* Clear the heap space. */
391*1b8adde7SWilliam Kucharski grub_memset (linux_data_tmp_addr + ((setup_sects + 1) << 9),
392*1b8adde7SWilliam Kucharski 0,
393*1b8adde7SWilliam Kucharski (64 - setup_sects - 1) << 9);
394*1b8adde7SWilliam Kucharski
395*1b8adde7SWilliam Kucharski /* Copy command-line plus memory hack to staging area.
396*1b8adde7SWilliam Kucharski NOTE: Linux has a bug that it doesn't handle multiple spaces
397*1b8adde7SWilliam Kucharski between two options and a space after a "mem=" option isn't
398*1b8adde7SWilliam Kucharski removed correctly so the arguments to init could be like
399*1b8adde7SWilliam Kucharski {"init", "", "", NULL}. This affects some not-very-clever
400*1b8adde7SWilliam Kucharski shells. Thus, the code below does a trick to avoid the bug.
401*1b8adde7SWilliam Kucharski That is, copy "mem=XXX" to the end of the command-line, and
402*1b8adde7SWilliam Kucharski avoid to copy spaces unnecessarily. Hell. */
403*1b8adde7SWilliam Kucharski {
404*1b8adde7SWilliam Kucharski char *src = skip_to (0, arg);
405*1b8adde7SWilliam Kucharski char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
406*1b8adde7SWilliam Kucharski
407*1b8adde7SWilliam Kucharski while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
408*1b8adde7SWilliam Kucharski *(dest++) = *(src++);
409*1b8adde7SWilliam Kucharski
410*1b8adde7SWilliam Kucharski /* Old Linux kernels have problems determining the amount of
411*1b8adde7SWilliam Kucharski the available memory. To work around this problem, we add
412*1b8adde7SWilliam Kucharski the "mem" option to the kernel command line. This has its
413*1b8adde7SWilliam Kucharski own drawbacks because newer kernels can determine the
414*1b8adde7SWilliam Kucharski memory map more accurately. Boot protocol 2.03, which
415*1b8adde7SWilliam Kucharski appeared in Linux 2.4.18, provides a pointer to the kernel
416*1b8adde7SWilliam Kucharski version string, so we could check it. But since kernel
417*1b8adde7SWilliam Kucharski 2.4.18 and newer are known to detect memory reliably, boot
418*1b8adde7SWilliam Kucharski protocol 2.03 already implies that the kernel is new
419*1b8adde7SWilliam Kucharski enough. The "mem" option is added if neither of the
420*1b8adde7SWilliam Kucharski following conditions is met:
421*1b8adde7SWilliam Kucharski 1) The "mem" option is already present.
422*1b8adde7SWilliam Kucharski 2) The "kernel" command is used with "--no-mem-option".
423*1b8adde7SWilliam Kucharski 3) GNU GRUB is configured not to pass the "mem" option.
424*1b8adde7SWilliam Kucharski 4) The kernel supports boot protocol 2.03 or newer. */
425*1b8adde7SWilliam Kucharski if (! grub_strstr (arg, "mem=")
426*1b8adde7SWilliam Kucharski && ! (load_flags & KERNEL_LOAD_NO_MEM_OPTION)
427*1b8adde7SWilliam Kucharski && lh->version < 0x0203 /* kernel version < 2.4.18 */
428*1b8adde7SWilliam Kucharski && dest + 15 < linux_data_tmp_addr + LINUX_CL_END_OFFSET)
429*1b8adde7SWilliam Kucharski {
430*1b8adde7SWilliam Kucharski *dest++ = ' ';
431*1b8adde7SWilliam Kucharski *dest++ = 'm';
432*1b8adde7SWilliam Kucharski *dest++ = 'e';
433*1b8adde7SWilliam Kucharski *dest++ = 'm';
434*1b8adde7SWilliam Kucharski *dest++ = '=';
435*1b8adde7SWilliam Kucharski
436*1b8adde7SWilliam Kucharski dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
437*1b8adde7SWilliam Kucharski *dest++ = 'K';
438*1b8adde7SWilliam Kucharski }
439*1b8adde7SWilliam Kucharski
440*1b8adde7SWilliam Kucharski *dest = 0;
441*1b8adde7SWilliam Kucharski }
442*1b8adde7SWilliam Kucharski
443*1b8adde7SWilliam Kucharski /* offset into file */
444*1b8adde7SWilliam Kucharski grub_seek (data_len + SECTOR_SIZE);
445*1b8adde7SWilliam Kucharski
446*1b8adde7SWilliam Kucharski cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
447*1b8adde7SWilliam Kucharski grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
448*1b8adde7SWilliam Kucharski
449*1b8adde7SWilliam Kucharski if (errnum == ERR_NONE)
450*1b8adde7SWilliam Kucharski {
451*1b8adde7SWilliam Kucharski grub_close ();
452*1b8adde7SWilliam Kucharski
453*1b8adde7SWilliam Kucharski /* Sanity check. */
454*1b8adde7SWilliam Kucharski if (suggested_type != KERNEL_TYPE_NONE
455*1b8adde7SWilliam Kucharski && ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX)
456*1b8adde7SWilliam Kucharski || (! big_linux && suggested_type != KERNEL_TYPE_LINUX)))
457*1b8adde7SWilliam Kucharski {
458*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
459*1b8adde7SWilliam Kucharski return KERNEL_TYPE_NONE;
460*1b8adde7SWilliam Kucharski }
461*1b8adde7SWilliam Kucharski
462*1b8adde7SWilliam Kucharski /* Ugly hack. */
463*1b8adde7SWilliam Kucharski linux_text_len = text_len;
464*1b8adde7SWilliam Kucharski
465*1b8adde7SWilliam Kucharski return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
466*1b8adde7SWilliam Kucharski }
467*1b8adde7SWilliam Kucharski }
468*1b8adde7SWilliam Kucharski }
469*1b8adde7SWilliam Kucharski else /* no recognizable format */
470*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
471*1b8adde7SWilliam Kucharski
472*1b8adde7SWilliam Kucharski /* return if error */
473*1b8adde7SWilliam Kucharski if (errnum)
474*1b8adde7SWilliam Kucharski {
475*1b8adde7SWilliam Kucharski grub_close ();
476*1b8adde7SWilliam Kucharski return KERNEL_TYPE_NONE;
477*1b8adde7SWilliam Kucharski }
478*1b8adde7SWilliam Kucharski
479*1b8adde7SWilliam Kucharski /* fill the multiboot info structure */
480*1b8adde7SWilliam Kucharski mbi.cmdline = (int) arg;
481*1b8adde7SWilliam Kucharski mbi.mods_count = 0;
482*1b8adde7SWilliam Kucharski mbi.mods_addr = 0;
483*1b8adde7SWilliam Kucharski mbi.boot_device = (current_drive << 24) | current_partition;
484*1b8adde7SWilliam Kucharski mbi.flags &= ~(MB_INFO_MODS | MB_INFO_AOUT_SYMS | MB_INFO_ELF_SHDR);
485*1b8adde7SWilliam Kucharski mbi.syms.a.tabsize = 0;
486*1b8adde7SWilliam Kucharski mbi.syms.a.strsize = 0;
487*1b8adde7SWilliam Kucharski mbi.syms.a.addr = 0;
488*1b8adde7SWilliam Kucharski mbi.syms.a.pad = 0;
489*1b8adde7SWilliam Kucharski
490*1b8adde7SWilliam Kucharski printf (" [%s-%s", str2, str);
491*1b8adde7SWilliam Kucharski
492*1b8adde7SWilliam Kucharski str = "";
493*1b8adde7SWilliam Kucharski
494*1b8adde7SWilliam Kucharski if (exec_type) /* can be loaded like a.out */
495*1b8adde7SWilliam Kucharski {
496*1b8adde7SWilliam Kucharski if (flags & MULTIBOOT_AOUT_KLUDGE)
497*1b8adde7SWilliam Kucharski str = "-and-data";
498*1b8adde7SWilliam Kucharski
499*1b8adde7SWilliam Kucharski printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
500*1b8adde7SWilliam Kucharski
501*1b8adde7SWilliam Kucharski /* read text, then read data */
502*1b8adde7SWilliam Kucharski if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
503*1b8adde7SWilliam Kucharski {
504*1b8adde7SWilliam Kucharski cur_addr += text_len;
505*1b8adde7SWilliam Kucharski
506*1b8adde7SWilliam Kucharski if (!(flags & MULTIBOOT_AOUT_KLUDGE))
507*1b8adde7SWilliam Kucharski {
508*1b8adde7SWilliam Kucharski /* we have to align to a 4K boundary */
509*1b8adde7SWilliam Kucharski if (align_4k)
510*1b8adde7SWilliam Kucharski cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
511*1b8adde7SWilliam Kucharski else
512*1b8adde7SWilliam Kucharski printf (", C");
513*1b8adde7SWilliam Kucharski
514*1b8adde7SWilliam Kucharski printf (", data=0x%x", data_len);
515*1b8adde7SWilliam Kucharski
516*1b8adde7SWilliam Kucharski if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
517*1b8adde7SWilliam Kucharski != data_len)
518*1b8adde7SWilliam Kucharski && !errnum)
519*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
520*1b8adde7SWilliam Kucharski cur_addr += data_len;
521*1b8adde7SWilliam Kucharski }
522*1b8adde7SWilliam Kucharski
523*1b8adde7SWilliam Kucharski if (!errnum)
524*1b8adde7SWilliam Kucharski {
525*1b8adde7SWilliam Kucharski memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
526*1b8adde7SWilliam Kucharski cur_addr += bss_len;
527*1b8adde7SWilliam Kucharski
528*1b8adde7SWilliam Kucharski printf (", bss=0x%x", bss_len);
529*1b8adde7SWilliam Kucharski }
530*1b8adde7SWilliam Kucharski }
531*1b8adde7SWilliam Kucharski else if (!errnum)
532*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
533*1b8adde7SWilliam Kucharski
534*1b8adde7SWilliam Kucharski if (!errnum && pu.aout->a_syms
535*1b8adde7SWilliam Kucharski && pu.aout->a_syms < (filemax - filepos))
536*1b8adde7SWilliam Kucharski {
537*1b8adde7SWilliam Kucharski int symtab_err, orig_addr = cur_addr;
538*1b8adde7SWilliam Kucharski
539*1b8adde7SWilliam Kucharski /* we should align to a 4K boundary here for good measure */
540*1b8adde7SWilliam Kucharski if (align_4k)
541*1b8adde7SWilliam Kucharski cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
542*1b8adde7SWilliam Kucharski
543*1b8adde7SWilliam Kucharski mbi.syms.a.addr = cur_addr;
544*1b8adde7SWilliam Kucharski
545*1b8adde7SWilliam Kucharski *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
546*1b8adde7SWilliam Kucharski cur_addr += sizeof (int);
547*1b8adde7SWilliam Kucharski
548*1b8adde7SWilliam Kucharski printf (", symtab=0x%x", pu.aout->a_syms);
549*1b8adde7SWilliam Kucharski
550*1b8adde7SWilliam Kucharski if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
551*1b8adde7SWilliam Kucharski == pu.aout->a_syms)
552*1b8adde7SWilliam Kucharski {
553*1b8adde7SWilliam Kucharski cur_addr += pu.aout->a_syms;
554*1b8adde7SWilliam Kucharski mbi.syms.a.tabsize = pu.aout->a_syms;
555*1b8adde7SWilliam Kucharski
556*1b8adde7SWilliam Kucharski if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
557*1b8adde7SWilliam Kucharski {
558*1b8adde7SWilliam Kucharski *((int *) RAW_ADDR (cur_addr)) = i;
559*1b8adde7SWilliam Kucharski cur_addr += sizeof (int);
560*1b8adde7SWilliam Kucharski
561*1b8adde7SWilliam Kucharski mbi.syms.a.strsize = i;
562*1b8adde7SWilliam Kucharski
563*1b8adde7SWilliam Kucharski i -= sizeof (int);
564*1b8adde7SWilliam Kucharski
565*1b8adde7SWilliam Kucharski printf (", strtab=0x%x", i);
566*1b8adde7SWilliam Kucharski
567*1b8adde7SWilliam Kucharski symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
568*1b8adde7SWilliam Kucharski != i);
569*1b8adde7SWilliam Kucharski cur_addr += i;
570*1b8adde7SWilliam Kucharski }
571*1b8adde7SWilliam Kucharski else
572*1b8adde7SWilliam Kucharski symtab_err = 1;
573*1b8adde7SWilliam Kucharski }
574*1b8adde7SWilliam Kucharski else
575*1b8adde7SWilliam Kucharski symtab_err = 1;
576*1b8adde7SWilliam Kucharski
577*1b8adde7SWilliam Kucharski if (symtab_err)
578*1b8adde7SWilliam Kucharski {
579*1b8adde7SWilliam Kucharski printf ("(bad)");
580*1b8adde7SWilliam Kucharski cur_addr = orig_addr;
581*1b8adde7SWilliam Kucharski mbi.syms.a.tabsize = 0;
582*1b8adde7SWilliam Kucharski mbi.syms.a.strsize = 0;
583*1b8adde7SWilliam Kucharski mbi.syms.a.addr = 0;
584*1b8adde7SWilliam Kucharski }
585*1b8adde7SWilliam Kucharski else
586*1b8adde7SWilliam Kucharski mbi.flags |= MB_INFO_AOUT_SYMS;
587*1b8adde7SWilliam Kucharski }
588*1b8adde7SWilliam Kucharski }
589*1b8adde7SWilliam Kucharski else
590*1b8adde7SWilliam Kucharski /* ELF executable */
591*1b8adde7SWilliam Kucharski {
592*1b8adde7SWilliam Kucharski unsigned loaded = 0, memaddr, memsiz, filesiz;
593*1b8adde7SWilliam Kucharski Elf32_Phdr *phdr;
594*1b8adde7SWilliam Kucharski
595*1b8adde7SWilliam Kucharski /* reset this to zero for now */
596*1b8adde7SWilliam Kucharski cur_addr = 0;
597*1b8adde7SWilliam Kucharski
598*1b8adde7SWilliam Kucharski /* scan for program segments */
599*1b8adde7SWilliam Kucharski for (i = 0; i < pu.elf->e_phnum; i++)
600*1b8adde7SWilliam Kucharski {
601*1b8adde7SWilliam Kucharski phdr = (Elf32_Phdr *)
602*1b8adde7SWilliam Kucharski (pu.elf->e_phoff + ((int) buffer)
603*1b8adde7SWilliam Kucharski + (pu.elf->e_phentsize * i));
604*1b8adde7SWilliam Kucharski if (phdr->p_type == PT_LOAD)
605*1b8adde7SWilliam Kucharski {
606*1b8adde7SWilliam Kucharski /* offset into file */
607*1b8adde7SWilliam Kucharski grub_seek (phdr->p_offset);
608*1b8adde7SWilliam Kucharski filesiz = phdr->p_filesz;
609*1b8adde7SWilliam Kucharski
610*1b8adde7SWilliam Kucharski if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
611*1b8adde7SWilliam Kucharski memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
612*1b8adde7SWilliam Kucharski else
613*1b8adde7SWilliam Kucharski memaddr = RAW_ADDR (phdr->p_paddr);
614*1b8adde7SWilliam Kucharski
615*1b8adde7SWilliam Kucharski memsiz = phdr->p_memsz;
616*1b8adde7SWilliam Kucharski if (memaddr < RAW_ADDR (0x100000))
617*1b8adde7SWilliam Kucharski errnum = ERR_BELOW_1MB;
618*1b8adde7SWilliam Kucharski
619*1b8adde7SWilliam Kucharski /* If the memory range contains the entry address, get the
620*1b8adde7SWilliam Kucharski physical address here. */
621*1b8adde7SWilliam Kucharski if (type == KERNEL_TYPE_MULTIBOOT
622*1b8adde7SWilliam Kucharski && (unsigned) entry_addr >= phdr->p_vaddr
623*1b8adde7SWilliam Kucharski && (unsigned) entry_addr < phdr->p_vaddr + memsiz)
624*1b8adde7SWilliam Kucharski real_entry_addr = (entry_func) ((unsigned) entry_addr
625*1b8adde7SWilliam Kucharski + memaddr - phdr->p_vaddr);
626*1b8adde7SWilliam Kucharski
627*1b8adde7SWilliam Kucharski /* make sure we only load what we're supposed to! */
628*1b8adde7SWilliam Kucharski if (filesiz > memsiz)
629*1b8adde7SWilliam Kucharski filesiz = memsiz;
630*1b8adde7SWilliam Kucharski /* mark memory as used */
631*1b8adde7SWilliam Kucharski if (cur_addr < memaddr + memsiz)
632*1b8adde7SWilliam Kucharski cur_addr = memaddr + memsiz;
633*1b8adde7SWilliam Kucharski printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
634*1b8adde7SWilliam Kucharski memsiz - filesiz);
635*1b8adde7SWilliam Kucharski /* increment number of segments */
636*1b8adde7SWilliam Kucharski loaded++;
637*1b8adde7SWilliam Kucharski
638*1b8adde7SWilliam Kucharski /* load the segment */
639*1b8adde7SWilliam Kucharski if (memcheck (memaddr, memsiz)
640*1b8adde7SWilliam Kucharski && grub_read ((char *) memaddr, filesiz) == filesiz)
641*1b8adde7SWilliam Kucharski {
642*1b8adde7SWilliam Kucharski if (memsiz > filesiz)
643*1b8adde7SWilliam Kucharski memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
644*1b8adde7SWilliam Kucharski }
645*1b8adde7SWilliam Kucharski else
646*1b8adde7SWilliam Kucharski break;
647*1b8adde7SWilliam Kucharski }
648*1b8adde7SWilliam Kucharski }
649*1b8adde7SWilliam Kucharski
650*1b8adde7SWilliam Kucharski if (! errnum)
651*1b8adde7SWilliam Kucharski {
652*1b8adde7SWilliam Kucharski if (! loaded)
653*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
654*1b8adde7SWilliam Kucharski else
655*1b8adde7SWilliam Kucharski {
656*1b8adde7SWilliam Kucharski /* Load ELF symbols. */
657*1b8adde7SWilliam Kucharski Elf32_Shdr *shdr = NULL;
658*1b8adde7SWilliam Kucharski int tab_size, sec_size;
659*1b8adde7SWilliam Kucharski int symtab_err = 0;
660*1b8adde7SWilliam Kucharski
661*1b8adde7SWilliam Kucharski mbi.syms.e.num = pu.elf->e_shnum;
662*1b8adde7SWilliam Kucharski mbi.syms.e.size = pu.elf->e_shentsize;
663*1b8adde7SWilliam Kucharski mbi.syms.e.shndx = pu.elf->e_shstrndx;
664*1b8adde7SWilliam Kucharski
665*1b8adde7SWilliam Kucharski /* We should align to a 4K boundary here for good measure. */
666*1b8adde7SWilliam Kucharski if (align_4k)
667*1b8adde7SWilliam Kucharski cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
668*1b8adde7SWilliam Kucharski
669*1b8adde7SWilliam Kucharski tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
670*1b8adde7SWilliam Kucharski
671*1b8adde7SWilliam Kucharski grub_seek (pu.elf->e_shoff);
672*1b8adde7SWilliam Kucharski /*
673*1b8adde7SWilliam Kucharski * Should not need to call RAW_ADDR; cur_addr is already
674*1b8adde7SWilliam Kucharski * adjusted to account for grub_scratch_mem.
675*1b8adde7SWilliam Kucharski * XXX Linux might calculate cur_addr differently.
676*1b8adde7SWilliam Kucharski */
677*1b8adde7SWilliam Kucharski if (grub_read ((char *) (cur_addr), tab_size)
678*1b8adde7SWilliam Kucharski == tab_size)
679*1b8adde7SWilliam Kucharski {
680*1b8adde7SWilliam Kucharski mbi.syms.e.addr = cur_addr;
681*1b8adde7SWilliam Kucharski shdr = (Elf32_Shdr *) mbi.syms.e.addr;
682*1b8adde7SWilliam Kucharski cur_addr += tab_size;
683*1b8adde7SWilliam Kucharski
684*1b8adde7SWilliam Kucharski printf (", shtab=0x%x", cur_addr);
685*1b8adde7SWilliam Kucharski
686*1b8adde7SWilliam Kucharski for (i = 0; i < mbi.syms.e.num; i++)
687*1b8adde7SWilliam Kucharski {
688*1b8adde7SWilliam Kucharski /* This section is a loaded section,
689*1b8adde7SWilliam Kucharski so we don't care. */
690*1b8adde7SWilliam Kucharski if (shdr[i].sh_addr != 0)
691*1b8adde7SWilliam Kucharski continue;
692*1b8adde7SWilliam Kucharski
693*1b8adde7SWilliam Kucharski /* This section is empty, so we don't care. */
694*1b8adde7SWilliam Kucharski if (shdr[i].sh_size == 0)
695*1b8adde7SWilliam Kucharski continue;
696*1b8adde7SWilliam Kucharski
697*1b8adde7SWilliam Kucharski /* Align the section to a sh_addralign bits boundary. */
698*1b8adde7SWilliam Kucharski cur_addr = ((cur_addr + shdr[i].sh_addralign) &
699*1b8adde7SWilliam Kucharski - (int) shdr[i].sh_addralign);
700*1b8adde7SWilliam Kucharski
701*1b8adde7SWilliam Kucharski grub_seek (shdr[i].sh_offset);
702*1b8adde7SWilliam Kucharski
703*1b8adde7SWilliam Kucharski sec_size = shdr[i].sh_size;
704*1b8adde7SWilliam Kucharski
705*1b8adde7SWilliam Kucharski /*
706*1b8adde7SWilliam Kucharski * Should not need to call RAW_ADDR; cur_addr is already
707*1b8adde7SWilliam Kucharski * adjusted to account for grub_scratch_mem.
708*1b8adde7SWilliam Kucharski * XXX Linux might calculate cur_addr differently.
709*1b8adde7SWilliam Kucharski */
710*1b8adde7SWilliam Kucharski if (! (memcheck (cur_addr, sec_size)
711*1b8adde7SWilliam Kucharski && (grub_read ((char *) (cur_addr),
712*1b8adde7SWilliam Kucharski sec_size)
713*1b8adde7SWilliam Kucharski == sec_size)))
714*1b8adde7SWilliam Kucharski {
715*1b8adde7SWilliam Kucharski symtab_err = 1;
716*1b8adde7SWilliam Kucharski break;
717*1b8adde7SWilliam Kucharski }
718*1b8adde7SWilliam Kucharski
719*1b8adde7SWilliam Kucharski shdr[i].sh_addr = cur_addr;
720*1b8adde7SWilliam Kucharski cur_addr += sec_size;
721*1b8adde7SWilliam Kucharski }
722*1b8adde7SWilliam Kucharski }
723*1b8adde7SWilliam Kucharski else
724*1b8adde7SWilliam Kucharski symtab_err = 1;
725*1b8adde7SWilliam Kucharski
726*1b8adde7SWilliam Kucharski if (mbi.syms.e.addr < RAW_ADDR(0x10000))
727*1b8adde7SWilliam Kucharski symtab_err = 1;
728*1b8adde7SWilliam Kucharski
729*1b8adde7SWilliam Kucharski if (symtab_err)
730*1b8adde7SWilliam Kucharski {
731*1b8adde7SWilliam Kucharski printf ("(bad)");
732*1b8adde7SWilliam Kucharski mbi.syms.e.num = 0;
733*1b8adde7SWilliam Kucharski mbi.syms.e.size = 0;
734*1b8adde7SWilliam Kucharski mbi.syms.e.addr = 0;
735*1b8adde7SWilliam Kucharski mbi.syms.e.shndx = 0;
736*1b8adde7SWilliam Kucharski cur_addr = 0;
737*1b8adde7SWilliam Kucharski }
738*1b8adde7SWilliam Kucharski else
739*1b8adde7SWilliam Kucharski mbi.flags |= MB_INFO_ELF_SHDR;
740*1b8adde7SWilliam Kucharski }
741*1b8adde7SWilliam Kucharski }
742*1b8adde7SWilliam Kucharski }
743*1b8adde7SWilliam Kucharski
744*1b8adde7SWilliam Kucharski if (! errnum)
745*1b8adde7SWilliam Kucharski {
746*1b8adde7SWilliam Kucharski grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
747*1b8adde7SWilliam Kucharski
748*1b8adde7SWilliam Kucharski /* If the entry address is physically different from that of the ELF
749*1b8adde7SWilliam Kucharski header, correct it here. */
750*1b8adde7SWilliam Kucharski if (real_entry_addr)
751*1b8adde7SWilliam Kucharski entry_addr = real_entry_addr;
752*1b8adde7SWilliam Kucharski }
753*1b8adde7SWilliam Kucharski else
754*1b8adde7SWilliam Kucharski {
755*1b8adde7SWilliam Kucharski putchar ('\n');
756*1b8adde7SWilliam Kucharski type = KERNEL_TYPE_NONE;
757*1b8adde7SWilliam Kucharski }
758*1b8adde7SWilliam Kucharski
759*1b8adde7SWilliam Kucharski grub_close ();
760*1b8adde7SWilliam Kucharski
761*1b8adde7SWilliam Kucharski /* Sanity check. */
762*1b8adde7SWilliam Kucharski if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
763*1b8adde7SWilliam Kucharski {
764*1b8adde7SWilliam Kucharski errnum = ERR_EXEC_FORMAT;
765*1b8adde7SWilliam Kucharski return KERNEL_TYPE_NONE;
766*1b8adde7SWilliam Kucharski }
767*1b8adde7SWilliam Kucharski
768*1b8adde7SWilliam Kucharski return type;
769*1b8adde7SWilliam Kucharski }
770*1b8adde7SWilliam Kucharski
771*1b8adde7SWilliam Kucharski int
load_module(char * module,char * arg)772*1b8adde7SWilliam Kucharski load_module (char *module, char *arg)
773*1b8adde7SWilliam Kucharski {
774*1b8adde7SWilliam Kucharski int len;
775*1b8adde7SWilliam Kucharski
776*1b8adde7SWilliam Kucharski /* if we are supposed to load on 4K boundaries */
777*1b8adde7SWilliam Kucharski cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
778*1b8adde7SWilliam Kucharski
779*1b8adde7SWilliam Kucharski if (!grub_open (module))
780*1b8adde7SWilliam Kucharski return 0;
781*1b8adde7SWilliam Kucharski
782*1b8adde7SWilliam Kucharski len = grub_read ((char *) cur_addr, -1);
783*1b8adde7SWilliam Kucharski if (! len)
784*1b8adde7SWilliam Kucharski {
785*1b8adde7SWilliam Kucharski grub_close ();
786*1b8adde7SWilliam Kucharski return 0;
787*1b8adde7SWilliam Kucharski }
788*1b8adde7SWilliam Kucharski
789*1b8adde7SWilliam Kucharski printf (" [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
790*1b8adde7SWilliam Kucharski
791*1b8adde7SWilliam Kucharski /* these two simply need to be set if any modules are loaded at all */
792*1b8adde7SWilliam Kucharski mbi.flags |= MB_INFO_MODS;
793*1b8adde7SWilliam Kucharski mbi.mods_addr = (int) mll;
794*1b8adde7SWilliam Kucharski
795*1b8adde7SWilliam Kucharski mll[mbi.mods_count].cmdline = (int) arg;
796*1b8adde7SWilliam Kucharski mll[mbi.mods_count].mod_start = cur_addr;
797*1b8adde7SWilliam Kucharski cur_addr += len;
798*1b8adde7SWilliam Kucharski mll[mbi.mods_count].mod_end = cur_addr;
799*1b8adde7SWilliam Kucharski mll[mbi.mods_count].pad = 0;
800*1b8adde7SWilliam Kucharski
801*1b8adde7SWilliam Kucharski /* increment number of modules included */
802*1b8adde7SWilliam Kucharski mbi.mods_count++;
803*1b8adde7SWilliam Kucharski
804*1b8adde7SWilliam Kucharski grub_close ();
805*1b8adde7SWilliam Kucharski return 1;
806*1b8adde7SWilliam Kucharski }
807*1b8adde7SWilliam Kucharski
808*1b8adde7SWilliam Kucharski int
load_initrd(char * initrd)809*1b8adde7SWilliam Kucharski load_initrd (char *initrd)
810*1b8adde7SWilliam Kucharski {
811*1b8adde7SWilliam Kucharski int len;
812*1b8adde7SWilliam Kucharski unsigned long moveto;
813*1b8adde7SWilliam Kucharski unsigned long max_addr;
814*1b8adde7SWilliam Kucharski struct linux_kernel_header *lh
815*1b8adde7SWilliam Kucharski = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE);
816*1b8adde7SWilliam Kucharski
817*1b8adde7SWilliam Kucharski #ifndef NO_DECOMPRESSION
818*1b8adde7SWilliam Kucharski no_decompression = 1;
819*1b8adde7SWilliam Kucharski #endif
820*1b8adde7SWilliam Kucharski
821*1b8adde7SWilliam Kucharski if (! grub_open (initrd))
822*1b8adde7SWilliam Kucharski goto fail;
823*1b8adde7SWilliam Kucharski
824*1b8adde7SWilliam Kucharski len = grub_read ((char *) cur_addr, -1);
825*1b8adde7SWilliam Kucharski if (! len)
826*1b8adde7SWilliam Kucharski {
827*1b8adde7SWilliam Kucharski grub_close ();
828*1b8adde7SWilliam Kucharski goto fail;
829*1b8adde7SWilliam Kucharski }
830*1b8adde7SWilliam Kucharski
831*1b8adde7SWilliam Kucharski if (linux_mem_size)
832*1b8adde7SWilliam Kucharski moveto = linux_mem_size;
833*1b8adde7SWilliam Kucharski else
834*1b8adde7SWilliam Kucharski moveto = (mbi.mem_upper + 0x400) << 10;
835*1b8adde7SWilliam Kucharski
836*1b8adde7SWilliam Kucharski moveto = (moveto - len) & 0xfffff000;
837*1b8adde7SWilliam Kucharski max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203
838*1b8adde7SWilliam Kucharski ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
839*1b8adde7SWilliam Kucharski if (moveto + len >= max_addr)
840*1b8adde7SWilliam Kucharski moveto = (max_addr - len) & 0xfffff000;
841*1b8adde7SWilliam Kucharski
842*1b8adde7SWilliam Kucharski /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
843*1b8adde7SWilliam Kucharski the last page.
844*1b8adde7SWilliam Kucharski XXX: Linux 2.2.xx has a bug in the memory range check, which is
845*1b8adde7SWilliam Kucharski worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */
846*1b8adde7SWilliam Kucharski moveto -= 0x10000;
847*1b8adde7SWilliam Kucharski memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
848*1b8adde7SWilliam Kucharski
849*1b8adde7SWilliam Kucharski printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
850*1b8adde7SWilliam Kucharski
851*1b8adde7SWilliam Kucharski /* FIXME: Should check if the kernel supports INITRD. */
852*1b8adde7SWilliam Kucharski lh->ramdisk_image = RAW_ADDR (moveto);
853*1b8adde7SWilliam Kucharski lh->ramdisk_size = len;
854*1b8adde7SWilliam Kucharski
855*1b8adde7SWilliam Kucharski grub_close ();
856*1b8adde7SWilliam Kucharski
857*1b8adde7SWilliam Kucharski fail:
858*1b8adde7SWilliam Kucharski
859*1b8adde7SWilliam Kucharski #ifndef NO_DECOMPRESSION
860*1b8adde7SWilliam Kucharski no_decompression = 0;
861*1b8adde7SWilliam Kucharski #endif
862*1b8adde7SWilliam Kucharski
863*1b8adde7SWilliam Kucharski return ! errnum;
864*1b8adde7SWilliam Kucharski }
865*1b8adde7SWilliam Kucharski
866*1b8adde7SWilliam Kucharski
867*1b8adde7SWilliam Kucharski #ifdef GRUB_UTIL
868*1b8adde7SWilliam Kucharski /* Dummy function to fake the *BSD boot. */
869*1b8adde7SWilliam Kucharski static void
bsd_boot_entry(int flags,int bootdev,int sym_start,int sym_end,int mem_upper,int mem_lower)870*1b8adde7SWilliam Kucharski bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
871*1b8adde7SWilliam Kucharski int mem_upper, int mem_lower)
872*1b8adde7SWilliam Kucharski {
873*1b8adde7SWilliam Kucharski stop ();
874*1b8adde7SWilliam Kucharski }
875*1b8adde7SWilliam Kucharski #endif
876*1b8adde7SWilliam Kucharski
877*1b8adde7SWilliam Kucharski
878*1b8adde7SWilliam Kucharski /*
879*1b8adde7SWilliam Kucharski * All "*_boot" commands depend on the images being loaded into memory
880*1b8adde7SWilliam Kucharski * correctly, the variables in this file being set up correctly, and
881*1b8adde7SWilliam Kucharski * the root partition being set in the 'saved_drive' and 'saved_partition'
882*1b8adde7SWilliam Kucharski * variables.
883*1b8adde7SWilliam Kucharski */
884*1b8adde7SWilliam Kucharski
885*1b8adde7SWilliam Kucharski
886*1b8adde7SWilliam Kucharski void
bsd_boot(kernel_t type,int bootdev,char * arg)887*1b8adde7SWilliam Kucharski bsd_boot (kernel_t type, int bootdev, char *arg)
888*1b8adde7SWilliam Kucharski {
889*1b8adde7SWilliam Kucharski char *str;
890*1b8adde7SWilliam Kucharski int clval = 0, i;
891*1b8adde7SWilliam Kucharski struct bootinfo bi;
892*1b8adde7SWilliam Kucharski
893*1b8adde7SWilliam Kucharski #ifdef GRUB_UTIL
894*1b8adde7SWilliam Kucharski entry_addr = (entry_func) bsd_boot_entry;
895*1b8adde7SWilliam Kucharski #else
896*1b8adde7SWilliam Kucharski stop_floppy ();
897*1b8adde7SWilliam Kucharski #endif
898*1b8adde7SWilliam Kucharski
899*1b8adde7SWilliam Kucharski while (*(++arg) && *arg != ' ');
900*1b8adde7SWilliam Kucharski str = arg;
901*1b8adde7SWilliam Kucharski while (*str)
902*1b8adde7SWilliam Kucharski {
903*1b8adde7SWilliam Kucharski if (*str == '-')
904*1b8adde7SWilliam Kucharski {
905*1b8adde7SWilliam Kucharski while (*str && *str != ' ')
906*1b8adde7SWilliam Kucharski {
907*1b8adde7SWilliam Kucharski if (*str == 'C')
908*1b8adde7SWilliam Kucharski clval |= RB_CDROM;
909*1b8adde7SWilliam Kucharski if (*str == 'a')
910*1b8adde7SWilliam Kucharski clval |= RB_ASKNAME;
911*1b8adde7SWilliam Kucharski if (*str == 'b')
912*1b8adde7SWilliam Kucharski clval |= RB_HALT;
913*1b8adde7SWilliam Kucharski if (*str == 'c')
914*1b8adde7SWilliam Kucharski clval |= RB_CONFIG;
915*1b8adde7SWilliam Kucharski if (*str == 'd')
916*1b8adde7SWilliam Kucharski clval |= RB_KDB;
917*1b8adde7SWilliam Kucharski if (*str == 'D')
918*1b8adde7SWilliam Kucharski clval |= RB_MULTIPLE;
919*1b8adde7SWilliam Kucharski if (*str == 'g')
920*1b8adde7SWilliam Kucharski clval |= RB_GDB;
921*1b8adde7SWilliam Kucharski if (*str == 'h')
922*1b8adde7SWilliam Kucharski clval |= RB_SERIAL;
923*1b8adde7SWilliam Kucharski if (*str == 'm')
924*1b8adde7SWilliam Kucharski clval |= RB_MUTE;
925*1b8adde7SWilliam Kucharski if (*str == 'r')
926*1b8adde7SWilliam Kucharski clval |= RB_DFLTROOT;
927*1b8adde7SWilliam Kucharski if (*str == 's')
928*1b8adde7SWilliam Kucharski clval |= RB_SINGLE;
929*1b8adde7SWilliam Kucharski if (*str == 'v')
930*1b8adde7SWilliam Kucharski clval |= RB_VERBOSE;
931*1b8adde7SWilliam Kucharski str++;
932*1b8adde7SWilliam Kucharski }
933*1b8adde7SWilliam Kucharski continue;
934*1b8adde7SWilliam Kucharski }
935*1b8adde7SWilliam Kucharski str++;
936*1b8adde7SWilliam Kucharski }
937*1b8adde7SWilliam Kucharski
938*1b8adde7SWilliam Kucharski if (type == KERNEL_TYPE_FREEBSD)
939*1b8adde7SWilliam Kucharski {
940*1b8adde7SWilliam Kucharski clval |= RB_BOOTINFO;
941*1b8adde7SWilliam Kucharski
942*1b8adde7SWilliam Kucharski bi.bi_version = BOOTINFO_VERSION;
943*1b8adde7SWilliam Kucharski
944*1b8adde7SWilliam Kucharski *arg = 0;
945*1b8adde7SWilliam Kucharski while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
946*1b8adde7SWilliam Kucharski if (*arg == '/')
947*1b8adde7SWilliam Kucharski bi.bi_kernelname = arg + 1;
948*1b8adde7SWilliam Kucharski else
949*1b8adde7SWilliam Kucharski bi.bi_kernelname = 0;
950*1b8adde7SWilliam Kucharski
951*1b8adde7SWilliam Kucharski bi.bi_nfs_diskless = 0;
952*1b8adde7SWilliam Kucharski bi.bi_n_bios_used = 0; /* this field is apparently unused */
953*1b8adde7SWilliam Kucharski
954*1b8adde7SWilliam Kucharski for (i = 0; i < N_BIOS_GEOM; i++)
955*1b8adde7SWilliam Kucharski {
956*1b8adde7SWilliam Kucharski struct geometry geom;
957*1b8adde7SWilliam Kucharski
958*1b8adde7SWilliam Kucharski /* XXX Should check the return value. */
959*1b8adde7SWilliam Kucharski get_diskinfo (i + 0x80, &geom);
960*1b8adde7SWilliam Kucharski /* FIXME: If HEADS or SECTORS is greater than 255, then this will
961*1b8adde7SWilliam Kucharski break the geometry information. That is a drawback of BSD
962*1b8adde7SWilliam Kucharski but not of GRUB. */
963*1b8adde7SWilliam Kucharski bi.bi_bios_geom[i] = (((geom.cylinders - 1) << 16)
964*1b8adde7SWilliam Kucharski + (((geom.heads - 1) & 0xff) << 8)
965*1b8adde7SWilliam Kucharski + (geom.sectors & 0xff));
966*1b8adde7SWilliam Kucharski }
967*1b8adde7SWilliam Kucharski
968*1b8adde7SWilliam Kucharski bi.bi_size = sizeof (struct bootinfo);
969*1b8adde7SWilliam Kucharski bi.bi_memsizes_valid = 1;
970*1b8adde7SWilliam Kucharski bi.bi_bios_dev = saved_drive;
971*1b8adde7SWilliam Kucharski bi.bi_basemem = mbi.mem_lower;
972*1b8adde7SWilliam Kucharski bi.bi_extmem = extended_memory;
973*1b8adde7SWilliam Kucharski
974*1b8adde7SWilliam Kucharski if (mbi.flags & MB_INFO_AOUT_SYMS)
975*1b8adde7SWilliam Kucharski {
976*1b8adde7SWilliam Kucharski bi.bi_symtab = mbi.syms.a.addr;
977*1b8adde7SWilliam Kucharski bi.bi_esymtab = mbi.syms.a.addr + 4
978*1b8adde7SWilliam Kucharski + mbi.syms.a.tabsize + mbi.syms.a.strsize;
979*1b8adde7SWilliam Kucharski }
980*1b8adde7SWilliam Kucharski #if 0
981*1b8adde7SWilliam Kucharski else if (mbi.flags & MB_INFO_ELF_SHDR)
982*1b8adde7SWilliam Kucharski {
983*1b8adde7SWilliam Kucharski /* FIXME: Should check if a symbol table exists and, if exists,
984*1b8adde7SWilliam Kucharski pass the table to BI. */
985*1b8adde7SWilliam Kucharski }
986*1b8adde7SWilliam Kucharski #endif
987*1b8adde7SWilliam Kucharski else
988*1b8adde7SWilliam Kucharski {
989*1b8adde7SWilliam Kucharski bi.bi_symtab = 0;
990*1b8adde7SWilliam Kucharski bi.bi_esymtab = 0;
991*1b8adde7SWilliam Kucharski }
992*1b8adde7SWilliam Kucharski
993*1b8adde7SWilliam Kucharski /* call entry point */
994*1b8adde7SWilliam Kucharski (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) (&bi)));
995*1b8adde7SWilliam Kucharski }
996*1b8adde7SWilliam Kucharski else
997*1b8adde7SWilliam Kucharski {
998*1b8adde7SWilliam Kucharski /*
999*1b8adde7SWilliam Kucharski * We now pass the various bootstrap parameters to the loaded
1000*1b8adde7SWilliam Kucharski * image via the argument list.
1001*1b8adde7SWilliam Kucharski *
1002*1b8adde7SWilliam Kucharski * This is the official list:
1003*1b8adde7SWilliam Kucharski *
1004*1b8adde7SWilliam Kucharski * arg0 = 8 (magic)
1005*1b8adde7SWilliam Kucharski * arg1 = boot flags
1006*1b8adde7SWilliam Kucharski * arg2 = boot device
1007*1b8adde7SWilliam Kucharski * arg3 = start of symbol table (0 if not loaded)
1008*1b8adde7SWilliam Kucharski * arg4 = end of symbol table (0 if not loaded)
1009*1b8adde7SWilliam Kucharski * arg5 = transfer address from image
1010*1b8adde7SWilliam Kucharski * arg6 = transfer address for next image pointer
1011*1b8adde7SWilliam Kucharski * arg7 = conventional memory size (640)
1012*1b8adde7SWilliam Kucharski * arg8 = extended memory size (8196)
1013*1b8adde7SWilliam Kucharski *
1014*1b8adde7SWilliam Kucharski * ...in actuality, we just pass the parameters used by the kernel.
1015*1b8adde7SWilliam Kucharski */
1016*1b8adde7SWilliam Kucharski
1017*1b8adde7SWilliam Kucharski /* call entry point */
1018*1b8adde7SWilliam Kucharski unsigned long end_mark;
1019*1b8adde7SWilliam Kucharski
1020*1b8adde7SWilliam Kucharski if (mbi.flags & MB_INFO_AOUT_SYMS)
1021*1b8adde7SWilliam Kucharski end_mark = (mbi.syms.a.addr + 4
1022*1b8adde7SWilliam Kucharski + mbi.syms.a.tabsize + mbi.syms.a.strsize);
1023*1b8adde7SWilliam Kucharski else
1024*1b8adde7SWilliam Kucharski /* FIXME: it should be mbi.syms.e.size. */
1025*1b8adde7SWilliam Kucharski end_mark = 0;
1026*1b8adde7SWilliam Kucharski
1027*1b8adde7SWilliam Kucharski (*entry_addr) (clval, bootdev, 0, end_mark,
1028*1b8adde7SWilliam Kucharski extended_memory, mbi.mem_lower);
1029*1b8adde7SWilliam Kucharski }
1030*1b8adde7SWilliam Kucharski }
1031