~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/loader/i386/bsdXX.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <grub/loader.h>
 
2
#include <grub/i386/bsd.h>
 
3
#include <grub/mm.h>
 
4
#include <grub/elf.h>
 
5
#include <grub/misc.h>
 
6
#include <grub/i386/relocator.h>
 
7
 
 
8
#define ALIGN_PAGE(a)   ALIGN_UP (a, 4096)
 
9
 
 
10
static inline grub_err_t
 
11
load (grub_file_t file, void *where, grub_off_t off, grub_size_t size)
 
12
{
 
13
  if (grub_file_seek (file, off) == (grub_off_t) -1)
 
14
    return grub_errno;
 
15
  if (grub_file_read (file, where, size) != (grub_ssize_t) size)
 
16
    {
 
17
      if (grub_errno)
 
18
        return grub_errno;
 
19
      else
 
20
        return grub_error (GRUB_ERR_BAD_OS, "file is truncated");
 
21
    }
 
22
  return GRUB_ERR_NONE;
 
23
}
 
24
 
 
25
static inline grub_err_t
 
26
read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr)
 
27
{
 
28
 if (grub_file_seek (file, 0) == (grub_off_t) -1)
 
29
    return grub_errno;
 
30
 
 
31
  if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
 
32
    {
 
33
      if (grub_errno)
 
34
        return grub_errno;
 
35
      else
 
36
        return grub_error (GRUB_ERR_BAD_OS, "file is too short");
 
37
    }
 
38
 
 
39
  if (e->e_ident[EI_MAG0] != ELFMAG0
 
40
      || e->e_ident[EI_MAG1] != ELFMAG1
 
41
      || e->e_ident[EI_MAG2] != ELFMAG2
 
42
      || e->e_ident[EI_MAG3] != ELFMAG3
 
43
      || e->e_ident[EI_VERSION] != EV_CURRENT
 
44
      || e->e_version != EV_CURRENT)
 
45
    return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic");
 
46
 
 
47
  if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
 
48
    return grub_error (GRUB_ERR_BAD_OS, "invalid arch dependent ELF magic");
 
49
 
 
50
  *shdr = grub_malloc (e->e_shnum * e->e_shentsize);
 
51
  if (! *shdr)
 
52
    return grub_errno;
 
53
 
 
54
  if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
 
55
    return grub_errno;
 
56
 
 
57
  if (grub_file_read (file, *shdr, e->e_shnum * e->e_shentsize)
 
58
      != e->e_shnum * e->e_shentsize)
 
59
    {
 
60
      if (grub_errno)
 
61
        return grub_errno;
 
62
      else
 
63
        return grub_error (GRUB_ERR_BAD_OS, "file is truncated");
 
64
    }
 
65
 
 
66
  return GRUB_ERR_NONE;
 
67
}
 
68
 
 
69
/* On i386 FreeBSD uses "elf module" approarch for 32-bit variant
 
70
   and "elf obj module" for 64-bit variant. However it may differ on other
 
71
   platforms. So I keep both versions.  */
 
72
#if OBJSYM
 
73
grub_err_t
 
74
SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator,
 
75
                                          grub_file_t file, int argc,
 
76
                                          char *argv[], grub_addr_t *kern_end)
 
77
{
 
78
  Elf_Ehdr e;
 
79
  Elf_Shdr *s;
 
80
  char *shdr = 0;
 
81
  grub_addr_t curload, module;
 
82
  grub_err_t err;
 
83
  grub_size_t chunk_size = 0;
 
84
  void *chunk_src;
 
85
 
 
86
  err = read_headers (file, &e, &shdr);
 
87
  if (err)
 
88
    return err;
 
89
 
 
90
  curload = module = ALIGN_PAGE (*kern_end);
 
91
 
 
92
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
 
93
                                                + e.e_shnum * e.e_shentsize);
 
94
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
95
    {
 
96
      if (s->sh_size == 0)
 
97
        continue;
 
98
 
 
99
      if (s->sh_addralign)
 
100
        chunk_size = ALIGN_UP (chunk_size + *kern_end, s->sh_addralign)
 
101
          - *kern_end;
 
102
 
 
103
      chunk_size += s->sh_size;
 
104
    }
 
105
 
 
106
  {
 
107
    grub_relocator_chunk_t ch;
 
108
    err = grub_relocator_alloc_chunk_addr (relocator, &ch,
 
109
                                           module, chunk_size);
 
110
    if (err)
 
111
      return err;
 
112
    chunk_src = get_virtual_current_address (ch);
 
113
  }
 
114
 
 
115
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
 
116
                                                + e.e_shnum * e.e_shentsize);
 
117
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
118
    {
 
119
      if (s->sh_size == 0)
 
120
        continue;
 
121
 
 
122
      if (s->sh_addralign)
 
123
        curload = ALIGN_UP (curload, s->sh_addralign);
 
124
      s->sh_addr = curload;
 
125
 
 
126
      grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n",
 
127
                    (unsigned) curload, (int) s->sh_size,
 
128
                    (int) s->sh_addralign);
 
129
 
 
130
      switch (s->sh_type)
 
131
        {
 
132
        default:
 
133
        case SHT_PROGBITS:
 
134
          err = load (file, (grub_uint8_t *) chunk_src + curload - *kern_end,
 
135
                      s->sh_offset, s->sh_size);
 
136
          if (err)
 
137
            return err;
 
138
          break;
 
139
        case SHT_NOBITS:
 
140
          grub_memset ((grub_uint8_t *) chunk_src + curload - *kern_end, 0,
 
141
                       s->sh_size);
 
142
          break;
 
143
        }
 
144
      curload += s->sh_size;
 
145
    }
 
146
 
 
147
  *kern_end = ALIGN_PAGE (curload);
 
148
 
 
149
  err = grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE_OBJ,
 
150
                                      argc - 1, argv + 1, module,
 
151
                                      curload - module);
 
152
  if (! err)
 
153
    err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA 
 
154
                             | FREEBSD_MODINFOMD_ELFHDR,
 
155
                             &e, sizeof (e));
 
156
  if (! err)
 
157
    err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
 
158
                             | FREEBSD_MODINFOMD_SHDR,
 
159
                             shdr, e.e_shnum * e.e_shentsize);
 
160
 
 
161
  return err;
 
162
}
 
163
 
 
164
#else
 
165
 
 
166
grub_err_t
 
167
SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
 
168
                                      grub_file_t file, int argc, char *argv[],
 
169
                                      grub_addr_t *kern_end)
 
170
{
 
171
  Elf_Ehdr e;
 
172
  Elf_Shdr *s;
 
173
  char *shdr = 0;
 
174
  grub_addr_t curload, module;
 
175
  grub_err_t err;
 
176
  grub_size_t chunk_size = 0;
 
177
  void *chunk_src;
 
178
 
 
179
  err = read_headers (file, &e, &shdr);
 
180
  if (err)
 
181
    return err;
 
182
 
 
183
  curload = module = ALIGN_PAGE (*kern_end);
 
184
 
 
185
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
 
186
                                                + e.e_shnum * e.e_shentsize);
 
187
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
188
    {
 
189
      if (s->sh_size == 0)
 
190
        continue;
 
191
 
 
192
      if (! (s->sh_flags & SHF_ALLOC))
 
193
        continue;
 
194
      if (chunk_size < s->sh_addr + s->sh_size)
 
195
        chunk_size = s->sh_addr + s->sh_size;
 
196
    }
 
197
 
 
198
  {
 
199
    grub_relocator_chunk_t ch;
 
200
 
 
201
    err = grub_relocator_alloc_chunk_addr (relocator, &ch,
 
202
                                           module, chunk_size);
 
203
    if (err)
 
204
      return err;
 
205
 
 
206
    chunk_src = get_virtual_current_address (ch);
 
207
  }
 
208
 
 
209
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
 
210
                                                + e.e_shnum * e.e_shentsize);
 
211
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
212
    {
 
213
      if (s->sh_size == 0)
 
214
        continue;
 
215
 
 
216
      if (! (s->sh_flags & SHF_ALLOC))
 
217
        continue;
 
218
 
 
219
      grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n",
 
220
                    (unsigned) curload, (int) s->sh_size,
 
221
                    (int) s->sh_addralign);
 
222
 
 
223
      switch (s->sh_type)
 
224
        {
 
225
        default:
 
226
        case SHT_PROGBITS:
 
227
          err = load (file, (grub_uint8_t *) chunk_src + module
 
228
                      + s->sh_addr - *kern_end,
 
229
                      s->sh_offset, s->sh_size);
 
230
          if (err)
 
231
            return err;
 
232
          break;
 
233
        case SHT_NOBITS:
 
234
          grub_memset ((grub_uint8_t *) chunk_src + module
 
235
                      + s->sh_addr - *kern_end, 0, s->sh_size);
 
236
          break;
 
237
        }
 
238
      if (curload < module + s->sh_addr + s->sh_size)
 
239
        curload = module + s->sh_addr + s->sh_size;
 
240
    }
 
241
 
 
242
  load (file, UINT_TO_PTR (module), 0, sizeof (e));
 
243
  if (curload < module + sizeof (e))
 
244
    curload = module + sizeof (e);
 
245
 
 
246
  load (file, UINT_TO_PTR (curload), e.e_shoff,
 
247
        e.e_shnum * e.e_shentsize);
 
248
  e.e_shoff = curload - module;
 
249
  curload +=  e.e_shnum * e.e_shentsize;
 
250
 
 
251
  load (file, UINT_TO_PTR (curload), e.e_phoff,
 
252
        e.e_phnum * e.e_phentsize);
 
253
  e.e_phoff = curload - module;
 
254
  curload +=  e.e_phnum * e.e_phentsize;
 
255
 
 
256
  *kern_end = curload;
 
257
 
 
258
  grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE,
 
259
                                argc - 1, argv + 1, module,
 
260
                                curload - module);
 
261
  return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, kern_end);
 
262
}
 
263
 
 
264
#endif
 
265
 
 
266
grub_err_t
 
267
SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
 
268
                                     grub_file_t file, grub_addr_t *kern_end)
 
269
{
 
270
  grub_err_t err;
 
271
  Elf_Ehdr e;
 
272
  Elf_Shdr *s;
 
273
  char *shdr = 0;
 
274
  unsigned symoff, stroff, symsize, strsize;
 
275
  grub_freebsd_addr_t symstart, symend, symentsize, dynamic;
 
276
  Elf_Sym *sym;
 
277
  void *sym_chunk;
 
278
  grub_uint8_t *curload;
 
279
  grub_freebsd_addr_t symtarget;
 
280
  const char *str;
 
281
  unsigned i;
 
282
  grub_size_t chunk_size;
 
283
 
 
284
  err = read_headers (file, &e, &shdr);
 
285
  if (err)
 
286
    return err;
 
287
 
 
288
  err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
 
289
                           FREEBSD_MODINFOMD_ELFHDR, &e,
 
290
                           sizeof (e));
 
291
  if (err)
 
292
    return err;
 
293
 
 
294
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
 
295
                                                + e.e_shnum * e.e_shentsize);
 
296
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
297
      if (s->sh_type == SHT_SYMTAB)
 
298
        break;
 
299
  if (s >= (Elf_Shdr *) ((char *) shdr
 
300
                        + e.e_shnum * e.e_shentsize))
 
301
    return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
 
302
  symoff = s->sh_offset;
 
303
  symsize = s->sh_size;
 
304
  symentsize = s->sh_entsize;
 
305
  s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
 
306
  stroff = s->sh_offset;
 
307
  strsize = s->sh_size;
 
308
 
 
309
  chunk_size = ALIGN_UP (symsize + strsize, sizeof (grub_freebsd_addr_t))
 
310
    + 2 * sizeof (grub_freebsd_addr_t);
 
311
 
 
312
  symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
 
313
 
 
314
  {
 
315
    grub_relocator_chunk_t ch;
 
316
    err = grub_relocator_alloc_chunk_addr (relocator, &ch,
 
317
                                           symtarget, chunk_size);
 
318
    if (err)
 
319
      return err;
 
320
    sym_chunk = get_virtual_current_address (ch);
 
321
  }
 
322
 
 
323
  symstart = symtarget;
 
324
  symend = symstart + chunk_size;
 
325
 
 
326
  curload = sym_chunk;
 
327
  *((grub_freebsd_addr_t *) curload) = symsize;
 
328
  curload += sizeof (grub_freebsd_addr_t);
 
329
 
 
330
  if (grub_file_seek (file, symoff) == (grub_off_t) -1)
 
331
    return grub_errno;
 
332
  sym = (Elf_Sym *) curload;
 
333
  if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
 
334
    {
 
335
      if (! grub_errno)
 
336
        return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
 
337
      return grub_errno;
 
338
    }
 
339
  curload += symsize;
 
340
 
 
341
  *((grub_freebsd_addr_t *) curload) = strsize;
 
342
  curload += sizeof (grub_freebsd_addr_t);
 
343
  if (grub_file_seek (file, stroff) == (grub_off_t) -1)
 
344
    return grub_errno;
 
345
  str = (char *) curload;
 
346
  if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
 
347
    {
 
348
      if (! grub_errno)
 
349
        return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
 
350
      return grub_errno;
 
351
    }
 
352
 
 
353
  for (i = 0;
 
354
       i * symentsize < symsize;
 
355
       i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
 
356
    {
 
357
      const char *name = str + sym->st_name;
 
358
      if (grub_strcmp (name, "_DYNAMIC") == 0)
 
359
        break;
 
360
    }
 
361
 
 
362
  if (i * symentsize < symsize)
 
363
    {
 
364
      dynamic = sym->st_value;
 
365
      grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic);
 
366
      err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
 
367
                               FREEBSD_MODINFOMD_DYNAMIC, &dynamic,
 
368
                               sizeof (dynamic));
 
369
      if (err)
 
370
        return err;
 
371
    }
 
372
 
 
373
  err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
 
374
                           FREEBSD_MODINFOMD_SSYM, &symstart,
 
375
                           sizeof (symstart));
 
376
  if (err)
 
377
    return err;
 
378
 
 
379
  err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
 
380
                           FREEBSD_MODINFOMD_ESYM, &symend,
 
381
                           sizeof (symend));
 
382
  if (err)
 
383
    return err;
 
384
 
 
385
  *kern_end = ALIGN_PAGE (symend);
 
386
 
 
387
  return GRUB_ERR_NONE;
 
388
}
 
389
 
 
390
grub_err_t
 
391
SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
 
392
                                    grub_file_t file, grub_addr_t *kern_end)
 
393
{
 
394
  grub_err_t err;
 
395
  Elf_Ehdr e;
 
396
  Elf_Shdr *s, *symsh, *strsh;
 
397
  char *shdr;
 
398
  unsigned symsize, strsize;
 
399
  void *sym_chunk;
 
400
  grub_uint8_t *curload;
 
401
  grub_size_t chunk_size;
 
402
  Elf_Ehdr *e2;
 
403
  struct grub_netbsd_btinfo_symtab symtab;
 
404
  grub_addr_t symtarget;
 
405
 
 
406
  err = read_headers (file, &e, &shdr);
 
407
  if (err)
 
408
    return err;
 
409
 
 
410
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
 
411
                                                + e.e_shnum * e.e_shentsize);
 
412
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
413
      if (s->sh_type == SHT_SYMTAB)
 
414
        break;
 
415
  if (s >= (Elf_Shdr *) ((char *) shdr
 
416
                        + e.e_shnum * e.e_shentsize))
 
417
    return GRUB_ERR_NONE;
 
418
  symsize = s->sh_size;
 
419
  symsh = s;
 
420
  s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
 
421
  strsize = s->sh_size;
 
422
  strsh = s;
 
423
 
 
424
  chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
 
425
    + ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
 
426
    + sizeof (e) + e.e_shnum * e.e_shentsize;
 
427
 
 
428
  symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
 
429
  {
 
430
    grub_relocator_chunk_t ch;
 
431
    err = grub_relocator_alloc_chunk_addr (relocator, &ch,
 
432
                                           symtarget, chunk_size);
 
433
    if (err)
 
434
      return err;
 
435
    sym_chunk = get_virtual_current_address (ch);
 
436
  }
 
437
 
 
438
  symtab.nsyms = 1;
 
439
  symtab.ssyms = symtarget;
 
440
  symtab.esyms = symtarget + chunk_size;
 
441
 
 
442
  curload = sym_chunk;
 
443
  
 
444
  e2 = (Elf_Ehdr *) curload;
 
445
  grub_memcpy (curload, &e, sizeof (e));
 
446
  e2->e_phoff = 0;
 
447
  e2->e_phnum = 0;
 
448
  e2->e_phentsize = 0;
 
449
  e2->e_shstrndx = 0;
 
450
  e2->e_shoff = sizeof (e);
 
451
 
 
452
  curload += sizeof (e);
 
453
 
 
454
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
 
455
                                                + e.e_shnum * e.e_shentsize);
 
456
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
457
    {
 
458
      Elf_Shdr *s2;
 
459
      s2 = (Elf_Shdr *) curload;
 
460
      grub_memcpy (curload, s, e.e_shentsize);
 
461
      if (s == symsh)
 
462
        s2->sh_offset = sizeof (e) + e.e_shnum * e.e_shentsize;
 
463
      else if (s == strsh)
 
464
        s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
 
465
          + sizeof (e) + e.e_shnum * e.e_shentsize;
 
466
      else
 
467
        s2->sh_offset = 0;
 
468
      s2->sh_addr = s2->sh_offset;
 
469
      curload += e.e_shentsize;
 
470
    }
 
471
 
 
472
  if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1)
 
473
    return grub_errno;
 
474
  if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
 
475
    {
 
476
      if (! grub_errno)
 
477
        return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
 
478
      return grub_errno;
 
479
    }
 
480
  curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t));
 
481
 
 
482
  if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1)
 
483
    return grub_errno;
 
484
  if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
 
485
    {
 
486
      if (! grub_errno)
 
487
        return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
 
488
      return grub_errno;
 
489
    }
 
490
 
 
491
  err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB, 
 
492
                           &symtab,
 
493
                           sizeof (symtab));
 
494
  if (err)
 
495
    return err;
 
496
 
 
497
  *kern_end = ALIGN_PAGE (symtarget + chunk_size);
 
498
 
 
499
  return GRUB_ERR_NONE;
 
500
}
 
501
 
 
502
grub_err_t
 
503
SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
 
504
                                   grub_addr_t kern_start,
 
505
                                   void *kern_chunk_src,
 
506
                                   struct grub_openbsd_ramdisk_descriptor *desc)
 
507
{
 
508
  unsigned symoff, stroff, symsize, strsize, symentsize;
 
509
 
 
510
  {
 
511
    grub_err_t err;
 
512
    Elf_Ehdr e;
 
513
    Elf_Shdr *s;
 
514
    char *shdr;
 
515
    
 
516
    err = read_headers (file, &e, &shdr);
 
517
    if (err)
 
518
      return err;
 
519
 
 
520
    for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
 
521
                                                  + e.e_shnum * e.e_shentsize);
 
522
         s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
 
523
      if (s->sh_type == SHT_SYMTAB)
 
524
        break;
 
525
    if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize))
 
526
      {
 
527
        grub_free (shdr);
 
528
        return GRUB_ERR_NONE;
 
529
      }
 
530
 
 
531
    symsize = s->sh_size;
 
532
    symentsize = s->sh_entsize;
 
533
    symoff = s->sh_offset;
 
534
    
 
535
    s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
 
536
    stroff = s->sh_offset;
 
537
    strsize = s->sh_size;
 
538
    grub_free (shdr);
 
539
  }
 
540
  {
 
541
    Elf_Sym *syms, *sym, *imagesym = NULL, *sizesym = NULL;
 
542
    unsigned i;
 
543
    char *strs;
 
544
 
 
545
    syms = grub_malloc (symsize);
 
546
    if (!syms)
 
547
      return grub_errno;
 
548
 
 
549
    if (grub_file_seek (file, symoff) == (grub_off_t) -1)
 
550
      {
 
551
        grub_free (syms);
 
552
        return grub_errno;
 
553
      }
 
554
    if (grub_file_read (file, syms, symsize) != (grub_ssize_t) symsize)
 
555
      {
 
556
        grub_free (syms);
 
557
        if (! grub_errno)
 
558
          return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
 
559
        return grub_errno;
 
560
      }
 
561
 
 
562
    strs = grub_malloc (strsize);
 
563
    if (!strs)
 
564
      {
 
565
        grub_free (syms);
 
566
        return grub_errno;
 
567
      }
 
568
 
 
569
    if (grub_file_seek (file, stroff) == (grub_off_t) -1)
 
570
      return grub_errno;
 
571
    if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize)
 
572
      {
 
573
        grub_free (syms);
 
574
        grub_free (strs);
 
575
        if (! grub_errno)
 
576
          return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
 
577
        return grub_errno;
 
578
      }
 
579
 
 
580
    for (i = 0, sym = syms; i < symsize / symentsize;
 
581
       i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
 
582
      {
 
583
        if (ELF_ST_TYPE (sym->st_info) != STT_OBJECT)
 
584
          continue;
 
585
        if (!sym->st_name)
 
586
          continue;
 
587
        if (grub_strcmp (strs + sym->st_name, "rd_root_image") == 0)
 
588
          imagesym = sym;
 
589
        if (grub_strcmp (strs + sym->st_name, "rd_root_size") == 0)
 
590
          sizesym = sym;
 
591
        if (imagesym && sizesym)
 
592
          break;
 
593
      }
 
594
    if (!imagesym || !sizesym)
 
595
      {
 
596
        grub_free (syms);
 
597
        grub_free (strs);
 
598
        return GRUB_ERR_NONE;
 
599
      }
 
600
    if (sizeof (*desc->size) != sizesym->st_size)
 
601
      {
 
602
        grub_free (syms);
 
603
        grub_free (strs);
 
604
        return grub_error (GRUB_ERR_BAD_OS, "unexpected size of rd_root_size");
 
605
      }
 
606
    desc->max_size = imagesym->st_size;
 
607
    desc->target = (imagesym->st_value & 0xFFFFFF) - kern_start
 
608
      + (grub_uint8_t *) kern_chunk_src;
 
609
    desc->size = (grub_uint32_t *) ((sizesym->st_value & 0xFFFFFF) - kern_start
 
610
                                    + (grub_uint8_t *) kern_chunk_src);
 
611
    grub_free (syms);
 
612
    grub_free (strs);
 
613
 
 
614
    return GRUB_ERR_NONE;
 
615
  }
 
616
}