~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to grub-core/partmap/msdos.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
/* pc.c - Read PC style partition tables.  */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 2002,2004,2005,2006,2007,2008,2009  Free Software Foundation, Inc.
 
5
 *
 
6
 *  GRUB 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 3 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  GRUB 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 GRUB.  If not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <grub/partition.h>
 
21
#include <grub/msdos_partition.h>
 
22
#include <grub/disk.h>
 
23
#include <grub/mm.h>
 
24
#include <grub/misc.h>
 
25
#include <grub/dl.h>
 
26
 
 
27
static struct grub_partition_map grub_msdos_partition_map;
 
28
 
 
29
 
 
30
grub_err_t
 
31
grub_partition_msdos_iterate (grub_disk_t disk,
 
32
                              int (*hook) (grub_disk_t disk,
 
33
                                           const grub_partition_t partition))
 
34
{
 
35
  struct grub_partition p;
 
36
  struct grub_msdos_partition_mbr mbr;
 
37
  int labeln = 0;
 
38
  grub_disk_addr_t lastaddr;
 
39
  grub_disk_addr_t ext_offset;
 
40
  grub_disk_addr_t delta = 0;
 
41
 
 
42
  if (disk->partition && disk->partition->partmap == &grub_msdos_partition_map)
 
43
    {
 
44
      if (disk->partition->msdostype == GRUB_PC_PARTITION_TYPE_LINUX_MINIX)
 
45
        delta = disk->partition->start;
 
46
      else
 
47
        return grub_error (GRUB_ERR_BAD_PART_TABLE, "no embedding supported");
 
48
    }
 
49
 
 
50
  p.offset = 0;
 
51
  ext_offset = 0;
 
52
  p.number = -1;
 
53
  p.partmap = &grub_msdos_partition_map;
 
54
 
 
55
  /* Any value different than `p.offset' will satisfy the check during
 
56
     first loop.  */
 
57
  lastaddr = !p.offset;
 
58
 
 
59
  while (1)
 
60
    {
 
61
      int i;
 
62
      struct grub_msdos_partition_entry *e;
 
63
 
 
64
      /* Read the MBR.  */
 
65
      if (grub_disk_read (disk, p.offset, 0, sizeof (mbr), &mbr))
 
66
        goto finish;
 
67
 
 
68
      /* This is our loop-detection algorithm. It works the following way:
 
69
         It saves last position which was a power of two. Then it compares the
 
70
         saved value with a current one. This way it's guaranteed that the loop
 
71
         will be broken by at most third walk.
 
72
       */
 
73
      if (labeln && lastaddr == p.offset)
 
74
        return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected");
 
75
 
 
76
      labeln++;
 
77
      if ((labeln & (labeln - 1)) == 0)
 
78
        lastaddr = p.offset;
 
79
 
 
80
      /* Check if it is valid.  */
 
81
      if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
 
82
        return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
 
83
 
 
84
      for (i = 0; i < 4; i++)
 
85
        if (mbr.entries[i].flag & 0x7f)
 
86
          return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");
 
87
 
 
88
      /* Analyze DOS partitions.  */
 
89
      for (p.index = 0; p.index < 4; p.index++)
 
90
        {
 
91
          e = mbr.entries + p.index;
 
92
 
 
93
          p.start = p.offset + grub_le_to_cpu32 (e->start) - delta;
 
94
          p.len = grub_le_to_cpu32 (e->length);
 
95
          p.msdostype = e->type;
 
96
 
 
97
          grub_dprintf ("partition",
 
98
                        "partition %d: flag 0x%x, type 0x%x, start 0x%llx, len 0x%llx\n",
 
99
                        p.index, e->flag, e->type,
 
100
                        (unsigned long long) p.start,
 
101
                        (unsigned long long) p.len);
 
102
 
 
103
          /* If this is a GPT partition, this MBR is just a dummy.  */
 
104
          if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && p.index == 0)
 
105
            return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
 
106
 
 
107
          /* If this partition is a normal one, call the hook.  */
 
108
          if (! grub_msdos_partition_is_empty (e->type)
 
109
              && ! grub_msdos_partition_is_extended (e->type))
 
110
            {
 
111
              p.number++;
 
112
 
 
113
              if (hook (disk, &p))
 
114
                return grub_errno;
 
115
            }
 
116
          else if (p.number < 4)
 
117
            /* If this partition is a logical one, shouldn't increase the
 
118
               partition number.  */
 
119
            p.number++;
 
120
        }
 
121
 
 
122
      /* Find an extended partition.  */
 
123
      for (i = 0; i < 4; i++)
 
124
        {
 
125
          e = mbr.entries + i;
 
126
 
 
127
          if (grub_msdos_partition_is_extended (e->type))
 
128
            {
 
129
              p.offset = ext_offset + grub_le_to_cpu32 (e->start);
 
130
              if (! ext_offset)
 
131
                ext_offset = p.offset;
 
132
 
 
133
              break;
 
134
            }
 
135
        }
 
136
 
 
137
      /* If no extended partition, the end.  */
 
138
      if (i == 4)
 
139
        break;
 
140
    }
 
141
 
 
142
 finish:
 
143
  return grub_errno;
 
144
}
 
145
 
 
146
#ifdef GRUB_UTIL
 
147
static grub_err_t
 
148
pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
 
149
                        grub_embed_type_t embed_type,
 
150
                        grub_disk_addr_t **sectors)
 
151
{
 
152
  grub_disk_addr_t end = ~0ULL;
 
153
  struct grub_msdos_partition_mbr mbr;
 
154
  int labeln = 0;
 
155
  /* Any value different than `p.offset' will satisfy the check during
 
156
     first loop.  */
 
157
  grub_disk_addr_t lastaddr = 1;
 
158
  grub_disk_addr_t ext_offset = 0;
 
159
  grub_disk_addr_t offset = 0;
 
160
 
 
161
  if (embed_type != GRUB_EMBED_PCBIOS)
 
162
    return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
 
163
                       "PC-style partitions curently support "
 
164
                       "only PC-BIOS embedding");
 
165
 
 
166
  if (disk->partition)
 
167
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
 
168
                       "Embedding on MSDOS subpartition isn't supported");
 
169
 
 
170
  while (1)
 
171
    {
 
172
      int i;
 
173
      struct grub_msdos_partition_entry *e;
 
174
      grub_err_t err;
 
175
 
 
176
      /* Read the MBR.  */
 
177
      err = grub_disk_read (disk, offset, 0, sizeof (mbr), &mbr);
 
178
      if (err)
 
179
        return err;
 
180
 
 
181
      /* This is our loop-detection algorithm. It works the following way:
 
182
         It saves last position which was a power of two. Then it compares the
 
183
         saved value with a current one. This way it's guaranteed that the loop
 
184
         will be broken by at most third walk.
 
185
       */
 
186
      if (labeln && lastaddr == offset)
 
187
        return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected");
 
188
 
 
189
      labeln++;
 
190
      if ((labeln & (labeln - 1)) == 0)
 
191
        lastaddr = offset;
 
192
 
 
193
      /* Check if it is valid.  */
 
194
      if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE))
 
195
        return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature");
 
196
 
 
197
      for (i = 0; i < 4; i++)
 
198
        if (mbr.entries[i].flag & 0x7f)
 
199
          return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag");
 
200
 
 
201
      /* Analyze DOS partitions.  */
 
202
      for (i = 0; i < 4; i++)
 
203
        {
 
204
          e = mbr.entries + i;
 
205
 
 
206
          if (!grub_msdos_partition_is_empty (e->type)
 
207
              && end > offset + grub_le_to_cpu32 (e->start))
 
208
            end = offset + grub_le_to_cpu32 (e->start);
 
209
 
 
210
          /* If this is a GPT partition, this MBR is just a dummy.  */
 
211
          if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0)
 
212
            return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr");
 
213
        }
 
214
 
 
215
      /* Find an extended partition.  */
 
216
      for (i = 0; i < 4; i++)
 
217
        {
 
218
          e = mbr.entries + i;
 
219
 
 
220
          if (grub_msdos_partition_is_extended (e->type))
 
221
            {
 
222
              offset = ext_offset + grub_le_to_cpu32 (e->start);
 
223
              if (! ext_offset)
 
224
                ext_offset = offset;
 
225
 
 
226
              break;
 
227
            }
 
228
        }
 
229
 
 
230
      /* If no extended partition, the end.  */
 
231
      if (i == 4)
 
232
        break;
 
233
    }
 
234
 
 
235
  if (end >= *nsectors + 1)
 
236
    {
 
237
      int i;
 
238
      *nsectors = end - 1;
 
239
      *sectors = grub_malloc (*nsectors * sizeof (**sectors));
 
240
      if (!*sectors)
 
241
        return grub_errno;
 
242
      for (i = 0; i < *nsectors; i++)
 
243
        (*sectors)[i] = 1 + i;
 
244
      return GRUB_ERR_NONE;
 
245
    }
 
246
 
 
247
  if (end <= 1)
 
248
    return grub_error (GRUB_ERR_FILE_NOT_FOUND,
 
249
                       "This msdos-style partition label has no "
 
250
                       "post-MBR gap; embedding won't be possible!");
 
251
 
 
252
  if (*nsectors > 62)
 
253
    return grub_error (GRUB_ERR_OUT_OF_RANGE,
 
254
                       "Your core.img is unusually large.  "
 
255
                       "It won't fit in the embedding area.");
 
256
 
 
257
  return grub_error (GRUB_ERR_OUT_OF_RANGE,
 
258
                     "Your embedding area is unusually small.  "
 
259
                     "core.img won't fit in it.");
 
260
}
 
261
#endif
 
262
 
 
263
 
 
264
/* Partition map type.  */
 
265
static struct grub_partition_map grub_msdos_partition_map =
 
266
  {
 
267
    .name = "msdos",
 
268
    .iterate = grub_partition_msdos_iterate,
 
269
#ifdef GRUB_UTIL
 
270
    .embed = pc_partition_map_embed
 
271
#endif
 
272
  };
 
273
 
 
274
GRUB_MOD_INIT(part_msdos)
 
275
{
 
276
  grub_partition_map_register (&grub_msdos_partition_map);
 
277
}
 
278
 
 
279
GRUB_MOD_FINI(part_msdos)
 
280
{
 
281
  grub_partition_map_unregister (&grub_msdos_partition_map);
 
282
}