~smartboyhw/wubi/bug-1080090-new

« back to all changes in this revision

Viewing changes to src/grub4dos/stage2/.svn/text-base/boot.c.svn-base

  • Committer: Howard Chan
  • Date: 2012-11-20 10:16:05 UTC
  • Revision ID: smartboyhw@gmail.com-20121120101605-qfmjfsdynpzg9an9
Added images

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* boot.c - load and bootstrap a kernel */
2
 
/*
3
 
 *  GRUB  --  GRand Unified Bootloader
4
 
 *  Copyright (C) 1999,2000,2001,2002,2003,2004  Free Software Foundation, Inc.
5
 
 *
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.
10
 
 *
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.
15
 
 *
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.
19
 
 */
20
 
 
21
 
 
22
 
#include "shared.h"
23
 
#include <term.h>
24
 
 
25
 
#include "freebsd.h"
26
 
#include "imgact_aout.h"
27
 
#include "i386-elf.h"
28
 
 
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;
33
 
 
34
 
/*
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.
38
 
 */
39
 
 
40
 
kernel_t
41
 
load_image (char *kernel, char *arg, kernel_t suggested_type,
42
 
            unsigned long load_flags)
43
 
{
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;
50
 
  union
51
 
    {
52
 
      struct multiboot_header *mb;
53
 
      struct exec *aout;
54
 
      Elf32_Ehdr *elf;
55
 
    }
56
 
  pu;
57
 
  /* presuming that MULTIBOOT_SEARCH is large enough to encompass an
58
 
     executable header */
59
 
#ifndef GRUB_UTIL
60
 
  unsigned char *buffer = (unsigned char *)(FSYS_BUF - MULTIBOOT_SEARCH);
61
 
#else
62
 
  unsigned char buffer[MULTIBOOT_SEARCH];
63
 
#endif
64
 
 
65
 
  /* sets the header pointer to point to the beginning of the
66
 
     buffer by default */
67
 
  pu.aout = (struct exec *) buffer;
68
 
 
69
 
  if (!grub_open (kernel))
70
 
    return KERNEL_TYPE_NONE;
71
 
 
72
 
  if (!(len = grub_read ((char *)buffer, MULTIBOOT_SEARCH)) || len < 32)
73
 
    {
74
 
      grub_close ();
75
 
      
76
 
      if (!errnum)
77
 
        errnum = ERR_EXEC_FORMAT;
78
 
 
79
 
      return KERNEL_TYPE_NONE;
80
 
    }
81
 
 
82
 
  for (i = 0; i < len; i++)
83
 
    {
84
 
      if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
85
 
        {
86
 
          flags = ((struct multiboot_header *) (buffer + i))->flags;
87
 
          if (flags & MULTIBOOT_UNSUPPORTED)
88
 
            {
89
 
              grub_close ();
90
 
              errnum = ERR_BOOT_FEATURES;
91
 
              return KERNEL_TYPE_NONE;
92
 
            }
93
 
          type = KERNEL_TYPE_MULTIBOOT;
94
 
          str2 = "Multiboot";
95
 
          break;
96
 
        }
97
 
    }
98
 
 
99
 
  /* leave graphics mode now before the extended memory is overwritten. */
100
 
#ifdef SUPPORT_GRAPHICS
101
 
  if (graphics_inited)
102
 
  {
103
 
    graphics_end ();
104
 
    current_term = term_table; /* assumption: console is first */
105
 
  }
106
 
#endif
107
 
 
108
 
  /* Use BUFFER as a linux kernel header, if the image is Linux zImage
109
 
     or bzImage.  */
110
 
  lh = (struct linux_kernel_header *) buffer;
111
 
  
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))))
119
 
    {
120
 
      if (type == KERNEL_TYPE_MULTIBOOT)
121
 
        entry_addr = (entry_func) pu.elf->e_entry;
122
 
      else
123
 
        entry_addr = (entry_func) (pu.elf->e_entry & 0xFFFFFF);
124
 
 
125
 
      if (entry_addr < (entry_func) 0x100000)
126
 
        errnum = ERR_BELOW_1MB;
127
 
 
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))
132
 
              >= len))
133
 
        errnum = ERR_EXEC_FORMAT;
134
 
      str = "elf";
135
 
 
136
 
      if (type == KERNEL_TYPE_NONE)
137
 
        {
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)
141
 
            {
142
 
              str2 = "NetBSD";
143
 
              type = suggested_type;
144
 
            }
145
 
          else
146
 
            {
147
 
              str2 = "FreeBSD";
148
 
              type = KERNEL_TYPE_FREEBSD;
149
 
            }
150
 
        }
151
 
    }
152
 
  else if (flags & MULTIBOOT_AOUT_KLUDGE)
153
 
    {
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);
159
 
 
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;
163
 
      
164
 
      text_len = pu.mb->load_end_addr - cur_addr;
165
 
      data_len = 0;
166
 
 
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;
170
 
      
171
 
      bss_len = pu.mb->bss_end_addr - pu.mb->load_end_addr;
172
 
 
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;
178
 
 
179
 
      if (cur_addr < 0x100000)
180
 
        errnum = ERR_BELOW_1MB;
181
 
 
182
 
      pu.aout = (struct exec *) buffer;
183
 
      exec_type = 2;
184
 
      str = "kludge";
185
 
    }
186
 
  else if (len > sizeof (struct exec) && !N_BADMAG ((*(pu.aout))))
187
 
    {
188
 
      entry_addr = (entry_func) pu.aout->a_entry;
189
 
 
190
 
      if (type == KERNEL_TYPE_NONE)
191
 
        {
192
 
          /*
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.
197
 
           *
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
201
 
           *  method to use.
202
 
           */
203
 
          entry_addr = (entry_func) ((int) entry_addr & 0xFFFFFF);
204
 
          
205
 
          if (buffer[0] == 0xb && buffer[1] == 1)
206
 
            {
207
 
              type = KERNEL_TYPE_FREEBSD;
208
 
              cur_addr = (int) entry_addr;
209
 
              str2 = "FreeBSD";
210
 
            }
211
 
          else
212
 
            {
213
 
              type = KERNEL_TYPE_NETBSD;
214
 
              cur_addr = (int) entry_addr & 0xF00000;
215
 
              if (N_GETMAGIC ((*(pu.aout))) != NMAGIC)
216
 
                align_4k = 0;
217
 
              str2 = "NetBSD";
218
 
            }
219
 
        }
220
 
 
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;
226
 
 
227
 
      if (cur_addr < 0x100000)
228
 
        errnum = ERR_BELOW_1MB;
229
 
 
230
 
      exec_type = 1;
231
 
      str = "a.out";
232
 
    }
233
 
  else if (lh->boot_flag == BOOTSEC_SIGNATURE
234
 
           && lh->setup_sects <= LINUX_MAX_SETUP_SECTS)
235
 
    {
236
 
      int big_linux = 0;
237
 
      int setup_sects = lh->setup_sects;
238
 
 
239
 
      if (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0200)
240
 
        {
241
 
          big_linux = (lh->loadflags & LINUX_FLAG_BIG_KERNEL);
242
 
          lh->type_of_loader = LINUX_BOOT_LOADER_TYPE;
243
 
 
244
 
          /* Put the real mode part at as a high location as possible.  */
245
 
          linux_data_real_addr
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;
250
 
 
251
 
          if (lh->version >= 0x0201)
252
 
            {
253
 
              lh->heap_end_ptr = LINUX_HEAP_END_OFFSET;
254
 
              lh->loadflags |= LINUX_FLAG_CAN_USE_HEAP;
255
 
            }
256
 
 
257
 
          if (lh->version >= 0x0202)
258
 
            lh->cmd_line_ptr = linux_data_real_addr + LINUX_CL_OFFSET;
259
 
          else
260
 
            {
261
 
              lh->cl_magic = LINUX_CL_MAGIC;
262
 
              lh->cl_offset = LINUX_CL_OFFSET;
263
 
              lh->setup_move_size = LINUX_SETUP_MOVE_SIZE;
264
 
            }
265
 
        }
266
 
      else
267
 
        {
268
 
          /* Your kernel is quite old...  */
269
 
          lh->cl_magic = LINUX_CL_MAGIC;
270
 
          lh->cl_offset = LINUX_CL_OFFSET;
271
 
          
272
 
          setup_sects = LINUX_DEFAULT_SETUP_SECTS;
273
 
 
274
 
          linux_data_real_addr = (char *) LINUX_OLD_REAL_MODE_ADDR;
275
 
        }
276
 
      
277
 
      /* If SETUP_SECTS is not set, set it to the default (4).  */
278
 
      if (! setup_sects)
279
 
        setup_sects = LINUX_DEFAULT_SETUP_SECTS;
280
 
 
281
 
      data_len = setup_sects << 9;
282
 
      text_len = filemax - data_len - SECTOR_SIZE;
283
 
 
284
 
      linux_data_tmp_addr = (char *) LINUX_BZIMAGE_ADDR + text_len;
285
 
      
286
 
      if (! big_linux
287
 
          && text_len > linux_data_real_addr - (char *) LINUX_ZIMAGE_ADDR)
288
 
        {
289
 
          grub_printf (" linux 'zImage' kernel too big, try 'make bzImage'\n");
290
 
          errnum = ERR_WONT_FIT;
291
 
        }
292
 
      else if (linux_data_real_addr + LINUX_SETUP_MOVE_SIZE
293
 
               > RAW_ADDR ((char *) (saved_mem_lower << 10)))
294
 
        errnum = ERR_WONT_FIT;
295
 
      else
296
 
        {
297
 
          if (debug > 0)
298
 
              grub_printf ("   [Linux-%s, setup=0x%x, size=0x%x]\n",
299
 
                       (big_linux ? "bzImage" : "zImage"), data_len, text_len);
300
 
 
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
305
 
             any more. -okuji  */
306
 
          {
307
 
            char *vga;
308
 
        
309
 
            /* Find the substring "vga=".  */
310
 
            vga = grub_strstr (arg, "vga=");
311
 
            if (vga)
312
 
              {
313
 
                char *value = vga + 4;
314
 
                int vid_mode;
315
 
            
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))
324
 
                  ;
325
 
                else
326
 
                  {
327
 
                    /* ERRNUM is already set inside the function
328
 
                       safe_parse_maxint.  */
329
 
                    grub_close ();
330
 
                    return KERNEL_TYPE_NONE;
331
 
                  }
332
 
            
333
 
                lh->vid_mode = vid_mode;
334
 
              }
335
 
          }
336
 
 
337
 
          /* Check the mem= option to limit memory used for initrd.  */
338
 
          {
339
 
            char *mem;
340
 
        
341
 
            mem = grub_strstr (arg, "mem=");
342
 
            if (mem)
343
 
              {
344
 
                char *value = mem + 4;
345
 
            
346
 
                safe_parse_maxint (&value, (int *)(void *)&linux_mem_size);
347
 
                switch (errnum)
348
 
                  {
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;
354
 
                    errnum = ERR_NONE;
355
 
                    break;
356
 
                
357
 
                  case ERR_NONE:
358
 
                    {
359
 
                      int shift = 0;
360
 
                  
361
 
                      switch (grub_tolower (*value))
362
 
                        {
363
 
                        case 'g':
364
 
                          shift += 10;
365
 
                        case 'm':
366
 
                          shift += 10;
367
 
                        case 'k':
368
 
                          shift += 10;
369
 
                        default:
370
 
                          break;
371
 
                        }
372
 
                  
373
 
                      /* Check an overflow.  */
374
 
                      if (linux_mem_size > (MAXINT >> shift))
375
 
                        linux_mem_size = LINUX_INITRD_MAX_ADDRESS;
376
 
                      else
377
 
                        linux_mem_size <<= shift;
378
 
                    }
379
 
                    break;
380
 
                
381
 
                  default:
382
 
                    linux_mem_size = 0;
383
 
                    errnum = ERR_NONE;
384
 
                    break;
385
 
                  }
386
 
              }
387
 
            else
388
 
              linux_mem_size = 0;
389
 
          }
390
 
      
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);
396
 
          else
397
 
            {
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);
401
 
            }
402
 
          
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),
407
 
                         0,
408
 
                         (64 - setup_sects - 1) << 9);
409
 
      
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.  */
418
 
          {
419
 
            char *src = skip_to (0, arg);
420
 
            char *dest = linux_data_tmp_addr + LINUX_CL_OFFSET;
421
 
        
422
 
            while (dest < linux_data_tmp_addr + LINUX_CL_END_OFFSET && *src)
423
 
              *(dest++) = *(src++);
424
 
        
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)
444
 
              {
445
 
                *dest++ = ' ';
446
 
                *dest++ = 'm';
447
 
                *dest++ = 'e';
448
 
                *dest++ = 'm';
449
 
                *dest++ = '=';
450
 
            
451
 
                dest = convert_to_ascii (dest, 'u', (extended_memory + 0x400));
452
 
                *dest++ = 'K';
453
 
              }
454
 
        
455
 
            *dest = 0;
456
 
          }
457
 
      
458
 
          /* offset into file */
459
 
          filepos = data_len + SECTOR_SIZE;
460
 
      
461
 
          cur_addr = (int) linux_data_tmp_addr + LINUX_SETUP_MOVE_SIZE;
462
 
          grub_read ((char *) LINUX_BZIMAGE_ADDR, text_len);
463
 
      
464
 
          if (errnum == ERR_NONE)
465
 
            {
466
 
              grub_close ();
467
 
          
468
 
              /* Sanity check.  */
469
 
              if (suggested_type != KERNEL_TYPE_NONE
470
 
                  && ((big_linux && suggested_type != KERNEL_TYPE_BIG_LINUX)
471
 
                      || (! big_linux && suggested_type != KERNEL_TYPE_LINUX)))
472
 
                {
473
 
                  errnum = ERR_EXEC_FORMAT;
474
 
                  return KERNEL_TYPE_NONE;
475
 
                }
476
 
          
477
 
              /* Ugly hack.  */
478
 
              linux_text_len = text_len;
479
 
          
480
 
              return big_linux ? KERNEL_TYPE_BIG_LINUX : KERNEL_TYPE_LINUX;
481
 
            }
482
 
        }
483
 
    }
484
 
  else                          /* no recognizable format */
485
 
    errnum = ERR_EXEC_FORMAT;
486
 
 
487
 
  /* return if error */
488
 
  if (errnum)
489
 
    {
490
 
      grub_close ();
491
 
      return KERNEL_TYPE_NONE;
492
 
    }
493
 
 
494
 
  /* fill the multiboot info structure */
495
 
  mbi.cmdline = (int) arg;
496
 
  mbi.mods_count = 0;
497
 
  mbi.mods_addr = 0;
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;
502
 
  mbi.syms.a.addr = 0;
503
 
  mbi.syms.a.pad = 0;
504
 
 
505
 
  if (debug > 0)
506
 
      printf ("   [%s-%s", str2, str);
507
 
 
508
 
  str = "";
509
 
 
510
 
  if (exec_type)                /* can be loaded like a.out */
511
 
    {
512
 
      if (flags & MULTIBOOT_AOUT_KLUDGE)
513
 
        str = "-and-data";
514
 
 
515
 
      if (debug > 0)
516
 
          printf (", loadaddr=0x%x, text%s=0x%x", cur_addr, str, text_len);
517
 
 
518
 
      /* read text, then read data */
519
 
      if (grub_read ((char *) RAW_ADDR (cur_addr), text_len) == text_len)
520
 
        {
521
 
          cur_addr += text_len;
522
 
 
523
 
          if (!(flags & MULTIBOOT_AOUT_KLUDGE))
524
 
            {
525
 
              /* we have to align to a 4K boundary */
526
 
              if (align_4k)
527
 
                cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
528
 
              else
529
 
                if (debug > 0)
530
 
                    printf (", C");
531
 
 
532
 
              if (debug > 0)
533
 
                  printf (", data=0x%x", data_len);
534
 
 
535
 
              if ((grub_read ((char *) RAW_ADDR (cur_addr), data_len)
536
 
                   != data_len)
537
 
                  && !errnum)
538
 
                errnum = ERR_EXEC_FORMAT;
539
 
              cur_addr += data_len;
540
 
            }
541
 
 
542
 
          if (!errnum)
543
 
            {
544
 
              memset ((char *) RAW_ADDR (cur_addr), 0, bss_len);
545
 
              cur_addr += bss_len;
546
 
 
547
 
              if (debug > 0)
548
 
                  printf (", bss=0x%x", bss_len);
549
 
            }
550
 
        }
551
 
      else if (!errnum)
552
 
        errnum = ERR_EXEC_FORMAT;
553
 
 
554
 
      if (!errnum && pu.aout->a_syms
555
 
          && pu.aout->a_syms < (filemax - filepos))
556
 
        {
557
 
          int symtab_err, orig_addr = cur_addr;
558
 
 
559
 
          /* we should align to a 4K boundary here for good measure */
560
 
          if (align_4k)
561
 
            cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
562
 
 
563
 
          mbi.syms.a.addr = cur_addr;
564
 
 
565
 
          *((int *) RAW_ADDR (cur_addr)) = pu.aout->a_syms;
566
 
          cur_addr += sizeof (int);
567
 
          
568
 
          if (debug > 0)
569
 
              printf (", symtab=0x%x", pu.aout->a_syms);
570
 
 
571
 
          if (grub_read ((char *) RAW_ADDR (cur_addr), pu.aout->a_syms)
572
 
              == pu.aout->a_syms)
573
 
            {
574
 
              cur_addr += pu.aout->a_syms;
575
 
              mbi.syms.a.tabsize = pu.aout->a_syms;
576
 
 
577
 
              if (grub_read ((char *) &i, sizeof (int)) == sizeof (int))
578
 
                {
579
 
                  *((int *) RAW_ADDR (cur_addr)) = i;
580
 
                  cur_addr += sizeof (int);
581
 
 
582
 
                  mbi.syms.a.strsize = i;
583
 
 
584
 
                  i -= sizeof (int);
585
 
 
586
 
                  if (debug > 0)
587
 
                      printf (", strtab=0x%x", i);
588
 
 
589
 
                  symtab_err = (grub_read ((char *) RAW_ADDR (cur_addr), i)
590
 
                                != i);
591
 
                  cur_addr += i;
592
 
                }
593
 
              else
594
 
                symtab_err = 1;
595
 
            }
596
 
          else
597
 
            symtab_err = 1;
598
 
 
599
 
          if (symtab_err)
600
 
            {
601
 
              if (debug > 0)
602
 
                  printf ("(bad)");
603
 
              cur_addr = orig_addr;
604
 
              mbi.syms.a.tabsize = 0;
605
 
              mbi.syms.a.strsize = 0;
606
 
              mbi.syms.a.addr = 0;
607
 
            }
608
 
          else
609
 
            mbi.flags |= MB_INFO_AOUT_SYMS;
610
 
        }
611
 
    }
612
 
  else
613
 
    /* ELF executable */
614
 
    {
615
 
      unsigned loaded = 0, memaddr, memsiz, filesiz;
616
 
      Elf32_Phdr *phdr;
617
 
 
618
 
      /* reset this to zero for now */
619
 
      cur_addr = 0;
620
 
 
621
 
      /* scan for program segments */
622
 
      for (i = 0; i < pu.elf->e_phnum; i++)
623
 
        {
624
 
          phdr = (Elf32_Phdr *)
625
 
            (pu.elf->e_phoff + ((int) buffer)
626
 
             + (pu.elf->e_phentsize * i));
627
 
          if (phdr->p_type == PT_LOAD)
628
 
            {
629
 
              /* offset into file */
630
 
              filepos = phdr->p_offset;
631
 
              filesiz = phdr->p_filesz;
632
 
              
633
 
              if (type == KERNEL_TYPE_FREEBSD || type == KERNEL_TYPE_NETBSD)
634
 
                memaddr = RAW_ADDR (phdr->p_paddr & 0xFFFFFF);
635
 
              else
636
 
                memaddr = RAW_ADDR (phdr->p_paddr);
637
 
              
638
 
              memsiz = phdr->p_memsz;
639
 
              if (memaddr < RAW_ADDR (0x100000))
640
 
                errnum = ERR_BELOW_1MB;
641
 
 
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);
649
 
                
650
 
              /* make sure we only load what we're supposed to! */
651
 
              if (filesiz > memsiz)
652
 
                filesiz = memsiz;
653
 
              /* mark memory as used */
654
 
              if (cur_addr < memaddr + memsiz)
655
 
                cur_addr = memaddr + memsiz;
656
 
              if (debug > 0)
657
 
                  printf (", <0x%x:0x%x:0x%x>", memaddr, filesiz,
658
 
                      memsiz - filesiz);
659
 
              /* increment number of segments */
660
 
              loaded++;
661
 
 
662
 
              /* load the segment */
663
 
              if (memcheck (memaddr, memsiz)
664
 
                  && grub_read ((char *) memaddr, filesiz) == filesiz)
665
 
                {
666
 
                  if (memsiz > filesiz)
667
 
                    memset ((char *) (memaddr + filesiz), 0, memsiz - filesiz);
668
 
                }
669
 
              else
670
 
                break;
671
 
            }
672
 
        }
673
 
 
674
 
      if (! errnum)
675
 
        {
676
 
          if (! loaded)
677
 
            errnum = ERR_EXEC_FORMAT;
678
 
          else
679
 
            {
680
 
              /* Load ELF symbols.  */
681
 
              Elf32_Shdr *shdr = NULL;
682
 
              int tab_size, sec_size;
683
 
              int symtab_err = 0;
684
 
 
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;
688
 
              
689
 
              /* We should align to a 4K boundary here for good measure.  */
690
 
              if (align_4k)
691
 
                cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
692
 
              
693
 
              tab_size = pu.elf->e_shentsize * pu.elf->e_shnum;
694
 
              
695
 
              filepos = pu.elf->e_shoff;
696
 
              if (grub_read ((char *) RAW_ADDR (cur_addr), tab_size)
697
 
                  == tab_size)
698
 
                {
699
 
                  mbi.syms.e.addr = cur_addr;
700
 
                  shdr = (Elf32_Shdr *) mbi.syms.e.addr;
701
 
                  cur_addr += tab_size;
702
 
                  
703
 
                  if (debug > 0)
704
 
                      printf (", shtab=0x%x", cur_addr);
705
 
                  
706
 
                  for (i = 0; i < mbi.syms.e.num; i++)
707
 
                    {
708
 
                      /* This section is a loaded section,
709
 
                         so we don't care.  */
710
 
                      if (shdr[i].sh_addr != 0)
711
 
                        continue;
712
 
                      
713
 
                      /* This section is empty, so we don't care.  */
714
 
                      if (shdr[i].sh_size == 0)
715
 
                        continue;
716
 
                      
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);
720
 
                      
721
 
                      filepos = shdr[i].sh_offset;
722
 
                      
723
 
                      sec_size = shdr[i].sh_size;
724
 
 
725
 
                      if (! (memcheck (cur_addr, sec_size)
726
 
                             && (grub_read ((char *) RAW_ADDR (cur_addr),
727
 
                                            sec_size)
728
 
                                 == sec_size)))
729
 
                        {
730
 
                          symtab_err = 1;
731
 
                          break;
732
 
                        }
733
 
                      
734
 
                      shdr[i].sh_addr = cur_addr;
735
 
                      cur_addr += sec_size;
736
 
                    }
737
 
                }
738
 
              else 
739
 
                symtab_err = 1;
740
 
              
741
 
              if (mbi.syms.e.addr < (unsigned long)(RAW_ADDR(0x10000)))
742
 
                symtab_err = 1;
743
 
              
744
 
              if (symtab_err) 
745
 
                {
746
 
                  if (debug > 0)
747
 
                      printf ("(bad)");
748
 
                  mbi.syms.e.num = 0;
749
 
                  mbi.syms.e.size = 0;
750
 
                  mbi.syms.e.addr = 0;
751
 
                  mbi.syms.e.shndx = 0;
752
 
                  cur_addr = 0;
753
 
                }
754
 
              else
755
 
                mbi.flags |= MB_INFO_ELF_SHDR;
756
 
            }
757
 
        }
758
 
    }
759
 
 
760
 
  if (! errnum)
761
 
    {
762
 
      if (debug > 0)
763
 
          grub_printf (", entry=0x%x]\n", (unsigned) entry_addr);
764
 
      
765
 
      /* If the entry address is physically different from that of the ELF
766
 
         header, correct it here.  */
767
 
      if (real_entry_addr)
768
 
        entry_addr = real_entry_addr;
769
 
    }
770
 
  else
771
 
    {
772
 
      putchar ('\n');
773
 
      type = KERNEL_TYPE_NONE;
774
 
    }
775
 
 
776
 
  grub_close ();
777
 
 
778
 
  /* Sanity check.  */
779
 
  if (suggested_type != KERNEL_TYPE_NONE && suggested_type != type)
780
 
    {
781
 
      errnum = ERR_EXEC_FORMAT;
782
 
      return KERNEL_TYPE_NONE;
783
 
    }
784
 
  
785
 
  return type;
786
 
}
787
 
 
788
 
int
789
 
load_module (char *module, char *arg)
790
 
{
791
 
  unsigned long len;
792
 
 
793
 
  /* if we are supposed to load on 4K boundaries */
794
 
  cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
795
 
 
796
 
  if (!grub_open (module))
797
 
    return 0;
798
 
 
799
 
  len = grub_read ((char *) cur_addr, -1);
800
 
  if (! len)
801
 
    {
802
 
      grub_close ();
803
 
      return 0;
804
 
    }
805
 
 
806
 
  if (debug > 0)
807
 
      printf ("   [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
808
 
 
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;
812
 
 
813
 
  mll[mbi.mods_count].cmdline = (int) arg;
814
 
  mll[mbi.mods_count].mod_start = cur_addr;
815
 
  cur_addr += len;
816
 
  mll[mbi.mods_count].mod_end = cur_addr;
817
 
  mll[mbi.mods_count].pad = 0;
818
 
 
819
 
  /* increment number of modules included */
820
 
  mbi.mods_count++;
821
 
 
822
 
  grub_close ();
823
 
  return 1;
824
 
}
825
 
 
826
 
int
827
 
load_initrd (char *initrd)
828
 
{
829
 
  unsigned long len;
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);
834
 
  
835
 
#ifndef NO_DECOMPRESSION
836
 
  no_decompression = 1;
837
 
#endif
838
 
  
839
 
  if (! grub_open (initrd))
840
 
    goto fail;
841
 
 
842
 
  len = filemax;        //grub_read ((char *) cur_addr, -1);
843
 
  if (! len)
844
 
    {
845
 
      grub_close ();
846
 
      errnum = ERR_EXEC_FORMAT; /* empty file */
847
 
      goto fail;
848
 
    }
849
 
 
850
 
  if (linux_mem_size)
851
 
    moveto = linux_mem_size;
852
 
  else
853
 
    moveto = (saved_mem_upper + 0x400) << 10;
854
 
  
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;
860
 
  
861
 
  /* XXX: Linux 2.3.xx has a bug in the memory range check, so avoid
862
 
     the last page.
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*  */
865
 
  moveto -= 0x10000;
866
 
  //memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len);
867
 
  len = grub_read ((char *) RAW_ADDR (moveto), -1);
868
 
  if (! len)
869
 
    {
870
 
      grub_close ();
871
 
      goto fail;
872
 
    }
873
 
 
874
 
  if (debug > 0)
875
 
      printf ("   [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len);
876
 
 
877
 
  /* FIXME: Should check if the kernel supports INITRD.  */
878
 
  lh->ramdisk_image = RAW_ADDR (moveto);
879
 
  lh->ramdisk_size = len;
880
 
 
881
 
  grub_close ();
882
 
 
883
 
 fail:
884
 
  
885
 
#ifndef NO_DECOMPRESSION
886
 
  no_decompression = 0;
887
 
#endif
888
 
 
889
 
  return ! errnum;
890
 
}
891
 
 
892
 
 
893
 
#ifdef GRUB_UTIL
894
 
/* Dummy function to fake the *BSD boot.  */
895
 
static void
896
 
bsd_boot_entry (int flags, int bootdev, int sym_start, int sym_end,
897
 
                int mem_upper, int mem_lower)
898
 
{
899
 
  stop ();
900
 
}
901
 
#endif
902
 
 
903
 
 
904
 
/*
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'
908
 
 *  variables.
909
 
 */
910
 
 
911
 
 
912
 
void
913
 
bsd_boot (kernel_t type, int bootdev, char *arg)
914
 
{
915
 
  char *str;
916
 
  int clval = 0, i;
917
 
 
918
 
#ifdef GRUB_UTIL
919
 
  struct bootinfo bi1;  //this takes up too much stack!
920
 
  struct bootinfo *bi = &bi1;
921
 
  entry_addr = (entry_func) bsd_boot_entry;
922
 
#else
923
 
  struct bootinfo *bi = (struct bootinfo *)mbr; // tmp. use mbr
924
 
  stop_floppy ();
925
 
#endif
926
 
 
927
 
  while (*(++arg) && *arg != ' ');
928
 
  str = arg;
929
 
  while (*str)
930
 
    {
931
 
      if (*str == '-')
932
 
        {
933
 
          while (*str && *str != ' ')
934
 
            {
935
 
              if (*str == 'C')
936
 
                clval |= RB_CDROM;
937
 
              if (*str == 'a')
938
 
                clval |= RB_ASKNAME;
939
 
              if (*str == 'b')
940
 
                clval |= RB_HALT;
941
 
              if (*str == 'c')
942
 
                clval |= RB_CONFIG;
943
 
              if (*str == 'd')
944
 
                clval |= RB_KDB;
945
 
              if (*str == 'D')
946
 
                clval |= RB_MULTIPLE;
947
 
              if (*str == 'g')
948
 
                clval |= RB_GDB;
949
 
              if (*str == 'h')
950
 
                clval |= RB_SERIAL;
951
 
              if (*str == 'm')
952
 
                clval |= RB_MUTE;
953
 
              if (*str == 'r')
954
 
                clval |= RB_DFLTROOT;
955
 
              if (*str == 's')
956
 
                clval |= RB_SINGLE;
957
 
              if (*str == 'v')
958
 
                clval |= RB_VERBOSE;
959
 
              str++;
960
 
            }
961
 
          continue;
962
 
        }
963
 
      str++;
964
 
    }
965
 
 
966
 
  if (type == KERNEL_TYPE_FREEBSD)
967
 
    {
968
 
      clval |= RB_BOOTINFO;
969
 
 
970
 
      bi->bi_version = BOOTINFO_VERSION;
971
 
 
972
 
      *arg = 0;
973
 
      while ((--arg) > (char *) MB_CMDLINE_BUF && *arg != '/');
974
 
      if (*arg == '/')
975
 
        bi->bi_kernelname = (unsigned char *)arg + 1;
976
 
      else
977
 
        bi->bi_kernelname = 0;
978
 
 
979
 
      bi->bi_nfs_diskless = 0;
980
 
      bi->bi_n_bios_used = 0;   /* this field is apparently unused */
981
 
 
982
 
      for (i = 0; i < N_BIOS_GEOM; i++)
983
 
        {
984
 
//        struct geometry tmp_geom;
985
 
 
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
990
 
             but not of GRUB.  */
991
 
          bi->bi_bios_geom[i] = (((tmp_geom.cylinders - 1) << 16)
992
 
                                + (((tmp_geom.heads - 1) & 0xff) << 8)
993
 
                                + (tmp_geom.sectors & 0xff));
994
 
        }
995
 
 
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;
1001
 
 
1002
 
      if (mbi.flags & MB_INFO_AOUT_SYMS)
1003
 
        {
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;
1006
 
        }
1007
 
#if 0
1008
 
      else if (mbi.flags & MB_INFO_ELF_SHDR)
1009
 
        {
1010
 
          /* FIXME: Should check if a symbol table exists and, if exists,
1011
 
             pass the table to BI.  */
1012
 
        }
1013
 
#endif
1014
 
      else
1015
 
        {
1016
 
          bi->bi_symtab = 0;
1017
 
          bi->bi_esymtab = 0;
1018
 
        }
1019
 
 
1020
 
      /* call entry point */
1021
 
      (*entry_addr) (clval, bootdev, 0, 0, 0, ((int) bi));
1022
 
    }
1023
 
  else
1024
 
    {
1025
 
      /*
1026
 
       *  We now pass the various bootstrap parameters to the loaded
1027
 
       *  image via the argument list.
1028
 
       *
1029
 
       *  This is the official list:
1030
 
       *
1031
 
       *  arg0 = 8 (magic)
1032
 
       *  arg1 = boot flags
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)
1040
 
       *
1041
 
       *  ...in actuality, we just pass the parameters used by the kernel.
1042
 
       */
1043
 
 
1044
 
      /* call entry point */
1045
 
      unsigned long end_mark;
1046
 
 
1047
 
      if (mbi.flags & MB_INFO_AOUT_SYMS)
1048
 
        end_mark = (mbi.syms.a.addr + 4 + mbi.syms.a.tabsize + mbi.syms.a.strsize);
1049
 
      else
1050
 
        /* FIXME: it should be mbi.syms.e.size.  */
1051
 
        end_mark = 0;
1052
 
      
1053
 
      (*entry_addr) (clval, bootdev, 0, end_mark, extended_memory, saved_mem_lower);
1054
 
    }
1055
 
}