~ubuntu-branches/ubuntu/quantal/grub2/quantal

« back to all changes in this revision

Viewing changes to debian/patches/ubuntu_efi_device_discovery.patch

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-04-17 16:11:45 UTC
  • Revision ID: package-import@ubuntu.com-20120417161145-p8qeqx5p9t9fs08t
Tags: 1.99-21ubuntu3
Backport several upstream EFI device discovery patches to fix boot
failures (LP: #975061).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Description: Several EFI device discovery patches to fix boot failures
 
2
 Move compare_device_paths to an externally-visible function.
 
3
 .
 
4
 Fix off-by-one error.
 
5
 .
 
6
 Accept whole disk declared as partition.
 
7
 .
 
8
 Fix incorrect memory usage.
 
9
 .
 
10
 Remove unreachable code.
 
11
 .
 
12
 Simplify root device discovery and don't fail when trying to open incorrect
 
13
 devices.
 
14
Author: Vladimir Serbinenko <phcoder@gmail.com>
 
15
Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3375
 
16
Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3383
 
17
Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3652
 
18
Origin: backport, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/3781
 
19
Bug-Ubuntu: https://bugs.launchpad.net/bugs/975061
 
20
Forwarded: not-needed
 
21
Last-Update: 2012-04-17
 
22
 
 
23
Index: b/grub-core/disk/efi/efidisk.c
 
24
===================================================================
 
25
--- a/grub-core/disk/efi/efidisk.c
 
26
+++ b/grub-core/disk/efi/efidisk.c
 
27
@@ -84,54 +84,6 @@
 
28
   return p;
 
29
 }
 
30
 
 
31
-/* Compare device paths.  */
 
32
-static int
 
33
-compare_device_paths (const grub_efi_device_path_t *dp1,
 
34
-                     const grub_efi_device_path_t *dp2)
 
35
-{
 
36
-  if (! dp1 || ! dp2)
 
37
-    /* Return non-zero.  */
 
38
-    return 1;
 
39
-
 
40
-  while (1)
 
41
-    {
 
42
-      grub_efi_uint8_t type1, type2;
 
43
-      grub_efi_uint8_t subtype1, subtype2;
 
44
-      grub_efi_uint16_t len1, len2;
 
45
-      int ret;
 
46
-
 
47
-      type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
 
48
-      type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
 
49
-
 
50
-      if (type1 != type2)
 
51
-       return (int) type2 - (int) type1;
 
52
-
 
53
-      subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
 
54
-      subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
 
55
-
 
56
-      if (subtype1 != subtype2)
 
57
-       return (int) subtype1 - (int) subtype2;
 
58
-
 
59
-      len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
 
60
-      len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
 
61
-
 
62
-      if (len1 != len2)
 
63
-       return (int) len1 - (int) len2;
 
64
-
 
65
-      ret = grub_memcmp (dp1, dp2, len1);
 
66
-      if (ret != 0)
 
67
-       return ret;
 
68
-
 
69
-      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
 
70
-       break;
 
71
-
 
72
-      dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
 
73
-      dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
 
74
-    }
 
75
-
 
76
-  return 0;
 
77
-}
 
78
-
 
79
 static struct grub_efidisk_data *
 
80
 make_devices (void)
 
81
 {
 
82
@@ -214,7 +166,7 @@
 
83
       if (parent == d)
 
84
        continue;
 
85
 
 
86
-      if (compare_device_paths (parent->device_path, dp) == 0)
 
87
+      if (grub_efi_compare_device_paths (parent->device_path, dp) == 0)
 
88
        {
 
89
          /* Found.  */
 
90
          if (! parent->last_device_path)
 
91
@@ -249,7 +201,7 @@
 
92
       ldp->length[0] = sizeof (*ldp);
 
93
       ldp->length[1] = 0;
 
94
 
 
95
-      if (compare_device_paths (dp, d->device_path) == 0)
 
96
+      if (grub_efi_compare_device_paths (dp, d->device_path) == 0)
 
97
        if (hook (p))
 
98
          {
 
99
            grub_free (dp);
 
100
@@ -273,11 +225,11 @@
 
101
     {
 
102
       int ret;
 
103
 
 
104
-      ret = compare_device_paths (find_last_device_path ((*p)->device_path),
 
105
-                                 find_last_device_path (d->device_path));
 
106
+      ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
 
107
+                                          find_last_device_path (d->device_path));
 
108
       if (ret == 0)
 
109
-       ret = compare_device_paths ((*p)->device_path,
 
110
-                                   d->device_path);
 
111
+       ret = grub_efi_compare_device_paths ((*p)->device_path,
 
112
+                                            d->device_path);
 
113
       if (ret == 0)
 
114
        return;
 
115
       else if (ret > 0)
 
116
@@ -530,7 +482,7 @@
 
117
      and total sectors should be replaced with total blocks.  */
 
118
   grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
 
119
                m, (unsigned long long) m->last_block, m->block_size);
 
120
-  disk->total_sectors = m->last_block;
 
121
+  disk->total_sectors = m->last_block + 1;
 
122
   if (m->block_size & (m->block_size - 1) || !m->block_size)
 
123
     return grub_error (GRUB_ERR_IO, "invalid sector size %d",
 
124
                       m->block_size);
 
125
@@ -703,10 +655,52 @@
 
126
   return 0;
 
127
 }
 
128
 
 
129
+#define NEEDED_BUFLEN sizeof ("XdXXXXXXXXXX")
 
130
+static inline int
 
131
+get_diskname_from_path_real (const grub_efi_device_path_t *path,
 
132
+                            struct grub_efidisk_data *head,
 
133
+                            char *buf)
 
134
+{
 
135
+  int count = 0;
 
136
+  struct grub_efidisk_data *d;
 
137
+  for (d = head, count = 0; d; d = d->next, count++)
 
138
+    if (grub_efi_compare_device_paths (d->device_path, path) == 0)
 
139
+      {
 
140
+       grub_snprintf (buf, NEEDED_BUFLEN - 1, "d%d", count);
 
141
+       return 1;
 
142
+      }
 
143
+  return 0;
 
144
+}
 
145
+
 
146
+static inline int
 
147
+get_diskname_from_path (const grub_efi_device_path_t *path,
 
148
+                       char *buf)
 
149
+{
 
150
+  if (get_diskname_from_path_real (path, hd_devices, buf + 1))
 
151
+    {
 
152
+      buf[0] = 'h';
 
153
+      return 1;
 
154
+    }
 
155
+
 
156
+  if (get_diskname_from_path_real (path, fd_devices, buf + 1))
 
157
+    {
 
158
+      buf[0] = 'f';
 
159
+      return 1;
 
160
+    }
 
161
+
 
162
+  if (get_diskname_from_path_real (path, cd_devices, buf + 1))
 
163
+    {
 
164
+      buf[0] = 'c';
 
165
+      return 1;
 
166
+    }
 
167
+  return 0;
 
168
+}
 
169
+
 
170
 char *
 
171
 grub_efidisk_get_device_name (grub_efi_handle_t *handle)
 
172
 {
 
173
   grub_efi_device_path_t *dp, *ldp;
 
174
+  char device_name[NEEDED_BUFLEN];
 
175
 
 
176
   dp = grub_efi_get_device_path (handle);
 
177
   if (! dp)
 
178
@@ -720,39 +714,13 @@
 
179
       && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
 
180
          == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
 
181
     {
 
182
-      /* This is a hard disk partition.  */
 
183
-      grub_disk_t parent = 0;
 
184
-      grub_partition_t tpart = NULL;
 
185
-      char *device_name;
 
186
+      char *partition_name = NULL;
 
187
+      char *dev_name;
 
188
       grub_efi_device_path_t *dup_dp, *dup_ldp;
 
189
       grub_efi_hard_drive_device_path_t hd;
 
190
-      auto int find_parent_disk (const char *name);
 
191
-      auto int find_partition (grub_disk_t disk, const grub_partition_t part);
 
192
-
 
193
-      /* Find the disk which is the parent of a given hard disk partition.  */
 
194
-      int find_parent_disk (const char *name)
 
195
-       {
 
196
-         grub_disk_t disk;
 
197
-
 
198
-         disk = grub_disk_open (name);
 
199
-         if (! disk)
 
200
-           return 1;
 
201
-
 
202
-         if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
 
203
-           {
 
204
-             struct grub_efidisk_data *d;
 
205
-
 
206
-             d = disk->data;
 
207
-             if (compare_device_paths (d->device_path, dup_dp) == 0)
 
208
-               {
 
209
-                 parent = disk;
 
210
-                 return 1;
 
211
-               }
 
212
-           }
 
213
+      grub_disk_t parent = 0;
 
214
 
 
215
-         grub_disk_close (disk);
 
216
-         return 0;
 
217
-       }
 
218
+      auto int find_partition (grub_disk_t disk, const grub_partition_t part);
 
219
 
 
220
       /* Find the identical partition.  */
 
221
       int find_partition (grub_disk_t disk __attribute__ ((unused)),
 
222
@@ -761,7 +729,7 @@
 
223
          if (grub_partition_get_start (part) == hd.partition_start
 
224
              && grub_partition_get_len (part) == hd.partition_size)
 
225
            {
 
226
-             tpart = part;
 
227
+             partition_name = grub_partition_get_name (part);
 
228
              return 1;
 
229
            }
 
230
 
 
231
@@ -780,7 +748,9 @@
 
232
       dup_ldp->length[0] = sizeof (*dup_ldp);
 
233
       dup_ldp->length[1] = 0;
 
234
 
 
235
-      grub_efidisk_iterate (find_parent_disk);
 
236
+      if (!get_diskname_from_path (dup_dp, device_name))
 
237
+       return 0;
 
238
+      parent = grub_disk_open (device_name);
 
239
       grub_free (dup_dp);
 
240
 
 
241
       if (! parent)
 
242
@@ -788,58 +758,33 @@
 
243
 
 
244
       /* Find a partition which matches the hard drive device path.  */
 
245
       grub_memcpy (&hd, ldp, sizeof (hd));
 
246
-      grub_partition_iterate (parent, find_partition);
 
247
-
 
248
-      if (! tpart)
 
249
+      if (hd.partition_start == 0
 
250
+         && hd.partition_size == grub_disk_get_size (parent))
 
251
        {
 
252
-         grub_disk_close (parent);
 
253
-         return 0;
 
254
+         dev_name = grub_strdup (parent->name);
 
255
        }
 
256
-
 
257
-      {
 
258
-       char *partition_name = grub_partition_get_name (tpart);
 
259
-       device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
 
260
-       grub_free (partition_name);
 
261
-      }
 
262
-      grub_disk_close (parent);
 
263
-
 
264
-      return device_name;
 
265
-    }
 
266
-  else
 
267
-    {
 
268
-      /* This should be an entire disk.  */
 
269
-      auto int find_disk (const char *name);
 
270
-      char *device_name = 0;
 
271
-
 
272
-      int find_disk (const char *name)
 
273
+      else
 
274
        {
 
275
-         grub_disk_t disk;
 
276
-
 
277
-         disk = grub_disk_open (name);
 
278
-         if (! disk)
 
279
-           return 1;
 
280
+         grub_partition_iterate (parent, find_partition);
 
281
 
 
282
-         if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
 
283
+         if (! partition_name)
 
284
            {
 
285
-             struct grub_efidisk_data *d;
 
286
-
 
287
-             d = disk->data;
 
288
-             if (compare_device_paths (d->device_path, dp) == 0)
 
289
-               {
 
290
-                 device_name = grub_strdup (disk->name);
 
291
-                 grub_disk_close (disk);
 
292
-                 return 1;
 
293
-               }
 
294
+             grub_disk_close (parent);
 
295
+             return 0;
 
296
            }
 
297
 
 
298
-         grub_disk_close (disk);
 
299
-         return 0;
 
300
-
 
301
+         dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
 
302
+         grub_free (partition_name);
 
303
        }
 
304
+      grub_disk_close (parent);
 
305
 
 
306
-      grub_efidisk_iterate (find_disk);
 
307
-      return device_name;
 
308
+      return dev_name;
 
309
+    }
 
310
+  else
 
311
+    {
 
312
+      /* This should be an entire disk.  */
 
313
+      if (!get_diskname_from_path (dp, device_name))
 
314
+       return 0;
 
315
+      return grub_strdup (device_name);
 
316
     }
 
317
-
 
318
-  return 0;
 
319
 }
 
320
Index: b/grub-core/kern/efi/efi.c
 
321
===================================================================
 
322
--- a/grub-core/kern/efi/efi.c
 
323
+++ b/grub-core/kern/efi/efi.c
 
324
@@ -740,3 +740,51 @@
 
325
       dp = (grub_efi_device_path_t *) ((char *) dp + len);
 
326
     }
 
327
 }
 
328
+
 
329
+/* Compare device paths.  */
 
330
+int
 
331
+grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
 
332
+                              const grub_efi_device_path_t *dp2)
 
333
+{
 
334
+  if (! dp1 || ! dp2)
 
335
+    /* Return non-zero.  */
 
336
+    return 1;
 
337
+
 
338
+  while (1)
 
339
+    {
 
340
+      grub_efi_uint8_t type1, type2;
 
341
+      grub_efi_uint8_t subtype1, subtype2;
 
342
+      grub_efi_uint16_t len1, len2;
 
343
+      int ret;
 
344
+
 
345
+      type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
 
346
+      type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
 
347
+
 
348
+      if (type1 != type2)
 
349
+       return (int) type2 - (int) type1;
 
350
+
 
351
+      subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
 
352
+      subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
 
353
+
 
354
+      if (subtype1 != subtype2)
 
355
+       return (int) subtype1 - (int) subtype2;
 
356
+
 
357
+      len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
 
358
+      len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
 
359
+
 
360
+      if (len1 != len2)
 
361
+       return (int) len1 - (int) len2;
 
362
+
 
363
+      ret = grub_memcmp (dp1, dp2, len1);
 
364
+      if (ret != 0)
 
365
+       return ret;
 
366
+
 
367
+      if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
 
368
+       break;
 
369
+
 
370
+      dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
 
371
+      dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
 
372
+    }
 
373
+
 
374
+  return 0;
 
375
+}
 
376
Index: b/include/grub/efi/efi.h
 
377
===================================================================
 
378
--- a/include/grub/efi/efi.h
 
379
+++ b/include/grub/efi/efi.h
 
380
@@ -62,6 +62,10 @@
 
381
                                                           grub_efi_uint32_t descriptor_version,
 
382
                                                           grub_efi_memory_descriptor_t *virtual_map);
 
383
 
 
384
+int
 
385
+EXPORT_FUNC (grub_efi_compare_device_paths) (const grub_efi_device_path_t *dp1,
 
386
+                                            const grub_efi_device_path_t *dp2);
 
387
+
 
388
 void grub_efi_mm_init (void);
 
389
 void grub_efi_mm_fini (void);
 
390
 void grub_efi_init (void);