1 /* ofpath.c - calculate OpenFirmware path names given an OS device */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2009 Free Software Foundation, Inc.
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.
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.
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/>.
20 #undef OFPATH_STANDALONE
22 #ifndef OFPATH_STANDALONE
23 #include <grub/types.h>
24 #include <grub/util/misc.h>
25 #include <grub/util/ofpath.h>
34 #include <sys/types.h>
41 #ifdef OFPATH_STANDALONE
42 #define xmalloc malloc
44 grub_util_error (const char *fmt
, ...)
48 fprintf (stderr
, "ofpath: error: ");
50 vfprintf (stderr
, fmt
, ap
);
59 kill_trailing_dir(char *path
)
61 char *end
= path
+ strlen(path
) - 1;
76 trim_newline (char *path
)
78 char *end
= path
+ strlen(path
) - 1;
84 #define OF_PATH_MAX 256
87 find_obppath(char *of_path
, const char *sysfs_path_orig
)
89 char *sysfs_path
, *path
;
91 sysfs_path
= xmalloc (PATH_MAX
);
92 path
= xmalloc (PATH_MAX
);
94 strcpy(sysfs_path
, sysfs_path_orig
);
99 snprintf(path
, PATH_MAX
, "%s/obppath", sysfs_path
);
101 printf("Trying %s\n", path
);
104 fd
= open(path
, O_RDONLY
);
107 kill_trailing_dir(sysfs_path
);
108 if (!strcmp(sysfs_path
, "/sys"))
109 grub_util_error("'obppath' not found in parent dirs of %s",
113 memset(of_path
, 0, OF_PATH_MAX
);
114 read(fd
, of_path
, OF_PATH_MAX
);
117 trim_newline(of_path
);
126 block_device_get_sysfs_path_and_link(const char *devicenode
,
127 char *sysfs_path
, int sysfs_path_len
)
129 char *rpath
= xmalloc (PATH_MAX
);
131 snprintf(sysfs_path
, sysfs_path_len
, "/sys/block/%s", devicenode
);
133 if (!realpath (sysfs_path
, rpath
))
134 grub_util_error ("cannot get the real path of `%s'", sysfs_path
);
136 strcat(rpath
, "/device");
138 if (!realpath (rpath
, sysfs_path
))
139 grub_util_error ("cannot get the real path of `%s'", rpath
);
145 trailing_digits (const char *p
)
149 end
= p
+ strlen(p
) - 1;
161 __of_path_common(char *of_path
, char *sysfs_path
,
162 const char *device
, int devno
)
164 const char *digit_string
;
167 find_obppath(of_path
, sysfs_path
);
169 digit_string
= trailing_digits (device
);
170 if (*digit_string
== '\0')
172 sprintf(disk
, "/disk@%d", devno
);
178 sscanf(digit_string
, "%d", &part
);
179 sprintf(disk
, "/disk@%d:%c", devno
, 'a' + (part
- 1));
181 strcat(of_path
, disk
);
185 get_basename(char *p
)
200 of_path_of_vdisk(char *of_path
,
201 const char *devname
__attribute__((unused
)),
203 const char *devnode
__attribute__((unused
)),
204 const char *devicenode
)
206 char *sysfs_path
, *p
;
209 sysfs_path
= xmalloc (PATH_MAX
);
210 block_device_get_sysfs_path_and_link(devicenode
,
211 sysfs_path
, PATH_MAX
);
212 p
= get_basename (sysfs_path
);
213 sscanf(p
, "vdc-port-%d-%d", &devno
, &junk
);
214 __of_path_common(of_path
, sysfs_path
, device
, devno
);
220 of_path_of_ide(char *of_path
,
221 const char *devname
__attribute__((unused
)), const char *device
,
222 const char *devnode
__attribute__((unused
)),
223 const char *devicenode
)
225 char *sysfs_path
, *p
;
228 sysfs_path
= xmalloc (PATH_MAX
);
229 block_device_get_sysfs_path_and_link(devicenode
,
230 sysfs_path
, PATH_MAX
);
231 p
= get_basename (sysfs_path
);
232 sscanf(p
, "%d.%d", &chan
, &devno
);
234 __of_path_common(of_path
, sysfs_path
, device
, devno
);
240 vendor_is_ATA(const char *path
)
245 buf
= xmalloc (PATH_MAX
);
247 snprintf(buf
, PATH_MAX
, "%s/vendor", path
);
248 fd
= open(buf
, O_RDONLY
);
250 grub_util_error ("cannot open 'vendor' node of `%s'", path
);
252 memset(buf
, 0, PATH_MAX
);
253 err
= read(fd
, buf
, PATH_MAX
);
255 grub_util_error ("cannot read 'vendor' node of `%s'", path
);
261 if (!strncmp(buf
, "ATA", 3))
267 check_sas (char *sysfs_path
, int *tgt
)
269 char *ed
= strstr (sysfs_path
, "end_device");
277 /* SAS devices are identified using disk@$PHY_ID */
278 p
= strdup (sysfs_path
);
279 ed
= strstr(p
, "end_device");
282 while (*q
&& *q
!= '/')
286 path
= xmalloc (PATH_MAX
);
287 sprintf (path
, "%s/sas_device:%s/phy_identifier", p
, ed
);
289 fd
= open(path
, O_RDONLY
);
291 grub_util_error("cannot open SAS PHY ID `%s'\n", path
);
293 memset (phy
, 0, sizeof (phy
));
294 read (fd
, phy
, sizeof (phy
));
296 sscanf (phy
, "%d", tgt
);
303 of_path_of_scsi(char *of_path
,
304 const char *devname
__attribute__((unused
)), const char *device
,
305 const char *devnode
__attribute__((unused
)),
306 const char *devicenode
)
308 const char *p
, *digit_string
, *disk_name
;
309 int host
, bus
, tgt
, lun
;
310 char *sysfs_path
, disk
[64];
312 sysfs_path
= xmalloc (PATH_MAX
);
314 block_device_get_sysfs_path_and_link(devicenode
,
315 sysfs_path
, PATH_MAX
);
316 p
= get_basename (sysfs_path
);
317 sscanf(p
, "%d:%d:%d:%d", &host
, &bus
, &tgt
, &lun
);
318 check_sas (sysfs_path
, &tgt
);
320 if (vendor_is_ATA(sysfs_path
))
322 __of_path_common(of_path
, sysfs_path
, device
, tgt
);
327 find_obppath(of_path
, sysfs_path
);
330 if (strstr (of_path
, "qlc"))
331 strcat (of_path
, "/fp@0,0");
333 if (strstr (of_path
, "sbus"))
338 digit_string
= trailing_digits (device
);
339 if (*digit_string
== '\0')
341 sprintf(disk
, "/%s@%x,%d", disk_name
, tgt
, lun
);
347 sscanf(digit_string
, "%d", &part
);
348 sprintf(disk
, "/%s@%x,%d:%c", disk_name
, tgt
, lun
, 'a' + (part
- 1));
350 strcat(of_path
, disk
);
354 strip_trailing_digits (const char *p
)
359 end
= new + strlen(new) - 1;
371 grub_util_devname_to_ofpath (char *devname
)
373 char *name_buf
, *device
, *devnode
, *devicenode
, *ofpath
;
375 name_buf
= xmalloc (PATH_MAX
);
376 name_buf
= realpath (devname
, name_buf
);
378 grub_util_error ("cannot get the real path of `%s'", devname
);
380 device
= get_basename (devname
);
381 devnode
= strip_trailing_digits (devname
);
382 devicenode
= strip_trailing_digits (device
);
384 ofpath
= xmalloc (OF_PATH_MAX
);
386 if (device
[0] == 'h' && device
[1] == 'd')
387 of_path_of_ide(ofpath
, name_buf
, device
, devnode
, devicenode
);
388 else if (device
[0] == 's'
389 && (device
[1] == 'd' || device
[1] == 'r'))
390 of_path_of_scsi(ofpath
, name_buf
, device
, devnode
, devicenode
);
391 else if (device
[0] == 'v' && device
[1] == 'd' && device
[2] == 'i'
392 && device
[3] == 's' && device
[4] == 'k')
393 of_path_of_vdisk(ofpath
, name_buf
, device
, devnode
, devicenode
);
402 #ifdef OFPATH_STANDALONE
403 int main(int argc
, char **argv
)
409 printf("Usage: grub-ofpathname DEVICE\n");
413 of_path
= grub_util_devname_to_ofpath (argv
[1]);
414 printf("%s\n", of_path
);