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

« back to all changes in this revision

Viewing changes to 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/cpu/bsd.h>
3
 
#include <grub/mm.h>
4
 
#include <grub/elf.h>
5
 
#include <grub/misc.h>
6
 
#include <grub/i386/loader.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 (PTR_TO_UINT32 (where) + size > grub_os_area_addr + grub_os_area_size)
14
 
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
15
 
                       "not enough memory for the module");
16
 
  if (grub_file_seek (file, off) == (grub_off_t) -1)
17
 
    return grub_errno;
18
 
  if (grub_file_read (file, where, size)
19
 
      != (grub_ssize_t) size)
20
 
    {
21
 
      if (grub_errno)
22
 
        return grub_errno;
23
 
      else
24
 
        return grub_error (GRUB_ERR_BAD_OS, "file is truncated");
25
 
    }
26
 
  return GRUB_ERR_NONE;
27
 
}
28
 
 
29
 
static inline grub_err_t
30
 
read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr)
31
 
{
32
 
 if (grub_file_seek (file, 0) == (grub_off_t) -1)
33
 
    return grub_errno;
34
 
 
35
 
  if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
36
 
    {
37
 
      if (grub_errno)
38
 
        return grub_errno;
39
 
      else
40
 
        return grub_error (GRUB_ERR_BAD_OS, "file is too short");
41
 
    }
42
 
 
43
 
  if (e->e_ident[EI_MAG0] != ELFMAG0
44
 
      || e->e_ident[EI_MAG1] != ELFMAG1
45
 
      || e->e_ident[EI_MAG2] != ELFMAG2
46
 
      || e->e_ident[EI_MAG3] != ELFMAG3
47
 
      || e->e_ident[EI_VERSION] != EV_CURRENT
48
 
      || e->e_version != EV_CURRENT)
49
 
    return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic");
50
 
 
51
 
  if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
52
 
    return grub_error (GRUB_ERR_BAD_OS, "invalid arch dependent ELF magic");
53
 
 
54
 
  *shdr = grub_malloc (e->e_shnum * e->e_shentsize);
55
 
  if (! *shdr)
56
 
    return grub_errno;
57
 
 
58
 
  if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
59
 
    return grub_errno;
60
 
 
61
 
  if (grub_file_read (file, *shdr, e->e_shnum * e->e_shentsize)
62
 
      != e->e_shnum * e->e_shentsize)
63
 
    {
64
 
      if (grub_errno)
65
 
        return grub_errno;
66
 
      else
67
 
        return grub_error (GRUB_ERR_BAD_OS, "file is truncated");
68
 
    }
69
 
 
70
 
  return GRUB_ERR_NONE;
71
 
}
72
 
 
73
 
/* On i386 FreeBSD uses "elf module" approarch for 32-bit variant
74
 
   and "elf obj module" for 64-bit variant. However it may differ on other
75
 
   platforms. So I keep both versions.  */
76
 
#if OBJSYM
77
 
grub_err_t
78
 
SUFFIX (grub_freebsd_load_elfmodule_obj) (grub_file_t file, int argc,
79
 
                                          char *argv[], grub_addr_t *kern_end)
80
 
{
81
 
  Elf_Ehdr e;
82
 
  Elf_Shdr *s;
83
 
  char *shdr = 0;
84
 
  grub_addr_t curload, module;
85
 
  grub_err_t err;
86
 
 
87
 
  err = read_headers (file, &e, &shdr);
88
 
  if (err)
89
 
    return err;
90
 
 
91
 
  curload = module = ALIGN_PAGE (*kern_end);
92
 
 
93
 
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
94
 
                                                + e.e_shnum * e.e_shentsize);
95
 
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
96
 
    {
97
 
      if (s->sh_size == 0)
98
 
        continue;
99
 
 
100
 
      if (s->sh_addralign)
101
 
        curload = ALIGN_UP (curload, s->sh_addralign);
102
 
      s->sh_addr = curload;
103
 
 
104
 
      grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n",
105
 
                    (unsigned) curload, (int) s->sh_size,
106
 
                    (int) s->sh_addralign);
107
 
 
108
 
      switch (s->sh_type)
109
 
        {
110
 
        default:
111
 
        case SHT_PROGBITS:
112
 
          err = load (file, UINT_TO_PTR (curload), s->sh_offset, s->sh_size);
113
 
          if (err)
114
 
            return err;
115
 
          break;
116
 
        case SHT_NOBITS:
117
 
          if (curload + s->sh_size > grub_os_area_addr + grub_os_area_size)
118
 
            return grub_error (GRUB_ERR_OUT_OF_RANGE,
119
 
                               "not enough memory for the module");
120
 
          grub_memset (UINT_TO_PTR (curload), 0, s->sh_size);
121
 
          break;
122
 
        }
123
 
      curload += s->sh_size;
124
 
    }
125
 
 
126
 
  *kern_end = ALIGN_PAGE (curload);
127
 
 
128
 
  err = grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE_OBJ,
129
 
                                      argc - 1, argv + 1, module,
130
 
                                      curload - module);
131
 
  if (! err)
132
 
    err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA
133
 
                                 | FREEBSD_MODINFOMD_ELFHDR,
134
 
                                 &e, sizeof (e));
135
 
  if (! err)
136
 
    err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA
137
 
                                 | FREEBSD_MODINFOMD_SHDR,
138
 
                                 shdr, e.e_shnum * e.e_shentsize);
139
 
 
140
 
  return err;
141
 
}
142
 
 
143
 
#else
144
 
 
145
 
grub_err_t
146
 
SUFFIX (grub_freebsd_load_elfmodule) (grub_file_t file, int argc, char *argv[],
147
 
                                      grub_addr_t *kern_end)
148
 
{
149
 
  Elf_Ehdr e;
150
 
  Elf_Shdr *s;
151
 
  char *shdr = 0;
152
 
  grub_addr_t curload, module;
153
 
  grub_err_t err;
154
 
 
155
 
  err = read_headers (file, &e, &shdr);
156
 
  if (err)
157
 
    return err;
158
 
 
159
 
  curload = module = ALIGN_PAGE (*kern_end);
160
 
 
161
 
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
162
 
                                                + e.e_shnum * e.e_shentsize);
163
 
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
164
 
    {
165
 
      if (s->sh_size == 0)
166
 
        continue;
167
 
 
168
 
      if (! (s->sh_flags & SHF_ALLOC))
169
 
        continue;
170
 
 
171
 
      grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n",
172
 
                    (unsigned) curload, (int) s->sh_size,
173
 
                    (int) s->sh_addralign);
174
 
 
175
 
      switch (s->sh_type)
176
 
        {
177
 
        default:
178
 
        case SHT_PROGBITS:
179
 
          err = load (file, UINT_TO_PTR (module + s->sh_addr),
180
 
                      s->sh_offset, s->sh_size);
181
 
          if (err)
182
 
            return err;
183
 
          break;
184
 
        case SHT_NOBITS:
185
 
          if (module + s->sh_addr + s->sh_size
186
 
              > grub_os_area_addr + grub_os_area_size)
187
 
            return grub_error (GRUB_ERR_OUT_OF_RANGE,
188
 
                               "not enough memory for the module");
189
 
          grub_memset (UINT_TO_PTR (module + s->sh_addr), 0, s->sh_size);
190
 
          break;
191
 
        }
192
 
      if (curload < module + s->sh_addr + s->sh_size)
193
 
        curload = module + s->sh_addr + s->sh_size;
194
 
    }
195
 
 
196
 
  load (file, UINT_TO_PTR (module), 0, sizeof (e));
197
 
  if (curload < module + sizeof (e))
198
 
    curload = module + sizeof (e);
199
 
 
200
 
  load (file, UINT_TO_PTR (curload), e.e_shoff,
201
 
        e.e_shnum * e.e_shentsize);
202
 
  e.e_shoff = curload - module;
203
 
  curload +=  e.e_shnum * e.e_shentsize;
204
 
 
205
 
  load (file, UINT_TO_PTR (curload), e.e_phoff,
206
 
        e.e_phnum * e.e_phentsize);
207
 
  e.e_phoff = curload - module;
208
 
  curload +=  e.e_phnum * e.e_phentsize;
209
 
 
210
 
  *kern_end = curload;
211
 
 
212
 
  grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE,
213
 
                                argc - 1, argv + 1, module,
214
 
                                curload - module);
215
 
  return SUFFIX (grub_freebsd_load_elf_meta) (file, kern_end);
216
 
}
217
 
 
218
 
#endif
219
 
 
220
 
grub_err_t
221
 
SUFFIX (grub_freebsd_load_elf_meta) (grub_file_t file, grub_addr_t *kern_end)
222
 
{
223
 
  grub_err_t err;
224
 
  Elf_Ehdr e;
225
 
  Elf_Shdr *s;
226
 
  char *shdr = 0;
227
 
  unsigned symoff, stroff, symsize, strsize;
228
 
  grub_addr_t curload;
229
 
  grub_freebsd_addr_t symstart, symend, symentsize, dynamic;
230
 
  Elf_Sym *sym;
231
 
  const char *str;
232
 
  unsigned i;
233
 
 
234
 
  err = read_headers (file, &e, &shdr);
235
 
  if (err)
236
 
    return err;
237
 
 
238
 
  err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
239
 
                               FREEBSD_MODINFOMD_ELFHDR, &e,
240
 
                               sizeof (e));
241
 
  if (err)
242
 
    return err;
243
 
 
244
 
  for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
245
 
                                                + e.e_shnum * e.e_shentsize);
246
 
       s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
247
 
      if (s->sh_type == SHT_SYMTAB)
248
 
        break;
249
 
  if (s >= (Elf_Shdr *) ((char *) shdr
250
 
                        + e.e_shnum * e.e_shentsize))
251
 
    return grub_error (GRUB_ERR_BAD_OS, "no symbol table");
252
 
  symoff = s->sh_offset;
253
 
  symsize = s->sh_size;
254
 
  symentsize = s->sh_entsize;
255
 
  s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
256
 
  stroff = s->sh_offset;
257
 
  strsize = s->sh_size;
258
 
 
259
 
  if (*kern_end + 4 * sizeof (grub_freebsd_addr_t) + symsize + strsize
260
 
      > grub_os_area_addr + grub_os_area_size)
261
 
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
262
 
                       "not enough memory for kernel symbols");
263
 
 
264
 
  symstart = curload = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
265
 
  *((grub_freebsd_addr_t *) UINT_TO_PTR (curload)) = symsize;
266
 
  curload += sizeof (grub_freebsd_addr_t);
267
 
  if (grub_file_seek (file, symoff) == (grub_off_t) -1)
268
 
    return grub_errno;
269
 
  sym = (Elf_Sym *) UINT_TO_PTR (curload);
270
 
  if (grub_file_read (file, UINT_TO_PTR (curload), symsize) !=
271
 
      (grub_ssize_t) symsize)
272
 
    {
273
 
      if (! grub_errno)
274
 
        return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
275
 
      return grub_errno;
276
 
    }
277
 
  curload += symsize;
278
 
 
279
 
  *((grub_freebsd_addr_t *) UINT_TO_PTR (curload)) = strsize;
280
 
  curload += sizeof (grub_freebsd_addr_t);
281
 
  if (grub_file_seek (file, stroff) == (grub_off_t) -1)
282
 
    return grub_errno;
283
 
  str = (char *) UINT_TO_PTR (curload);
284
 
  if (grub_file_read (file, UINT_TO_PTR (curload), strsize)
285
 
      != (grub_ssize_t) strsize)
286
 
    {
287
 
      if (! grub_errno)
288
 
        return grub_error (GRUB_ERR_BAD_OS, "invalid ELF");
289
 
      return grub_errno;
290
 
    }
291
 
  curload += strsize;
292
 
  curload = ALIGN_UP (curload, sizeof (grub_freebsd_addr_t));
293
 
  symend = curload;
294
 
 
295
 
  for (i = 0;
296
 
       i * symentsize < symsize;
297
 
       i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
298
 
    {
299
 
      const char *name = str + sym->st_name;
300
 
      if (grub_strcmp (name, "_DYNAMIC") == 0)
301
 
        break;
302
 
    }
303
 
 
304
 
  if (i * symentsize < symsize)
305
 
    {
306
 
      dynamic = sym->st_value;
307
 
      grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic);
308
 
      err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
309
 
                                   FREEBSD_MODINFOMD_DYNAMIC, &dynamic,
310
 
                                   sizeof (dynamic));
311
 
      if (err)
312
 
        return err;
313
 
    }
314
 
 
315
 
  err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
316
 
                               FREEBSD_MODINFOMD_SSYM, &symstart,
317
 
                               sizeof (symstart));
318
 
  if (err)
319
 
    return err;
320
 
 
321
 
  err = grub_freebsd_add_meta (FREEBSD_MODINFO_METADATA |
322
 
                               FREEBSD_MODINFOMD_ESYM, &symend,
323
 
                               sizeof (symend));
324
 
  if (err)
325
 
    return err;
326
 
  *kern_end = ALIGN_PAGE (curload);
327
 
 
328
 
  return GRUB_ERR_NONE;
329
 
}