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

« back to all changes in this revision

Viewing changes to grub-core/disk/ieee1275/ofdisk.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
/* ofdisk.c - Open Firmware disk access.  */
 
2
/*
 
3
 *  GRUB  --  GRand Unified Bootloader
 
4
 *  Copyright (C) 2004,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/misc.h>
 
21
#include <grub/disk.h>
 
22
#include <grub/mm.h>
 
23
#include <grub/ieee1275/ieee1275.h>
 
24
#include <grub/ieee1275/ofdisk.h>
 
25
 
 
26
static char *last_devpath;
 
27
static grub_ieee1275_ihandle_t last_ihandle;
 
28
 
 
29
struct ofdisk_hash_ent
 
30
{
 
31
  char *devpath;
 
32
  /* Pointer to shortest available name on nodes representing canonical names,
 
33
     otherwise NULL.  */
 
34
  const char *shortest;
 
35
  struct ofdisk_hash_ent *next;
 
36
};
 
37
 
 
38
#define OFDISK_HASH_SZ  8
 
39
static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ];
 
40
 
 
41
static int
 
42
ofdisk_hash_fn (const char *devpath)
 
43
{
 
44
  int hash = 0;
 
45
  while (*devpath)
 
46
    hash ^= *devpath++;
 
47
  return (hash & (OFDISK_HASH_SZ - 1));
 
48
}
 
49
 
 
50
static struct ofdisk_hash_ent *
 
51
ofdisk_hash_find (const char *devpath)
 
52
{
 
53
  struct ofdisk_hash_ent *p = ofdisk_hash[ofdisk_hash_fn(devpath)];
 
54
 
 
55
  while (p)
 
56
    {
 
57
      if (!grub_strcmp (p->devpath, devpath))
 
58
        break;
 
59
      p = p->next;
 
60
    }
 
61
  return p;
 
62
}
 
63
 
 
64
static struct ofdisk_hash_ent *
 
65
ofdisk_hash_add (char *devpath)
 
66
{
 
67
  struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
 
68
  struct ofdisk_hash_ent *p, *pcan;
 
69
  char *curcan;
 
70
 
 
71
  p = grub_malloc(sizeof (*p));
 
72
  if (!p)
 
73
    return NULL;
 
74
 
 
75
  p->devpath = devpath;
 
76
  p->next = *head;
 
77
  p->shortest = 0;
 
78
  *head = p;
 
79
 
 
80
  curcan = grub_ieee1275_canonicalise_devname (devpath);
 
81
  if (!curcan)
 
82
    {
 
83
      grub_errno = GRUB_ERR_NONE;
 
84
      return p;
 
85
    }
 
86
 
 
87
  pcan = ofdisk_hash_find (curcan);
 
88
  if (!pcan)
 
89
    pcan = ofdisk_hash_add (curcan);
 
90
  else
 
91
    grub_free (curcan);
 
92
 
 
93
  if (!pcan)
 
94
    grub_errno = GRUB_ERR_NONE;
 
95
  else
 
96
    {
 
97
      if (!pcan->shortest
 
98
          || grub_strlen (pcan->shortest) > grub_strlen (devpath))
 
99
        pcan->shortest = devpath;
 
100
    }
 
101
 
 
102
  return p;
 
103
}
 
104
 
 
105
static void
 
106
scan (void)
 
107
{
 
108
  auto int dev_iterate (struct grub_ieee1275_devalias *alias);
 
109
 
 
110
  int dev_iterate (struct grub_ieee1275_devalias *alias)
 
111
    {
 
112
      struct ofdisk_hash_ent *op;
 
113
 
 
114
      grub_dprintf ("disk", "device name = %s type = %s\n", alias->name,
 
115
                    alias->type);
 
116
 
 
117
      if (grub_strcmp (alias->type, "block") != 0)
 
118
        return 0;
 
119
 
 
120
      grub_dprintf ("disk", "disk name = %s\n", alias->name);
 
121
 
 
122
      op = ofdisk_hash_find (alias->path);
 
123
      if (!op)
 
124
        {
 
125
          char *name = grub_strdup (alias->name);
 
126
          if (!name)
 
127
            {
 
128
              grub_errno = GRUB_ERR_NONE;
 
129
              return 0;
 
130
            }
 
131
          op = ofdisk_hash_add (name);
 
132
        }
 
133
      return 0;
 
134
    }
 
135
 
 
136
  grub_devalias_iterate (dev_iterate);
 
137
  grub_ieee1275_devices_iterate (dev_iterate);
 
138
}
 
139
 
 
140
static int
 
141
grub_ofdisk_iterate (int (*hook) (const char *name))
 
142
{
 
143
  unsigned i;
 
144
  scan ();
 
145
  
 
146
  for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
 
147
    {
 
148
      static struct ofdisk_hash_ent *ent;
 
149
      for (ent = ofdisk_hash[i]; ent; ent = ent->next)
 
150
        {
 
151
          if (!ent->shortest)
 
152
            continue;
 
153
          if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
 
154
            {
 
155
              grub_ieee1275_phandle_t dev;
 
156
              char tmp[8];
 
157
 
 
158
              if (grub_ieee1275_finddevice (ent->devpath, &dev))
 
159
                {
 
160
                  grub_dprintf ("disk", "finddevice (%s) failed\n",
 
161
                                ent->devpath);
 
162
                  continue;
 
163
                }
 
164
 
 
165
              if (grub_ieee1275_get_property (dev, "iconname", tmp,
 
166
                                              sizeof tmp, 0))
 
167
                {
 
168
                  grub_dprintf ("disk", "get iconname failed\n");
 
169
                  continue;
 
170
                }
 
171
 
 
172
              if (grub_strcmp (tmp, "sdmmc") != 0)
 
173
                {
 
174
                  grub_dprintf ("disk", "device is not an SD card\n");
 
175
                  continue;
 
176
                }
 
177
            }
 
178
 
 
179
          if (grub_strncmp (ent->shortest, "cdrom", 5) == 0)
 
180
            continue;
 
181
 
 
182
          if (hook (ent->shortest))
 
183
            return 1;
 
184
        }
 
185
    }     
 
186
  return 0;
 
187
}
 
188
 
 
189
static char *
 
190
compute_dev_path (const char *name)
 
191
{
 
192
  char *devpath = grub_malloc (grub_strlen (name) + 3);
 
193
  char *p, c;
 
194
 
 
195
  if (!devpath)
 
196
    return NULL;
 
197
 
 
198
  /* Un-escape commas. */
 
199
  p = devpath;
 
200
  while ((c = *name++) != '\0')
 
201
    {
 
202
      if (c == '\\' && *name == ',')
 
203
        {
 
204
          *p++ = ',';
 
205
          name++;
 
206
        }
 
207
      else
 
208
        *p++ = c;
 
209
    }
 
210
 
 
211
  *p++ = '\0';
 
212
 
 
213
  return devpath;
 
214
}
 
215
 
 
216
static grub_err_t
 
217
grub_ofdisk_open (const char *name, grub_disk_t disk)
 
218
{
 
219
  grub_ieee1275_phandle_t dev;
 
220
  char *devpath;
 
221
  /* XXX: This should be large enough for any possible case.  */
 
222
  char prop[64];
 
223
  grub_ssize_t actual;
 
224
 
 
225
  devpath = compute_dev_path (name);
 
226
  if (! devpath)
 
227
    return grub_errno;
 
228
 
 
229
  grub_dprintf ("disk", "Opening `%s'.\n", devpath);
 
230
 
 
231
  if (grub_ieee1275_finddevice (devpath, &dev))
 
232
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties");
 
233
 
 
234
  if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
 
235
                                  &actual))
 
236
    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
 
237
 
 
238
  if (grub_strcmp (prop, "block"))
 
239
    return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
 
240
 
 
241
  /* XXX: There is no property to read the number of blocks.  There
 
242
     should be a property `#blocks', but it is not there.  Perhaps it
 
243
     is possible to use seek for this.  */
 
244
  disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
 
245
 
 
246
  {
 
247
    struct ofdisk_hash_ent *op;
 
248
    op = ofdisk_hash_find (devpath);
 
249
    if (!op)
 
250
      op = ofdisk_hash_add (devpath);
 
251
    else
 
252
      grub_free (devpath);
 
253
    if (!op)
 
254
      return grub_errno;
 
255
    disk->id = (unsigned long) op;
 
256
    disk->data = op->devpath;
 
257
  }
 
258
 
 
259
  return 0;
 
260
}
 
261
 
 
262
static void
 
263
grub_ofdisk_close (grub_disk_t disk)
 
264
{
 
265
  if (disk->data == last_devpath)
 
266
    {
 
267
      if (last_ihandle)
 
268
        grub_ieee1275_close (last_ihandle);
 
269
      last_ihandle = 0;
 
270
      last_devpath = NULL;
 
271
    }
 
272
  disk->data = 0;
 
273
}
 
274
 
 
275
static grub_err_t
 
276
grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
 
277
                  grub_size_t size, char *buf)
 
278
{
 
279
  grub_ssize_t status, actual;
 
280
  unsigned long long pos;
 
281
 
 
282
  if (disk->data != last_devpath)
 
283
    {
 
284
      if (last_ihandle)
 
285
        grub_ieee1275_close (last_ihandle);
 
286
      last_ihandle = 0;
 
287
      last_devpath = NULL;
 
288
 
 
289
      if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
 
290
        {
 
291
          char name2[grub_strlen (disk->data) + 3];
 
292
          char *p;
 
293
          
 
294
          grub_strcpy (name2, disk->data);
 
295
          p = name2 + grub_strlen (name2);
 
296
          *p++ = ':';
 
297
          *p++ = '0';
 
298
          *p = 0;
 
299
          grub_ieee1275_open (name2, &last_ihandle);
 
300
        }
 
301
      else
 
302
        grub_ieee1275_open (disk->data, &last_ihandle);
 
303
      if (! last_ihandle)
 
304
        return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
 
305
      last_devpath = disk->data;      
 
306
    }
 
307
 
 
308
  pos = sector * 512UL;
 
309
 
 
310
  grub_ieee1275_seek (last_ihandle, pos, &status);
 
311
  if (status < 0)
 
312
    return grub_error (GRUB_ERR_READ_ERROR,
 
313
                       "seek error, can't seek block %llu",
 
314
                       (long long) sector);
 
315
  grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual);
 
316
  if (actual != (grub_ssize_t) (size * 512UL))
 
317
    return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu",
 
318
                       (long long) sector);
 
319
 
 
320
  return 0;
 
321
}
 
322
 
 
323
static grub_err_t
 
324
grub_ofdisk_write (grub_disk_t disk __attribute ((unused)),
 
325
                   grub_disk_addr_t sector __attribute ((unused)),
 
326
                   grub_size_t size __attribute ((unused)),
 
327
                   const char *buf __attribute ((unused)))
 
328
{
 
329
  return GRUB_ERR_NOT_IMPLEMENTED_YET;
 
330
}
 
331
 
 
332
static struct grub_disk_dev grub_ofdisk_dev =
 
333
  {
 
334
    .name = "ofdisk",
 
335
    .id = GRUB_DISK_DEVICE_OFDISK_ID,
 
336
    .iterate = grub_ofdisk_iterate,
 
337
    .open = grub_ofdisk_open,
 
338
    .close = grub_ofdisk_close,
 
339
    .read = grub_ofdisk_read,
 
340
    .write = grub_ofdisk_write,
 
341
    .next = 0
 
342
  };
 
343
 
 
344
void
 
345
grub_ofdisk_init (void)
 
346
{
 
347
  grub_disk_dev_register (&grub_ofdisk_dev);
 
348
}
 
349
 
 
350
void
 
351
grub_ofdisk_fini (void)
 
352
{
 
353
  if (last_ihandle)
 
354
    grub_ieee1275_close (last_ihandle);
 
355
  last_ihandle = 0;
 
356
  last_devpath = NULL;
 
357
 
 
358
  grub_disk_dev_unregister (&grub_ofdisk_dev);
 
359
}