~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to util/ieee1275/ofpath.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-09-13 18:02:04 UTC
  • mfrom: (1.17.15 upstream)
  • mto: (17.6.27 experimental)
  • mto: This revision was merged to the branch mainline in revision 145.
  • Revision ID: package-import@ubuntu.com-20120913180204-mojnmocbimlom4im
Tags: upstream-2.00
ImportĀ upstreamĀ versionĀ 2.00

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include <grub/types.h>
24
24
#include <grub/util/misc.h>
25
25
#include <grub/util/ofpath.h>
 
26
#include <grub/i18n.h>
26
27
#endif
27
28
 
28
29
#include <limits.h>
33
34
#include <string.h>
34
35
#include <sys/types.h>
35
36
#include <sys/stat.h>
36
 
#include <malloc.h>
37
37
#include <fcntl.h>
38
38
#include <errno.h>
39
39
#include <ctype.h>
53
53
  exit (1);
54
54
}
55
55
 
 
56
void
 
57
grub_util_info (const char *fmt, ...)
 
58
{
 
59
  va_list ap;
 
60
 
 
61
  fprintf (stderr, "ofpath: info: ");
 
62
  va_start (ap, fmt);
 
63
  vfprintf (stderr, fmt, ap);
 
64
  va_end (ap);
 
65
  fputc ('\n', stderr);
 
66
}
 
67
 
 
68
#define grub_util_warn grub_util_info
 
69
#define _(x) x
 
70
#define xstrdup strdup
56
71
#endif
57
72
 
58
73
static void
81
96
    *end-- = '\0';
82
97
}
83
98
 
84
 
#define OF_PATH_MAX     256
 
99
#define MAX_DISK_CAT    64
85
100
 
86
 
static void
87
 
find_obppath(char *of_path, const char *sysfs_path_orig)
 
101
static char *
 
102
find_obppath (const char *sysfs_path_orig)
88
103
{
89
104
  char *sysfs_path, *path;
90
 
 
91
 
  sysfs_path = xmalloc (PATH_MAX);
92
 
  path = xmalloc (PATH_MAX);
93
 
 
94
 
  strcpy(sysfs_path, sysfs_path_orig);
 
105
  size_t path_size = strlen (sysfs_path_orig) + sizeof ("/obppath");
 
106
 
 
107
  sysfs_path = xstrdup (sysfs_path_orig);
 
108
  path = xmalloc (path_size);
 
109
 
95
110
  while (1)
96
111
    {
97
112
      int fd;
 
113
      char *of_path;
 
114
      struct stat st;
 
115
      size_t size;
98
116
 
99
 
      snprintf(path, PATH_MAX, "%s/obppath", sysfs_path);
 
117
      snprintf(path, path_size, "%s/obppath", sysfs_path);
100
118
#if 0
101
119
      printf("Trying %s\n", path);
102
120
#endif
103
121
 
104
122
      fd = open(path, O_RDONLY);
105
 
      if (fd < 0)
 
123
      if (fd < 0 || fstat (fd, &st) < 0)
 
124
        {
 
125
          snprintf(path, path_size, "%s/devspec", sysfs_path);
 
126
          fd = open(path, O_RDONLY);
 
127
        }
 
128
 
 
129
      if (fd < 0 || fstat (fd, &st) < 0)
106
130
        {
107
131
          kill_trailing_dir(sysfs_path);
108
132
          if (!strcmp(sysfs_path, "/sys"))
109
 
            grub_util_error("'obppath' not found in parent dirs of %s",
110
 
                            sysfs_path_orig);
 
133
            {
 
134
              grub_util_info (_("'obppath' not found in parent dirs of %s,"
 
135
                                " no IEEE1275 name discovery"),
 
136
                              sysfs_path_orig);
 
137
              free (path);
 
138
              free (sysfs_path);
 
139
              return NULL;
 
140
            }
111
141
          continue;
112
142
        }
113
 
      memset(of_path, 0, OF_PATH_MAX);
114
 
      read(fd, of_path, OF_PATH_MAX);
 
143
      size = st.st_size;
 
144
      of_path = xmalloc (size + MAX_DISK_CAT + 1);
 
145
      memset(of_path, 0, size + MAX_DISK_CAT + 1);
 
146
      read(fd, of_path, size);
115
147
      close(fd);
116
148
 
117
149
      trim_newline(of_path);
118
 
      break;
 
150
      free (path);
 
151
      free (sysfs_path);
 
152
      return of_path;
119
153
    }
120
 
 
121
 
  free (path);
122
 
  free (sysfs_path);
123
 
}
124
 
 
125
 
static void
126
 
block_device_get_sysfs_path_and_link(const char *devicenode,
127
 
                                     char *sysfs_path, int sysfs_path_len)
128
 
{
129
 
  char *rpath = xmalloc (PATH_MAX);
130
 
 
131
 
  snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode);
132
 
 
133
 
  if (!realpath (sysfs_path, rpath))
134
 
    grub_util_error ("cannot get the real path of `%s'", sysfs_path);
135
 
 
136
 
  strcat(rpath, "/device");
137
 
 
138
 
  if (!realpath (rpath, sysfs_path))
139
 
    grub_util_error ("cannot get the real path of `%s'", rpath);
140
 
 
 
154
}
 
155
 
 
156
static char *
 
157
xrealpath (const char *in)
 
158
{
 
159
  char *out;
 
160
#ifdef PATH_MAX
 
161
  out = xmalloc (PATH_MAX);
 
162
  out = realpath (in, out);
 
163
#else
 
164
  out = realpath (in, NULL);
 
165
#endif
 
166
  if (!out)
 
167
    grub_util_error (_("failed to get canonical path of %s"), in);
 
168
  return out;
 
169
}
 
170
 
 
171
static char *
 
172
block_device_get_sysfs_path_and_link(const char *devicenode)
 
173
{
 
174
  char *rpath;
 
175
  char *rpath2;
 
176
  char *ret;
 
177
  size_t tmp_size = strlen (devicenode) + sizeof ("/sys/block/");
 
178
  char *tmp = xmalloc (tmp_size);
 
179
 
 
180
  memcpy (tmp, "/sys/block/", sizeof ("/sys/block/"));
 
181
  strcat (tmp, devicenode);
 
182
 
 
183
  rpath = xrealpath (tmp);
 
184
  rpath2 = xmalloc (strlen (rpath) + sizeof ("/device"));
 
185
  strcpy (rpath2, rpath);
 
186
  strcat (rpath2, "/device");
 
187
 
 
188
  ret = xrealpath (rpath2);
 
189
 
 
190
  free (tmp);
141
191
  free (rpath);
 
192
  free (rpath2);
 
193
  return ret;
 
194
}
 
195
 
 
196
static inline int
 
197
my_isdigit (int c)
 
198
{
 
199
  return (c >= '0' && c <= '9');
142
200
}
143
201
 
144
202
static const char *
149
207
  end = p + strlen(p) - 1;
150
208
  while (end >= p)
151
209
    {
152
 
      if (! isdigit(*end))
 
210
      if (! my_isdigit(*end))
153
211
        break;
154
212
      end--;
155
213
    }
157
215
  return end + 1;
158
216
}
159
217
 
160
 
static void
161
 
__of_path_common(char *of_path, char *sysfs_path,
 
218
static char *
 
219
__of_path_common(char *sysfs_path,
162
220
                 const char *device, int devno)
163
221
{
164
222
  const char *digit_string;
165
 
  char disk[64];
 
223
  char disk[MAX_DISK_CAT];
 
224
  char *of_path = find_obppath(sysfs_path);
166
225
 
167
 
  find_obppath(of_path, sysfs_path);
 
226
  if (!of_path)
 
227
    return NULL;
168
228
 
169
229
  digit_string = trailing_digits (device);
170
230
  if (*digit_string == '\0')
171
231
    {
172
 
      sprintf(disk, "/disk@%d", devno);
 
232
      snprintf(disk, sizeof (disk), "/disk@%d", devno);
173
233
    }
174
234
  else
175
235
    {
176
236
      int part;
177
237
 
178
238
      sscanf(digit_string, "%d", &part);
179
 
      sprintf(disk, "/disk@%d:%c", devno, 'a' + (part - 1));
 
239
      snprintf(disk, sizeof (disk), "/disk@%d:%c", devno, 'a' + (part - 1));
180
240
    }
181
241
  strcat(of_path, disk);
 
242
  return of_path;
182
243
}
183
244
 
184
245
static char *
196
257
  return ret;
197
258
}
198
259
 
199
 
static void
200
 
of_path_of_vdisk(char *of_path,
201
 
                 const char *devname __attribute__((unused)),
 
260
static char *
 
261
of_path_of_vdisk(const char *sys_devname __attribute__((unused)),
202
262
                 const char *device,
203
263
                 const char *devnode __attribute__((unused)),
204
264
                 const char *devicenode)
205
265
{
206
266
  char *sysfs_path, *p;
207
267
  int devno, junk;
 
268
  char *ret;
208
269
 
209
 
  sysfs_path = xmalloc (PATH_MAX);
210
 
  block_device_get_sysfs_path_and_link(devicenode,
211
 
                                       sysfs_path, PATH_MAX);
 
270
  sysfs_path = block_device_get_sysfs_path_and_link(devicenode);
212
271
  p = get_basename (sysfs_path);
213
272
  sscanf(p, "vdc-port-%d-%d", &devno, &junk);
214
 
  __of_path_common(of_path, sysfs_path, device, devno);
 
273
  ret = __of_path_common (sysfs_path, device, devno);
215
274
 
216
275
  free (sysfs_path);
 
276
  return ret;
217
277
}
218
278
 
219
 
static void
220
 
of_path_of_ide(char *of_path,
221
 
               const char *devname __attribute__((unused)), const char *device,
 
279
static char *
 
280
of_path_of_ide(const char *sys_devname __attribute__((unused)), const char *device,
222
281
               const char *devnode __attribute__((unused)),
223
282
               const char *devicenode)
224
283
{
225
284
  char *sysfs_path, *p;
226
285
  int chan, devno;
 
286
  char *ret;
227
287
 
228
 
  sysfs_path = xmalloc (PATH_MAX);
229
 
  block_device_get_sysfs_path_and_link(devicenode,
230
 
                                       sysfs_path, PATH_MAX);
 
288
  sysfs_path = block_device_get_sysfs_path_and_link(devicenode);
231
289
  p = get_basename (sysfs_path);
232
290
  sscanf(p, "%d.%d", &chan, &devno);
233
291
 
234
 
  __of_path_common(of_path, sysfs_path, device, devno);
 
292
  ret = __of_path_common(sysfs_path, device, 2 * chan + devno);
235
293
 
236
294
  free (sysfs_path);
 
295
  return ret;
237
296
}
238
297
 
239
298
static int
240
299
vendor_is_ATA(const char *path)
241
300
{
242
301
  int fd, err;
243
 
  char *buf;
244
 
 
245
 
  buf = xmalloc (PATH_MAX);
246
 
 
247
 
  snprintf(buf, PATH_MAX, "%s/vendor", path);
248
 
  fd = open(buf, O_RDONLY);
 
302
  char *bufname;
 
303
  char bufcont[3];
 
304
  size_t path_size;
 
305
 
 
306
  path_size = strlen (path) + sizeof ("/vendor");
 
307
 
 
308
  bufname = xmalloc (path_size);
 
309
 
 
310
  snprintf (bufname, path_size, "%s/vendor", path);
 
311
  fd = open (bufname, O_RDONLY);
249
312
  if (fd < 0)
250
 
    grub_util_error ("cannot open 'vendor' node of `%s'", path);
 
313
    grub_util_error (_("cannot open `%s': %s"), bufname, strerror (errno));
251
314
 
252
 
  memset(buf, 0, PATH_MAX);
253
 
  err = read(fd, buf, PATH_MAX);
 
315
  memset(bufcont, 0, sizeof (bufcont));
 
316
  err = read(fd, bufcont, sizeof (bufcont));
254
317
  if (err < 0)
255
 
    grub_util_error ("cannot read 'vendor' node of `%s'", path);
 
318
    grub_util_error (_("cannot open `%s': %s"), bufname, strerror (errno));
256
319
 
257
320
  close(fd);
258
 
 
259
 
  free (buf);
260
 
 
261
 
  if (!strncmp(buf, "ATA", 3))
262
 
    return 1;
263
 
  return 0;
 
321
  free (bufname);
 
322
 
 
323
  return (memcmp(bufcont, "ATA", 3) == 0);
264
324
}
265
325
 
266
326
static void
270
330
  char *p, *q, *path;
271
331
  char phy[16];
272
332
  int fd;
 
333
  size_t path_size;
273
334
 
274
335
  if (!ed)
275
336
    return;
283
344
    q++;
284
345
  *q = '\0';
285
346
 
286
 
  path = xmalloc (PATH_MAX);
287
 
  sprintf (path, "%s/sas_device:%s/phy_identifier", p, ed);
 
347
  path_size = (strlen (p) + strlen (ed)
 
348
               + sizeof ("%s/sas_device/%s/phy_identifier"));
 
349
  path = xmalloc (path_size);
 
350
  snprintf (path, path_size, "%s/sas_device/%s/phy_identifier", p, ed);
288
351
 
289
 
  fd = open(path, O_RDONLY);
 
352
  fd = open (path, O_RDONLY);
290
353
  if (fd < 0)
291
 
    grub_util_error("cannot open SAS PHY ID `%s'\n", path);
 
354
    grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
292
355
 
293
356
  memset (phy, 0, sizeof (phy));
294
357
  read (fd, phy, sizeof (phy));
297
360
 
298
361
  free (path);
299
362
  free (p);
 
363
  close (fd);
300
364
}
301
365
 
302
 
static void
303
 
of_path_of_scsi(char *of_path,
304
 
                const char *devname __attribute__((unused)), const char *device,
 
366
static char *
 
367
of_path_of_scsi(const char *sys_devname __attribute__((unused)), const char *device,
305
368
                const char *devnode __attribute__((unused)),
306
369
                const char *devicenode)
307
370
{
308
371
  const char *p, *digit_string, *disk_name;
309
372
  int host, bus, tgt, lun;
310
 
  char *sysfs_path, disk[64];
311
 
 
312
 
  sysfs_path = xmalloc (PATH_MAX);
313
 
 
314
 
  block_device_get_sysfs_path_and_link(devicenode,
315
 
                                       sysfs_path, PATH_MAX);
 
373
  char *sysfs_path, disk[MAX_DISK_CAT - sizeof ("/fp@0,0")];
 
374
  char *of_path;
 
375
 
 
376
  sysfs_path = block_device_get_sysfs_path_and_link(devicenode);
316
377
  p = get_basename (sysfs_path);
317
378
  sscanf(p, "%d:%d:%d:%d", &host, &bus, &tgt, &lun);
318
379
  check_sas (sysfs_path, &tgt);
319
380
 
320
381
  if (vendor_is_ATA(sysfs_path))
321
382
    {
322
 
      __of_path_common(of_path, sysfs_path, device, tgt);
 
383
      of_path = __of_path_common(sysfs_path, device, tgt);
323
384
      free (sysfs_path);
324
 
      return;
 
385
      return of_path;
325
386
    }
326
387
 
327
 
  find_obppath(of_path, sysfs_path);
 
388
  of_path = find_obppath(sysfs_path);
328
389
  free (sysfs_path);
 
390
  if (!of_path)
 
391
    return NULL;
329
392
 
330
393
  if (strstr (of_path, "qlc"))
331
394
    strcat (of_path, "/fp@0,0");
336
399
    disk_name = "disk";
337
400
 
338
401
  digit_string = trailing_digits (device);
339
 
  if (*digit_string == '\0')
 
402
  if (strncmp (of_path, "/vdevice/", sizeof ("/vdevice/") - 1) == 0)
340
403
    {
341
 
      sprintf(disk, "/%s@%x,%d", disk_name, tgt, lun);
 
404
      unsigned long id = 0x8000 | (tgt << 8) | (bus << 5) | lun;
 
405
      if (*digit_string == '\0')
 
406
        {
 
407
          snprintf(disk, sizeof (disk), "/%s@%04lx000000000000", disk_name, id);
 
408
        }
 
409
      else
 
410
        {
 
411
          int part;
 
412
 
 
413
          sscanf(digit_string, "%d", &part);
 
414
          snprintf(disk, sizeof (disk),
 
415
                   "/%s@%04lx000000000000:%c", disk_name, id, 'a' + (part - 1));
 
416
        }
342
417
    }
343
418
  else
344
419
    {
345
 
      int part;
 
420
      if (*digit_string == '\0')
 
421
        {
 
422
          snprintf(disk, sizeof (disk), "/%s@%x,%d", disk_name, tgt, lun);
 
423
        }
 
424
      else
 
425
        {
 
426
          int part;
346
427
 
347
 
      sscanf(digit_string, "%d", &part);
348
 
      sprintf(disk, "/%s@%x,%d:%c", disk_name, tgt, lun, 'a' + (part - 1));
 
428
          sscanf(digit_string, "%d", &part);
 
429
          snprintf(disk, sizeof (disk),
 
430
                   "/%s@%x,%d:%c", disk_name, tgt, lun, 'a' + (part - 1));
 
431
        }
349
432
    }
350
433
  strcat(of_path, disk);
 
434
  return of_path;
351
435
}
352
436
 
353
437
static char *
359
443
  end = new + strlen(new) - 1;
360
444
  while (end >= new)
361
445
    {
362
 
      if (! isdigit(*end))
 
446
      if (! my_isdigit(*end))
363
447
        break;
364
448
      *end-- = '\0';
365
449
    }
368
452
}
369
453
 
370
454
char *
371
 
grub_util_devname_to_ofpath (const char *devname)
 
455
grub_util_devname_to_ofpath (const char *sys_devname)
372
456
{
373
457
  char *name_buf, *device, *devnode, *devicenode, *ofpath;
374
458
 
375
 
  name_buf = xmalloc (PATH_MAX);
376
 
  name_buf = realpath (devname, name_buf);
377
 
  if (! name_buf)
378
 
    grub_util_error ("cannot get the real path of `%s'", devname);
 
459
  name_buf = xrealpath (sys_devname);
379
460
 
380
461
  device = get_basename (name_buf);
381
462
  devnode = strip_trailing_digits (name_buf);
382
463
  devicenode = strip_trailing_digits (device);
383
464
 
384
 
  ofpath = xmalloc (OF_PATH_MAX);
385
 
 
386
465
  if (device[0] == 'h' && device[1] == 'd')
387
 
    of_path_of_ide(ofpath, name_buf, device, devnode, devicenode);
 
466
    ofpath = of_path_of_ide(name_buf, device, devnode, devicenode);
388
467
  else if (device[0] == 's'
389
468
           && (device[1] == 'd' || device[1] == 'r'))
390
 
    of_path_of_scsi(ofpath, name_buf, device, devnode, devicenode);
 
469
    ofpath = of_path_of_scsi(name_buf, device, devnode, devicenode);
391
470
  else if (device[0] == 'v' && device[1] == 'd' && device[2] == 'i'
392
471
           && device[3] == 's' && device[4] == 'k')
393
 
    of_path_of_vdisk(ofpath, name_buf, device, devnode, devicenode);
 
472
    ofpath = of_path_of_vdisk(name_buf, device, devnode, devicenode);
394
473
  else if (device[0] == 'f' && device[1] == 'd'
395
474
           && device[2] == '0' && device[3] == '\0')
396
475
    /* All the models I've seen have a devalias "floppy".
397
476
       New models have no floppy at all. */
398
 
    strcpy (ofpath, "floppy");
 
477
    ofpath = xstrdup ("floppy");
399
478
  else
400
 
    grub_util_error ("unknown device type %s\n", device);
 
479
    {
 
480
      grub_util_warn (_("unknown device type %s\n"), device);
 
481
      return NULL;
 
482
    }
401
483
 
402
484
  free (devnode);
403
485
  free (devicenode);
413
495
 
414
496
  if (argc != 2)
415
497
    {
416
 
      printf("Usage: grub-ofpathname DEVICE\n");
 
498
      printf(_("Usage: %s DEVICE\n"), argv[0]);
417
499
      return 1;
418
500
    }
419
501
 
420
502
  of_path = grub_util_devname_to_ofpath (argv[1]);
421
 
  printf("%s\n", of_path);
 
503
  if (of_path)
 
504
    printf("%s\n", of_path);
 
505
  free (of_path);
422
506
 
423
507
  return 0;
424
508
}